From 0292059f4a16434600564cfa3f0ad2309a508a54 Mon Sep 17 00:00:00 2001 From: tpearson Date: Wed, 24 Feb 2010 17:43:19 +0000 Subject: Added libksquirrel for KDE3 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/libraries/libksquirrel@1095624 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kernel/Makefile.am | 123 + kernel/generate | 223 + kernel/include/fmt_codec_avs.h | 39 + kernel/include/fmt_codec_bmp.h | 46 + kernel/include/fmt_codec_cd_func.h | 35 + kernel/include/fmt_codec_cut.h | 38 + kernel/include/fmt_codec_dds.h | 39 + kernel/include/fmt_codec_fli.h | 42 + kernel/include/fmt_codec_gif.h | 45 + kernel/include/fmt_codec_hdr.h | 42 + kernel/include/fmt_codec_ico.h | 43 + kernel/include/fmt_codec_iff.h | 41 + kernel/include/fmt_codec_jbig.h | 34 + kernel/include/fmt_codec_jpeg.h | 48 + kernel/include/fmt_codec_jpeg2000.h | 51 + kernel/include/fmt_codec_koala.h | 39 + kernel/include/fmt_codec_lif.h | 39 + kernel/include/fmt_codec_mac.h | 37 + kernel/include/fmt_codec_mdl.h | 40 + kernel/include/fmt_codec_mng.h | 51 + kernel/include/fmt_codec_msp.h | 41 + kernel/include/fmt_codec_mtv.h | 39 + kernel/include/fmt_codec_openexr.h | 45 + kernel/include/fmt_codec_pcx.h | 40 + kernel/include/fmt_codec_pix.h | 34 + kernel/include/fmt_codec_png.h | 63 + kernel/include/fmt_codec_pnm.h | 48 + kernel/include/fmt_codec_psd.h | 41 + kernel/include/fmt_codec_psp.h | 53 + kernel/include/fmt_codec_pxr.h | 34 + kernel/include/fmt_codec_ras.h | 43 + kernel/include/fmt_codec_rawrgb.h | 40 + kernel/include/fmt_codec_sct.h | 37 + kernel/include/fmt_codec_sgi.h | 40 + kernel/include/fmt_codec_sun.h | 38 + kernel/include/fmt_codec_tga.h | 40 + kernel/include/fmt_codec_tiff.h | 46 + kernel/include/fmt_codec_ttf.h | 34 + kernel/include/fmt_codec_utah.h | 38 + kernel/include/fmt_codec_wal.h | 39 + kernel/include/fmt_codec_wbmp.h | 49 + kernel/include/fmt_codec_wmf.h | 39 + kernel/include/fmt_codec_xbm.h | 40 + kernel/include/fmt_codec_xcur.h | 43 + kernel/include/fmt_codec_xpm.h | 44 + kernel/include/fmt_codec_xwd.h | 38 + kernel/include/ksquirrel-libs/error.h | 49 + kernel/include/ksquirrel-libs/fileio.h | 73 + kernel/include/ksquirrel-libs/fmt_codec_base.h | 258 + kernel/include/ksquirrel-libs/fmt_defs.h | 242 + kernel/include/ksquirrel-libs/fmt_types.h | 36 + kernel/include/ksquirrel-libs/fmt_utils.h | 64 + kernel/include/ksquirrel-libs/settings.h | 69 + kernel/kls_avs/Makefile.am | 9 + kernel/kls_avs/fmt_codec_avs.cpp | 207 + kernel/kls_avs/fmt_codec_avs_defs.h | 27 + kernel/kls_bmp/Makefile.am | 9 + kernel/kls_bmp/fmt_codec_bmp.cpp | 445 ++ kernel/kls_bmp/fmt_codec_bmp_defs.h | 58 + kernel/kls_camera/Makefile.am | 39 + kernel/kls_camera/dcraw.c | 8269 ++++++++++++++++++++++++ kernel/kls_camera/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_camera/fmt_codec_pnm_defs.h | 64 + kernel/kls_camera/ksquirrel-libs-camera2ppm.in | 20 + kernel/kls_camera/libkls_camera.so.ui | 1023 +++ kernel/kls_cut/Makefile.am | 9 + kernel/kls_cut/fmt_codec_cut.cpp | 173 + kernel/kls_cut/fmt_codec_cut_defs.h | 25 + kernel/kls_dds/Makefile.am | 9 + kernel/kls_dds/dds.cpp | 1066 +++ kernel/kls_dds/dds.h | 36 + kernel/kls_dds/fmt_codec_dds.cpp | 143 + kernel/kls_dds/fmt_codec_dds_defs.h | 27 + kernel/kls_dicom/Makefile.am | 15 + kernel/kls_dicom/fmt_codec_png.cpp | 655 ++ kernel/kls_dicom/fmt_codec_png_defs.h | 27 + kernel/kls_dicom/ksquirrel-libs-dicom2png.in | 3 + kernel/kls_djvu/Makefile.am | 17 + kernel/kls_djvu/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_djvu/fmt_codec_pnm_defs.h | 64 + kernel/kls_djvu/libkls_djvu.so.ui | 195 + kernel/kls_dxf/Makefile.am | 17 + kernel/kls_dxf/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_dxf/fmt_codec_pnm_defs.h | 64 + kernel/kls_dxf/libkls_dxf.so.ui | 192 + kernel/kls_eps/Makefile.am | 11 + kernel/kls_eps/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_eps/fmt_codec_pnm_defs.h | 64 + kernel/kls_fig/Makefile.am | 15 + kernel/kls_fig/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_fig/fmt_codec_pnm_defs.h | 64 + kernel/kls_fig/ksquirrel-libs-fig2ppm.in | 3 + kernel/kls_fli/Makefile.am | 9 + kernel/kls_fli/fmt_codec_fli.cpp | 449 ++ kernel/kls_fli/fmt_codec_fli_defs.h | 92 + kernel/kls_gif/Makefile.am | 9 + kernel/kls_gif/fmt_codec_gif.cpp | 516 ++ kernel/kls_gif/fmt_codec_gif_defs.h | 32 + kernel/kls_hdr/Makefile.am | 9 + kernel/kls_hdr/fmt_codec_hdr.cpp | 332 + kernel/kls_hdr/fmt_codec_hdr_defs.h | 32 + kernel/kls_ico/Makefile.am | 9 + kernel/kls_ico/fmt_codec_ico.cpp | 296 + kernel/kls_ico/fmt_codec_ico_defs.h | 63 + kernel/kls_iff/Makefile.am | 15 + kernel/kls_iff/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_iff/fmt_codec_pnm_defs.h | 64 + kernel/kls_iff/ksquirrel-libs-iff2ppm.in | 3 + kernel/kls_jbig/Makefile.am | 11 + kernel/kls_jbig/fmt_codec_jbig.cpp | 148 + kernel/kls_jbig/fmt_codec_jbig_defs.h | 27 + kernel/kls_jbig/jbig2mem.cpp | 270 + kernel/kls_jbig/jbig2mem.h | 6 + kernel/kls_jbig/libjbig/ANNOUNCE | 147 + kernel/kls_jbig/libjbig/COPYING | 339 + kernel/kls_jbig/libjbig/Makefile.am | 5 + kernel/kls_jbig/libjbig/jbig.c | 3190 +++++++++ kernel/kls_jbig/libjbig/jbig.h | 270 + kernel/kls_jbig/libjbig/jbig_tab.c | 428 ++ kernel/kls_jpeg/Makefile.am | 9 + kernel/kls_jpeg/fmt_codec_jpeg.cpp | 308 + kernel/kls_jpeg/fmt_codec_jpeg_defs.h | 42 + kernel/kls_jpeg2000/Makefile.am | 9 + kernel/kls_jpeg2000/fmt_codec_jpeg2000.cpp | 277 + kernel/kls_jpeg2000/fmt_codec_jpeg2000_defs.h | 28 + kernel/kls_koala/Makefile.am | 9 + kernel/kls_koala/fmt_codec_koala.cpp | 207 + kernel/kls_koala/fmt_codec_koala_defs.h | 39 + kernel/kls_leaf/Makefile.am | 15 + kernel/kls_leaf/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_leaf/fmt_codec_pnm_defs.h | 64 + kernel/kls_leaf/ksquirrel-libs-leaf2ppm.in | 3 + kernel/kls_lif/Makefile.am | 9 + kernel/kls_lif/fmt_codec_lif.cpp | 155 + kernel/kls_lif/fmt_codec_lif_defs.h | 41 + kernel/kls_ljpeg/Makefile.am | 17 + kernel/kls_ljpeg/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_ljpeg/fmt_codec_pnm_defs.h | 64 + kernel/kls_ljpeg/ksquirrel-libs-ljpeg2ppm-s.in | 18 + kernel/kls_ljpeg/ljpeg2ppm/Copyright | 79 + kernel/kls_ljpeg/ljpeg2ppm/Makefile.am | 5 + kernel/kls_ljpeg/ljpeg2ppm/huffd.c | 665 ++ kernel/kls_ljpeg/ljpeg2ppm/io.h | 105 + kernel/kls_ljpeg/ljpeg2ppm/jpeg.h | 249 + kernel/kls_ljpeg/ljpeg2ppm/ljpgtopnm.c | 263 + kernel/kls_ljpeg/ljpeg2ppm/mcu.c | 125 + kernel/kls_ljpeg/ljpeg2ppm/mcu.h | 63 + kernel/kls_ljpeg/ljpeg2ppm/predictor.c | 189 + kernel/kls_ljpeg/ljpeg2ppm/predictor.h | 176 + kernel/kls_ljpeg/ljpeg2ppm/proto.h | 75 + kernel/kls_ljpeg/ljpeg2ppm/read.c | 665 ++ kernel/kls_ljpeg/ljpeg2ppm/util.c | 297 + kernel/kls_mac/Makefile.am | 15 + kernel/kls_mac/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_mac/fmt_codec_pnm_defs.h | 64 + kernel/kls_mac/ksquirrel-libs-mac2ppm.in | 3 + kernel/kls_mdl/Makefile.am | 9 + kernel/kls_mdl/fmt_codec_mdl.cpp | 171 + kernel/kls_mdl/fmt_codec_mdl_defs.h | 35 + kernel/kls_mng/Makefile.am | 9 + kernel/kls_mng/fmt_codec_mng.cpp | 372 ++ kernel/kls_mng/fmt_codec_mng_defs.h | 27 + kernel/kls_msp/Makefile.am | 9 + kernel/kls_msp/fmt_codec_msp.cpp | 228 + kernel/kls_msp/fmt_codec_msp_defs.h | 49 + kernel/kls_mtv/Makefile.am | 9 + kernel/kls_mtv/fmt_codec_mtv.cpp | 196 + kernel/kls_mtv/fmt_codec_mtv_defs.h | 27 + kernel/kls_neo/Makefile.am | 15 + kernel/kls_neo/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_neo/fmt_codec_pnm_defs.h | 64 + kernel/kls_neo/ksquirrel-libs-neo2ppm.in | 3 + kernel/kls_openexr/Makefile.am | 11 + kernel/kls_openexr/fmt_codec_openexr.cpp | 303 + kernel/kls_openexr/fmt_codec_openexr_defs.h | 27 + kernel/kls_pcx/Makefile.am | 9 + kernel/kls_pcx/fmt_codec_pcx.cpp | 256 + kernel/kls_pcx/fmt_codec_pcx_defs.h | 48 + kernel/kls_pi1/Makefile.am | 15 + kernel/kls_pi1/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_pi1/fmt_codec_pnm_defs.h | 64 + kernel/kls_pi1/ksquirrel-libs-pi12ppm.in | 3 + kernel/kls_pi3/Makefile.am | 15 + kernel/kls_pi3/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_pi3/fmt_codec_pnm_defs.h | 64 + kernel/kls_pi3/ksquirrel-libs-pi32ppm.in | 3 + kernel/kls_pict/Makefile.am | 15 + kernel/kls_pict/fmt_codec_pnm.cpp | 1469 +++++ kernel/kls_pict/fmt_codec_pnm_defs.h | 64 + kernel/kls_pict/ksquirrel-libs-pict2ppm.in | 3 + kernel/kls_pix/Makefile.am | 9 + kernel/kls_pix/fmt_codec_pix.cpp | 156 + kernel/kls_pix/fmt_codec_pix_defs.h | 36 + kernel/kls_png/Makefile.am | 15 + kernel/kls_png/README | 2 + kernel/kls_png/fmt_codec_png.cpp | 655 ++ kernel/kls_png/fmt_codec_png_defs.h | 27 + kernel/kls_png/ksquirrel-libs-png/Makefile.am | 8 + kernel/kls_png/ksquirrel-libs-png/png.c | 792 +++ kernel/kls_png/ksquirrel-libs-png/png.h | 3672 +++++++++++ kernel/kls_png/ksquirrel-libs-png/pngconf.h | 1490 +++++ kernel/kls_png/ksquirrel-libs-png/pngerror.c | 341 + kernel/kls_png/ksquirrel-libs-png/pnggccrd.c | 101 + kernel/kls_png/ksquirrel-libs-png/pngget.c | 1062 +++ kernel/kls_png/ksquirrel-libs-png/pnghack.h | 409 ++ kernel/kls_png/ksquirrel-libs-png/pngmem.c | 608 ++ kernel/kls_png/ksquirrel-libs-png/pngpread.c | 1773 +++++ kernel/kls_png/ksquirrel-libs-png/pngread.c | 1604 +++++ kernel/kls_png/ksquirrel-libs-png/pngrio.c | 167 + kernel/kls_png/ksquirrel-libs-png/pngrtran.c | 4284 ++++++++++++ kernel/kls_png/ksquirrel-libs-png/pngrutil.c | 3392 ++++++++++ kernel/kls_png/ksquirrel-libs-png/pngset.c | 1383 ++++ kernel/kls_png/ksquirrel-libs-png/pngtest.c | 1551 +++++ kernel/kls_png/ksquirrel-libs-png/pngtrans.c | 662 ++ kernel/kls_png/ksquirrel-libs-png/pngvcrd.c | 1 + kernel/kls_png/ksquirrel-libs-png/pngwio.c | 234 + kernel/kls_png/ksquirrel-libs-png/pngwrite.c | 1549 +++++ kernel/kls_png/ksquirrel-libs-png/pngwtran.c | 572 ++ kernel/kls_png/ksquirrel-libs-png/pngwutil.c | 2920 +++++++++ kernel/kls_pnm/Makefile.am | 11 + kernel/kls_pnm/fmt_codec_pnm.cpp | 1469 +++++ kernel/kls_pnm/fmt_codec_pnm_defs.h | 64 + kernel/kls_psd/Makefile.am | 9 + kernel/kls_psd/fmt_codec_psd.cpp | 394 ++ kernel/kls_psd/fmt_codec_psd_defs.h | 43 + kernel/kls_psp/Makefile.am | 9 + kernel/kls_psp/fmt_codec_psp.cpp | 635 ++ kernel/kls_psp/fmt_codec_psp_defs.h | 249 + kernel/kls_pxr/Makefile.am | 9 + kernel/kls_pxr/fmt_codec_pxr.cpp | 173 + kernel/kls_pxr/fmt_codec_pxr_defs.h | 25 + kernel/kls_ras/Makefile.am | 9 + kernel/kls_ras/fmt_codec_ras.cpp | 361 ++ kernel/kls_ras/fmt_codec_ras_defs.h | 54 + kernel/kls_rawrgb/Makefile.am | 9 + kernel/kls_rawrgb/fmt_codec_rawrgb.cpp | 229 + kernel/kls_rawrgb/fmt_codec_rawrgb_defs.h | 27 + kernel/kls_sct/Makefile.am | 9 + kernel/kls_sct/fmt_codec_sct.cpp | 232 + kernel/kls_sct/fmt_codec_sct_defs.h | 51 + kernel/kls_sgi/Makefile.am | 9 + kernel/kls_sgi/fmt_codec_sgi.cpp | 341 + kernel/kls_sgi/fmt_codec_sgi_defs.h | 50 + kernel/kls_sun/Makefile.am | 9 + kernel/kls_sun/fmt_codec_sun.cpp | 235 + kernel/kls_sun/fmt_codec_sun_defs.h | 27 + kernel/kls_svg/Makefile.am | 19 + kernel/kls_svg/fmt_codec_png.cpp | 655 ++ kernel/kls_svg/fmt_codec_png_defs.h | 27 + kernel/kls_svg/ksquirrel-libs-svg2png.in | 20 + kernel/kls_svg/libkls_svg.so.ui | 120 + kernel/kls_tga/Makefile.am | 9 + kernel/kls_tga/fmt_codec_tga.cpp | 411 ++ kernel/kls_tga/fmt_codec_tga_defs.h | 70 + kernel/kls_tiff/Makefile.am | 17 + kernel/kls_tiff/fmt_codec_tiff.cpp | 298 + kernel/kls_tiff/fmt_codec_tiff_defs.h | 27 + kernel/kls_tiff/libkls_tiff.so.ui | 135 + kernel/kls_ttf/Makefile.am | 19 + kernel/kls_ttf/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_ttf/fmt_codec_pnm_defs.h | 64 + kernel/kls_ttf/ftcommon.cpp | 1333 ++++ kernel/kls_ttf/ftcommon.h | 307 + kernel/kls_ttf/ftview/Makefile.am | 9 + kernel/kls_ttf/ftview/README | 1 + kernel/kls_ttf/ftview/gblany.h | 133 + kernel/kls_ttf/ftview/gblblit.cpp | 318 + kernel/kls_ttf/ftview/gblblit.h | 82 + kernel/kls_ttf/ftview/gblcolor.h | 56 + kernel/kls_ttf/ftview/gblender.cpp | 381 ++ kernel/kls_ttf/ftview/gblender.h | 216 + kernel/kls_ttf/ftview/gblhbgr.h | 74 + kernel/kls_ttf/ftview/gblhrgb.h | 76 + kernel/kls_ttf/ftview/gblvbgr.h | 76 + kernel/kls_ttf/ftview/gblvrgb.h | 76 + kernel/kls_ttf/ftview/graph.h | 653 ++ kernel/kls_ttf/ftview/grblit.cpp | 2068 ++++++ kernel/kls_ttf/ftview/grblit.h | 25 + kernel/kls_ttf/ftview/grconfig.h | 9 + kernel/kls_ttf/ftview/grevents.h | 117 + kernel/kls_ttf/ftview/grfont.cpp | 373 ++ kernel/kls_ttf/ftview/grfont.h | 17 + kernel/kls_ttf/ftview/grobjs.cpp | 213 + kernel/kls_ttf/ftview/grobjs.h | 182 + kernel/kls_ttf/ftview/grtypes.h | 52 + kernel/kls_ttf/ttf2pnm.cpp | 187 + kernel/kls_utah/Makefile.am | 15 + kernel/kls_utah/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_utah/fmt_codec_pnm_defs.h | 64 + kernel/kls_utah/ksquirrel-libs-utah2ppm.in | 3 + kernel/kls_wal/Makefile.am | 9 + kernel/kls_wal/fmt_codec_wal.cpp | 172 + kernel/kls_wal/fmt_codec_wal_defs.h | 42 + kernel/kls_wal/q2pal.h | 266 + kernel/kls_wbmp/Makefile.am | 9 + kernel/kls_wbmp/fmt_codec_wbmp.cpp | 278 + kernel/kls_wbmp/fmt_codec_wbmp_defs.h | 37 + kernel/kls_wmf/Makefile.am | 9 + kernel/kls_wmf/fmt_codec_wmf.cpp | 150 + kernel/kls_wmf/fmt_codec_wmf_defs.h | 25 + kernel/kls_wmf/wmf2mem.cpp | 361 ++ kernel/kls_xbm/Makefile.am | 9 + kernel/kls_xbm/fmt_codec_xbm.cpp | 219 + kernel/kls_xbm/fmt_codec_xbm_defs.h | 48 + kernel/kls_xcf/Makefile.am | 18 + kernel/kls_xcf/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_xcf/fmt_codec_pnm_defs.h | 64 + kernel/kls_xcf/libkls_xcf.so.ui | 78 + kernel/kls_xcf/xcf2pnm/Makefile.am | 5 + kernel/kls_xcf/xcf2pnm/enums.c | 116 + kernel/kls_xcf/xcf2pnm/enums.h | 98 + kernel/kls_xcf/xcf2pnm/flatspec.c | 370 ++ kernel/kls_xcf/xcf2pnm/flatten.c | 689 ++ kernel/kls_xcf/xcf2pnm/flatten.h | 77 + kernel/kls_xcf/xcf2pnm/io-unix.c | 176 + kernel/kls_xcf/xcf2pnm/options.i | 410 ++ kernel/kls_xcf/xcf2pnm/pixels.c | 487 ++ kernel/kls_xcf/xcf2pnm/pixels.h | 128 + kernel/kls_xcf/xcf2pnm/scaletab.c | 42 + kernel/kls_xcf/xcf2pnm/table.c | 263 + kernel/kls_xcf/xcf2pnm/utils.c | 164 + kernel/kls_xcf/xcf2pnm/xcf-general.c | 287 + kernel/kls_xcf/xcf2pnm/xcf2pnm.c | 269 + kernel/kls_xcf/xcf2pnm/xcf2pnm.oi | 41 + kernel/kls_xcf/xcf2pnm/xcftools.h | 182 + kernel/kls_xcur/Makefile.am | 9 + kernel/kls_xcur/fmt_codec_xcur.cpp | 166 + kernel/kls_xcur/fmt_codec_xcur_defs.h | 76 + kernel/kls_xim/Makefile.am | 15 + kernel/kls_xim/fmt_codec_pnm.cpp | 1470 +++++ kernel/kls_xim/fmt_codec_pnm_defs.h | 64 + kernel/kls_xim/ksquirrel-libs-xim2ppm.in | 3 + kernel/kls_xpm/Makefile.am | 17 + kernel/kls_xpm/fmt_codec_xpm.cpp | 258 + kernel/kls_xpm/fmt_codec_xpm_defs.h | 25 + kernel/kls_xpm/rgbmap | 719 ++ kernel/kls_xpm/xpm_utils.h | 103 + kernel/kls_xwd/Makefile.am | 9 + kernel/kls_xwd/fmt_codec_xwd.cpp | 214 + kernel/kls_xwd/fmt_codec_xwd_defs.h | 27 + kernel/ksquirrel-libs/Makefile.am | 8 + kernel/ksquirrel-libs/fileio.cpp | 136 + kernel/ksquirrel-libs/fmt_utils.cpp | 187 + kernel/link | 24 + kernel/plusx | 3 + kernel/xpm/codec_avs.xpm | 34 + kernel/xpm/codec_bmp.xpm | 34 + kernel/xpm/codec_camera.xpm | 34 + kernel/xpm/codec_cut.xpm | 34 + kernel/xpm/codec_dds.xpm | 30 + kernel/xpm/codec_dicom.xpm | 30 + kernel/xpm/codec_djvu.xpm | 31 + kernel/xpm/codec_dxf.xpm | 36 + kernel/xpm/codec_eps.xpm | 30 + kernel/xpm/codec_fig.xpm | 30 + kernel/xpm/codec_fits.xpm | 30 + kernel/xpm/codec_fli.xpm | 34 + kernel/xpm/codec_gif.xpm | 34 + kernel/xpm/codec_hdr.xpm | 34 + kernel/xpm/codec_ico.xpm | 34 + kernel/xpm/codec_iff.xpm | 34 + kernel/xpm/codec_jbig.xpm | 34 + kernel/xpm/codec_jpeg.xpm | 34 + kernel/xpm/codec_jpeg2000.xpm | 34 + kernel/xpm/codec_koala.xpm | 34 + kernel/xpm/codec_lbm.xpm | 30 + kernel/xpm/codec_leaf.xpm | 30 + kernel/xpm/codec_lif.xpm | 34 + kernel/xpm/codec_ljpeg.xpm | 29 + kernel/xpm/codec_mac.xpm | 34 + kernel/xpm/codec_mdl.xpm | 34 + kernel/xpm/codec_mng.xpm | 34 + kernel/xpm/codec_msp.xpm | 34 + kernel/xpm/codec_mtv.xpm | 34 + kernel/xpm/codec_neo.xpm | 30 + kernel/xpm/codec_openexr.xpm | 34 + kernel/xpm/codec_pcx.xpm | 34 + kernel/xpm/codec_pi1.xpm | 30 + kernel/xpm/codec_pi3.xpm | 30 + kernel/xpm/codec_pict.xpm | 30 + kernel/xpm/codec_pix.xpm | 34 + kernel/xpm/codec_png.xpm | 34 + kernel/xpm/codec_pnm.xpm | 34 + kernel/xpm/codec_psd.xpm | 34 + kernel/xpm/codec_psp.xpm | 30 + kernel/xpm/codec_pxr.xpm | 34 + kernel/xpm/codec_ras.xpm | 34 + kernel/xpm/codec_rawrgb.xpm | 34 + kernel/xpm/codec_sct.xpm | 34 + kernel/xpm/codec_sgi.xpm | 34 + kernel/xpm/codec_sun.xpm | 34 + kernel/xpm/codec_svg.xpm | 34 + kernel/xpm/codec_tga.xpm | 34 + kernel/xpm/codec_tiff.xpm | 34 + kernel/xpm/codec_ttf.xpm | 34 + kernel/xpm/codec_utah.xpm | 34 + kernel/xpm/codec_wal.xpm | 34 + kernel/xpm/codec_wbmp.xpm | 34 + kernel/xpm/codec_wmf.xpm | 34 + kernel/xpm/codec_xbm.xpm | 34 + kernel/xpm/codec_xcf.xpm | 30 + kernel/xpm/codec_xcur.xpm | 34 + kernel/xpm/codec_xim.xpm | 30 + kernel/xpm/codec_xpm.xpm | 34 + kernel/xpm/codec_xwd.xpm | 34 + 405 files changed, 107134 insertions(+) create mode 100644 kernel/Makefile.am create mode 100755 kernel/generate create mode 100644 kernel/include/fmt_codec_avs.h create mode 100644 kernel/include/fmt_codec_bmp.h create mode 100644 kernel/include/fmt_codec_cd_func.h create mode 100644 kernel/include/fmt_codec_cut.h create mode 100644 kernel/include/fmt_codec_dds.h create mode 100644 kernel/include/fmt_codec_fli.h create mode 100644 kernel/include/fmt_codec_gif.h create mode 100644 kernel/include/fmt_codec_hdr.h create mode 100644 kernel/include/fmt_codec_ico.h create mode 100644 kernel/include/fmt_codec_iff.h create mode 100644 kernel/include/fmt_codec_jbig.h create mode 100644 kernel/include/fmt_codec_jpeg.h create mode 100644 kernel/include/fmt_codec_jpeg2000.h create mode 100644 kernel/include/fmt_codec_koala.h create mode 100644 kernel/include/fmt_codec_lif.h create mode 100644 kernel/include/fmt_codec_mac.h create mode 100644 kernel/include/fmt_codec_mdl.h create mode 100644 kernel/include/fmt_codec_mng.h create mode 100644 kernel/include/fmt_codec_msp.h create mode 100644 kernel/include/fmt_codec_mtv.h create mode 100644 kernel/include/fmt_codec_openexr.h create mode 100644 kernel/include/fmt_codec_pcx.h create mode 100644 kernel/include/fmt_codec_pix.h create mode 100644 kernel/include/fmt_codec_png.h create mode 100644 kernel/include/fmt_codec_pnm.h create mode 100644 kernel/include/fmt_codec_psd.h create mode 100644 kernel/include/fmt_codec_psp.h create mode 100644 kernel/include/fmt_codec_pxr.h create mode 100644 kernel/include/fmt_codec_ras.h create mode 100644 kernel/include/fmt_codec_rawrgb.h create mode 100644 kernel/include/fmt_codec_sct.h create mode 100644 kernel/include/fmt_codec_sgi.h create mode 100644 kernel/include/fmt_codec_sun.h create mode 100644 kernel/include/fmt_codec_tga.h create mode 100644 kernel/include/fmt_codec_tiff.h create mode 100644 kernel/include/fmt_codec_ttf.h create mode 100644 kernel/include/fmt_codec_utah.h create mode 100644 kernel/include/fmt_codec_wal.h create mode 100644 kernel/include/fmt_codec_wbmp.h create mode 100644 kernel/include/fmt_codec_wmf.h create mode 100644 kernel/include/fmt_codec_xbm.h create mode 100644 kernel/include/fmt_codec_xcur.h create mode 100644 kernel/include/fmt_codec_xpm.h create mode 100644 kernel/include/fmt_codec_xwd.h create mode 100644 kernel/include/ksquirrel-libs/error.h create mode 100644 kernel/include/ksquirrel-libs/fileio.h create mode 100644 kernel/include/ksquirrel-libs/fmt_codec_base.h create mode 100644 kernel/include/ksquirrel-libs/fmt_defs.h create mode 100644 kernel/include/ksquirrel-libs/fmt_types.h create mode 100644 kernel/include/ksquirrel-libs/fmt_utils.h create mode 100644 kernel/include/ksquirrel-libs/settings.h create mode 100644 kernel/kls_avs/Makefile.am create mode 100644 kernel/kls_avs/fmt_codec_avs.cpp create mode 100644 kernel/kls_avs/fmt_codec_avs_defs.h create mode 100644 kernel/kls_bmp/Makefile.am create mode 100644 kernel/kls_bmp/fmt_codec_bmp.cpp create mode 100644 kernel/kls_bmp/fmt_codec_bmp_defs.h create mode 100644 kernel/kls_camera/Makefile.am create mode 100644 kernel/kls_camera/dcraw.c create mode 100644 kernel/kls_camera/fmt_codec_pnm.cpp create mode 100644 kernel/kls_camera/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_camera/ksquirrel-libs-camera2ppm.in create mode 100644 kernel/kls_camera/libkls_camera.so.ui create mode 100644 kernel/kls_cut/Makefile.am create mode 100644 kernel/kls_cut/fmt_codec_cut.cpp create mode 100644 kernel/kls_cut/fmt_codec_cut_defs.h create mode 100644 kernel/kls_dds/Makefile.am create mode 100644 kernel/kls_dds/dds.cpp create mode 100644 kernel/kls_dds/dds.h create mode 100644 kernel/kls_dds/fmt_codec_dds.cpp create mode 100644 kernel/kls_dds/fmt_codec_dds_defs.h create mode 100644 kernel/kls_dicom/Makefile.am create mode 100644 kernel/kls_dicom/fmt_codec_png.cpp create mode 100644 kernel/kls_dicom/fmt_codec_png_defs.h create mode 100644 kernel/kls_dicom/ksquirrel-libs-dicom2png.in create mode 100644 kernel/kls_djvu/Makefile.am create mode 100644 kernel/kls_djvu/fmt_codec_pnm.cpp create mode 100644 kernel/kls_djvu/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_djvu/libkls_djvu.so.ui create mode 100644 kernel/kls_dxf/Makefile.am create mode 100644 kernel/kls_dxf/fmt_codec_pnm.cpp create mode 100644 kernel/kls_dxf/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_dxf/libkls_dxf.so.ui create mode 100644 kernel/kls_eps/Makefile.am create mode 100644 kernel/kls_eps/fmt_codec_pnm.cpp create mode 100644 kernel/kls_eps/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_fig/Makefile.am create mode 100644 kernel/kls_fig/fmt_codec_pnm.cpp create mode 100644 kernel/kls_fig/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_fig/ksquirrel-libs-fig2ppm.in create mode 100644 kernel/kls_fli/Makefile.am create mode 100644 kernel/kls_fli/fmt_codec_fli.cpp create mode 100644 kernel/kls_fli/fmt_codec_fli_defs.h create mode 100644 kernel/kls_gif/Makefile.am create mode 100644 kernel/kls_gif/fmt_codec_gif.cpp create mode 100644 kernel/kls_gif/fmt_codec_gif_defs.h create mode 100644 kernel/kls_hdr/Makefile.am create mode 100644 kernel/kls_hdr/fmt_codec_hdr.cpp create mode 100644 kernel/kls_hdr/fmt_codec_hdr_defs.h create mode 100644 kernel/kls_ico/Makefile.am create mode 100644 kernel/kls_ico/fmt_codec_ico.cpp create mode 100644 kernel/kls_ico/fmt_codec_ico_defs.h create mode 100644 kernel/kls_iff/Makefile.am create mode 100644 kernel/kls_iff/fmt_codec_pnm.cpp create mode 100644 kernel/kls_iff/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_iff/ksquirrel-libs-iff2ppm.in create mode 100644 kernel/kls_jbig/Makefile.am create mode 100644 kernel/kls_jbig/fmt_codec_jbig.cpp create mode 100644 kernel/kls_jbig/fmt_codec_jbig_defs.h create mode 100644 kernel/kls_jbig/jbig2mem.cpp create mode 100644 kernel/kls_jbig/jbig2mem.h create mode 100644 kernel/kls_jbig/libjbig/ANNOUNCE create mode 100644 kernel/kls_jbig/libjbig/COPYING create mode 100644 kernel/kls_jbig/libjbig/Makefile.am create mode 100644 kernel/kls_jbig/libjbig/jbig.c create mode 100644 kernel/kls_jbig/libjbig/jbig.h create mode 100644 kernel/kls_jbig/libjbig/jbig_tab.c create mode 100644 kernel/kls_jpeg/Makefile.am create mode 100644 kernel/kls_jpeg/fmt_codec_jpeg.cpp create mode 100644 kernel/kls_jpeg/fmt_codec_jpeg_defs.h create mode 100644 kernel/kls_jpeg2000/Makefile.am create mode 100644 kernel/kls_jpeg2000/fmt_codec_jpeg2000.cpp create mode 100644 kernel/kls_jpeg2000/fmt_codec_jpeg2000_defs.h create mode 100644 kernel/kls_koala/Makefile.am create mode 100644 kernel/kls_koala/fmt_codec_koala.cpp create mode 100644 kernel/kls_koala/fmt_codec_koala_defs.h create mode 100644 kernel/kls_leaf/Makefile.am create mode 100644 kernel/kls_leaf/fmt_codec_pnm.cpp create mode 100644 kernel/kls_leaf/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_leaf/ksquirrel-libs-leaf2ppm.in create mode 100644 kernel/kls_lif/Makefile.am create mode 100644 kernel/kls_lif/fmt_codec_lif.cpp create mode 100644 kernel/kls_lif/fmt_codec_lif_defs.h create mode 100644 kernel/kls_ljpeg/Makefile.am create mode 100644 kernel/kls_ljpeg/fmt_codec_pnm.cpp create mode 100644 kernel/kls_ljpeg/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_ljpeg/ksquirrel-libs-ljpeg2ppm-s.in create mode 100644 kernel/kls_ljpeg/ljpeg2ppm/Copyright create mode 100644 kernel/kls_ljpeg/ljpeg2ppm/Makefile.am create mode 100644 kernel/kls_ljpeg/ljpeg2ppm/huffd.c create mode 100644 kernel/kls_ljpeg/ljpeg2ppm/io.h create mode 100644 kernel/kls_ljpeg/ljpeg2ppm/jpeg.h create mode 100644 kernel/kls_ljpeg/ljpeg2ppm/ljpgtopnm.c create mode 100644 kernel/kls_ljpeg/ljpeg2ppm/mcu.c create mode 100644 kernel/kls_ljpeg/ljpeg2ppm/mcu.h create mode 100644 kernel/kls_ljpeg/ljpeg2ppm/predictor.c create mode 100644 kernel/kls_ljpeg/ljpeg2ppm/predictor.h create mode 100644 kernel/kls_ljpeg/ljpeg2ppm/proto.h create mode 100644 kernel/kls_ljpeg/ljpeg2ppm/read.c create mode 100644 kernel/kls_ljpeg/ljpeg2ppm/util.c create mode 100644 kernel/kls_mac/Makefile.am create mode 100644 kernel/kls_mac/fmt_codec_pnm.cpp create mode 100644 kernel/kls_mac/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_mac/ksquirrel-libs-mac2ppm.in create mode 100644 kernel/kls_mdl/Makefile.am create mode 100644 kernel/kls_mdl/fmt_codec_mdl.cpp create mode 100644 kernel/kls_mdl/fmt_codec_mdl_defs.h create mode 100644 kernel/kls_mng/Makefile.am create mode 100644 kernel/kls_mng/fmt_codec_mng.cpp create mode 100644 kernel/kls_mng/fmt_codec_mng_defs.h create mode 100644 kernel/kls_msp/Makefile.am create mode 100644 kernel/kls_msp/fmt_codec_msp.cpp create mode 100644 kernel/kls_msp/fmt_codec_msp_defs.h create mode 100644 kernel/kls_mtv/Makefile.am create mode 100644 kernel/kls_mtv/fmt_codec_mtv.cpp create mode 100644 kernel/kls_mtv/fmt_codec_mtv_defs.h create mode 100644 kernel/kls_neo/Makefile.am create mode 100644 kernel/kls_neo/fmt_codec_pnm.cpp create mode 100644 kernel/kls_neo/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_neo/ksquirrel-libs-neo2ppm.in create mode 100644 kernel/kls_openexr/Makefile.am create mode 100644 kernel/kls_openexr/fmt_codec_openexr.cpp create mode 100644 kernel/kls_openexr/fmt_codec_openexr_defs.h create mode 100644 kernel/kls_pcx/Makefile.am create mode 100644 kernel/kls_pcx/fmt_codec_pcx.cpp create mode 100644 kernel/kls_pcx/fmt_codec_pcx_defs.h create mode 100644 kernel/kls_pi1/Makefile.am create mode 100644 kernel/kls_pi1/fmt_codec_pnm.cpp create mode 100644 kernel/kls_pi1/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_pi1/ksquirrel-libs-pi12ppm.in create mode 100644 kernel/kls_pi3/Makefile.am create mode 100644 kernel/kls_pi3/fmt_codec_pnm.cpp create mode 100644 kernel/kls_pi3/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_pi3/ksquirrel-libs-pi32ppm.in create mode 100644 kernel/kls_pict/Makefile.am create mode 100644 kernel/kls_pict/fmt_codec_pnm.cpp create mode 100644 kernel/kls_pict/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_pict/ksquirrel-libs-pict2ppm.in create mode 100644 kernel/kls_pix/Makefile.am create mode 100644 kernel/kls_pix/fmt_codec_pix.cpp create mode 100644 kernel/kls_pix/fmt_codec_pix_defs.h create mode 100644 kernel/kls_png/Makefile.am create mode 100644 kernel/kls_png/README create mode 100644 kernel/kls_png/fmt_codec_png.cpp create mode 100644 kernel/kls_png/fmt_codec_png_defs.h create mode 100644 kernel/kls_png/ksquirrel-libs-png/Makefile.am create mode 100644 kernel/kls_png/ksquirrel-libs-png/png.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/png.h create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngconf.h create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngerror.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pnggccrd.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngget.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pnghack.h create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngmem.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngpread.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngread.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngrio.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngrtran.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngrutil.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngset.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngtest.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngtrans.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngvcrd.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngwio.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngwrite.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngwtran.c create mode 100644 kernel/kls_png/ksquirrel-libs-png/pngwutil.c create mode 100644 kernel/kls_pnm/Makefile.am create mode 100644 kernel/kls_pnm/fmt_codec_pnm.cpp create mode 100644 kernel/kls_pnm/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_psd/Makefile.am create mode 100644 kernel/kls_psd/fmt_codec_psd.cpp create mode 100644 kernel/kls_psd/fmt_codec_psd_defs.h create mode 100644 kernel/kls_psp/Makefile.am create mode 100644 kernel/kls_psp/fmt_codec_psp.cpp create mode 100644 kernel/kls_psp/fmt_codec_psp_defs.h create mode 100644 kernel/kls_pxr/Makefile.am create mode 100644 kernel/kls_pxr/fmt_codec_pxr.cpp create mode 100644 kernel/kls_pxr/fmt_codec_pxr_defs.h create mode 100644 kernel/kls_ras/Makefile.am create mode 100644 kernel/kls_ras/fmt_codec_ras.cpp create mode 100644 kernel/kls_ras/fmt_codec_ras_defs.h create mode 100644 kernel/kls_rawrgb/Makefile.am create mode 100644 kernel/kls_rawrgb/fmt_codec_rawrgb.cpp create mode 100644 kernel/kls_rawrgb/fmt_codec_rawrgb_defs.h create mode 100644 kernel/kls_sct/Makefile.am create mode 100644 kernel/kls_sct/fmt_codec_sct.cpp create mode 100644 kernel/kls_sct/fmt_codec_sct_defs.h create mode 100644 kernel/kls_sgi/Makefile.am create mode 100644 kernel/kls_sgi/fmt_codec_sgi.cpp create mode 100644 kernel/kls_sgi/fmt_codec_sgi_defs.h create mode 100644 kernel/kls_sun/Makefile.am create mode 100644 kernel/kls_sun/fmt_codec_sun.cpp create mode 100644 kernel/kls_sun/fmt_codec_sun_defs.h create mode 100644 kernel/kls_svg/Makefile.am create mode 100644 kernel/kls_svg/fmt_codec_png.cpp create mode 100644 kernel/kls_svg/fmt_codec_png_defs.h create mode 100644 kernel/kls_svg/ksquirrel-libs-svg2png.in create mode 100644 kernel/kls_svg/libkls_svg.so.ui create mode 100644 kernel/kls_tga/Makefile.am create mode 100644 kernel/kls_tga/fmt_codec_tga.cpp create mode 100644 kernel/kls_tga/fmt_codec_tga_defs.h create mode 100644 kernel/kls_tiff/Makefile.am create mode 100644 kernel/kls_tiff/fmt_codec_tiff.cpp create mode 100644 kernel/kls_tiff/fmt_codec_tiff_defs.h create mode 100644 kernel/kls_tiff/libkls_tiff.so.ui create mode 100644 kernel/kls_ttf/Makefile.am create mode 100644 kernel/kls_ttf/fmt_codec_pnm.cpp create mode 100644 kernel/kls_ttf/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_ttf/ftcommon.cpp create mode 100644 kernel/kls_ttf/ftcommon.h create mode 100644 kernel/kls_ttf/ftview/Makefile.am create mode 100644 kernel/kls_ttf/ftview/README create mode 100644 kernel/kls_ttf/ftview/gblany.h create mode 100644 kernel/kls_ttf/ftview/gblblit.cpp create mode 100644 kernel/kls_ttf/ftview/gblblit.h create mode 100644 kernel/kls_ttf/ftview/gblcolor.h create mode 100644 kernel/kls_ttf/ftview/gblender.cpp create mode 100644 kernel/kls_ttf/ftview/gblender.h create mode 100644 kernel/kls_ttf/ftview/gblhbgr.h create mode 100644 kernel/kls_ttf/ftview/gblhrgb.h create mode 100644 kernel/kls_ttf/ftview/gblvbgr.h create mode 100644 kernel/kls_ttf/ftview/gblvrgb.h create mode 100644 kernel/kls_ttf/ftview/graph.h create mode 100644 kernel/kls_ttf/ftview/grblit.cpp create mode 100644 kernel/kls_ttf/ftview/grblit.h create mode 100644 kernel/kls_ttf/ftview/grconfig.h create mode 100644 kernel/kls_ttf/ftview/grevents.h create mode 100644 kernel/kls_ttf/ftview/grfont.cpp create mode 100644 kernel/kls_ttf/ftview/grfont.h create mode 100644 kernel/kls_ttf/ftview/grobjs.cpp create mode 100644 kernel/kls_ttf/ftview/grobjs.h create mode 100644 kernel/kls_ttf/ftview/grtypes.h create mode 100644 kernel/kls_ttf/ttf2pnm.cpp create mode 100644 kernel/kls_utah/Makefile.am create mode 100644 kernel/kls_utah/fmt_codec_pnm.cpp create mode 100644 kernel/kls_utah/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_utah/ksquirrel-libs-utah2ppm.in create mode 100644 kernel/kls_wal/Makefile.am create mode 100644 kernel/kls_wal/fmt_codec_wal.cpp create mode 100644 kernel/kls_wal/fmt_codec_wal_defs.h create mode 100644 kernel/kls_wal/q2pal.h create mode 100644 kernel/kls_wbmp/Makefile.am create mode 100644 kernel/kls_wbmp/fmt_codec_wbmp.cpp create mode 100644 kernel/kls_wbmp/fmt_codec_wbmp_defs.h create mode 100644 kernel/kls_wmf/Makefile.am create mode 100644 kernel/kls_wmf/fmt_codec_wmf.cpp create mode 100644 kernel/kls_wmf/fmt_codec_wmf_defs.h create mode 100644 kernel/kls_wmf/wmf2mem.cpp create mode 100644 kernel/kls_xbm/Makefile.am create mode 100644 kernel/kls_xbm/fmt_codec_xbm.cpp create mode 100644 kernel/kls_xbm/fmt_codec_xbm_defs.h create mode 100644 kernel/kls_xcf/Makefile.am create mode 100644 kernel/kls_xcf/fmt_codec_pnm.cpp create mode 100644 kernel/kls_xcf/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_xcf/libkls_xcf.so.ui create mode 100644 kernel/kls_xcf/xcf2pnm/Makefile.am create mode 100644 kernel/kls_xcf/xcf2pnm/enums.c create mode 100644 kernel/kls_xcf/xcf2pnm/enums.h create mode 100644 kernel/kls_xcf/xcf2pnm/flatspec.c create mode 100644 kernel/kls_xcf/xcf2pnm/flatten.c create mode 100644 kernel/kls_xcf/xcf2pnm/flatten.h create mode 100644 kernel/kls_xcf/xcf2pnm/io-unix.c create mode 100644 kernel/kls_xcf/xcf2pnm/options.i create mode 100644 kernel/kls_xcf/xcf2pnm/pixels.c create mode 100644 kernel/kls_xcf/xcf2pnm/pixels.h create mode 100644 kernel/kls_xcf/xcf2pnm/scaletab.c create mode 100644 kernel/kls_xcf/xcf2pnm/table.c create mode 100644 kernel/kls_xcf/xcf2pnm/utils.c create mode 100644 kernel/kls_xcf/xcf2pnm/xcf-general.c create mode 100644 kernel/kls_xcf/xcf2pnm/xcf2pnm.c create mode 100644 kernel/kls_xcf/xcf2pnm/xcf2pnm.oi create mode 100644 kernel/kls_xcf/xcf2pnm/xcftools.h create mode 100644 kernel/kls_xcur/Makefile.am create mode 100644 kernel/kls_xcur/fmt_codec_xcur.cpp create mode 100644 kernel/kls_xcur/fmt_codec_xcur_defs.h create mode 100644 kernel/kls_xim/Makefile.am create mode 100644 kernel/kls_xim/fmt_codec_pnm.cpp create mode 100644 kernel/kls_xim/fmt_codec_pnm_defs.h create mode 100644 kernel/kls_xim/ksquirrel-libs-xim2ppm.in create mode 100644 kernel/kls_xpm/Makefile.am create mode 100644 kernel/kls_xpm/fmt_codec_xpm.cpp create mode 100644 kernel/kls_xpm/fmt_codec_xpm_defs.h create mode 100644 kernel/kls_xpm/rgbmap create mode 100644 kernel/kls_xpm/xpm_utils.h create mode 100644 kernel/kls_xwd/Makefile.am create mode 100644 kernel/kls_xwd/fmt_codec_xwd.cpp create mode 100644 kernel/kls_xwd/fmt_codec_xwd_defs.h create mode 100644 kernel/ksquirrel-libs/Makefile.am create mode 100644 kernel/ksquirrel-libs/fileio.cpp create mode 100644 kernel/ksquirrel-libs/fmt_utils.cpp create mode 100755 kernel/link create mode 100755 kernel/plusx create mode 100644 kernel/xpm/codec_avs.xpm create mode 100644 kernel/xpm/codec_bmp.xpm create mode 100644 kernel/xpm/codec_camera.xpm create mode 100644 kernel/xpm/codec_cut.xpm create mode 100644 kernel/xpm/codec_dds.xpm create mode 100644 kernel/xpm/codec_dicom.xpm create mode 100644 kernel/xpm/codec_djvu.xpm create mode 100644 kernel/xpm/codec_dxf.xpm create mode 100644 kernel/xpm/codec_eps.xpm create mode 100644 kernel/xpm/codec_fig.xpm create mode 100644 kernel/xpm/codec_fits.xpm create mode 100644 kernel/xpm/codec_fli.xpm create mode 100644 kernel/xpm/codec_gif.xpm create mode 100644 kernel/xpm/codec_hdr.xpm create mode 100644 kernel/xpm/codec_ico.xpm create mode 100644 kernel/xpm/codec_iff.xpm create mode 100644 kernel/xpm/codec_jbig.xpm create mode 100644 kernel/xpm/codec_jpeg.xpm create mode 100644 kernel/xpm/codec_jpeg2000.xpm create mode 100644 kernel/xpm/codec_koala.xpm create mode 100644 kernel/xpm/codec_lbm.xpm create mode 100644 kernel/xpm/codec_leaf.xpm create mode 100644 kernel/xpm/codec_lif.xpm create mode 100644 kernel/xpm/codec_ljpeg.xpm create mode 100644 kernel/xpm/codec_mac.xpm create mode 100644 kernel/xpm/codec_mdl.xpm create mode 100644 kernel/xpm/codec_mng.xpm create mode 100644 kernel/xpm/codec_msp.xpm create mode 100644 kernel/xpm/codec_mtv.xpm create mode 100644 kernel/xpm/codec_neo.xpm create mode 100644 kernel/xpm/codec_openexr.xpm create mode 100644 kernel/xpm/codec_pcx.xpm create mode 100644 kernel/xpm/codec_pi1.xpm create mode 100644 kernel/xpm/codec_pi3.xpm create mode 100644 kernel/xpm/codec_pict.xpm create mode 100644 kernel/xpm/codec_pix.xpm create mode 100644 kernel/xpm/codec_png.xpm create mode 100644 kernel/xpm/codec_pnm.xpm create mode 100644 kernel/xpm/codec_psd.xpm create mode 100644 kernel/xpm/codec_psp.xpm create mode 100644 kernel/xpm/codec_pxr.xpm create mode 100644 kernel/xpm/codec_ras.xpm create mode 100644 kernel/xpm/codec_rawrgb.xpm create mode 100644 kernel/xpm/codec_sct.xpm create mode 100644 kernel/xpm/codec_sgi.xpm create mode 100644 kernel/xpm/codec_sun.xpm create mode 100644 kernel/xpm/codec_svg.xpm create mode 100644 kernel/xpm/codec_tga.xpm create mode 100644 kernel/xpm/codec_tiff.xpm create mode 100644 kernel/xpm/codec_ttf.xpm create mode 100644 kernel/xpm/codec_utah.xpm create mode 100644 kernel/xpm/codec_wal.xpm create mode 100644 kernel/xpm/codec_wbmp.xpm create mode 100644 kernel/xpm/codec_wmf.xpm create mode 100644 kernel/xpm/codec_xbm.xpm create mode 100644 kernel/xpm/codec_xcf.xpm create mode 100644 kernel/xpm/codec_xcur.xpm create mode 100644 kernel/xpm/codec_xim.xpm create mode 100644 kernel/xpm/codec_xpm.xpm create mode 100644 kernel/xpm/codec_xwd.xpm (limited to 'kernel') diff --git a/kernel/Makefile.am b/kernel/Makefile.am new file mode 100644 index 0000000..7f29cf2 --- /dev/null +++ b/kernel/Makefile.am @@ -0,0 +1,123 @@ +SUBDIRS = ksquirrel-libs kls_avs kls_bmp kls_cut kls_dds kls_fli kls_hdr kls_ico kls_jbig kls_koala kls_lif kls_mdl kls_mtv kls_pcx kls_pix kls_pnm kls_psd kls_pxr kls_ras kls_rawrgb kls_sct kls_sgi kls_sun kls_tga kls_wal kls_wbmp kls_xbm kls_xcf kls_xcur kls_xpm kls_png kls_psp + +EXTRA_DIST = generate link include/*.h include/ksquirrel-libs/*.h xpm/*.xpm + +if SQ_HAVE_CAMERA +SUBDIRS += kls_camera +endif + +if SQ_HAVE_JPEG +SUBDIRS += kls_jpeg +endif + +if SQ_HAVE_TIFF +SUBDIRS += kls_tiff +endif + +if SQ_HAVE_XWD +SUBDIRS += kls_xwd +endif + +if SQ_HAVE_WMF +SUBDIRS += kls_wmf +endif + +if SQ_HAVE_SVG +SUBDIRS += kls_svg +endif + +if SQ_HAVE_GIF +SUBDIRS += kls_gif +endif + +if SQ_HAVE_OPENEXR +SUBDIRS += kls_openexr +endif + +if SQ_HAVE_JPEG2000 +SUBDIRS += kls_jpeg2000 +endif + +if SQ_HAVE_TTF +SUBDIRS += kls_ttf +endif + +if SQ_HAVE_MNG +SUBDIRS += kls_mng +endif + +if SQ_HAVE_DJVU +SUBDIRS += kls_djvu +endif + +if SQ_HAVE_DXF +SUBDIRS += kls_dxf +endif + +if SQ_HAVE_NEO +SUBDIRS += kls_neo +endif + +if SQ_HAVE_LEAF +SUBDIRS += kls_leaf +endif + +if SQ_HAVE_PI1 +SUBDIRS += kls_pi1 +endif + +if SQ_HAVE_PI3 +SUBDIRS += kls_pi3 +endif + +if SQ_HAVE_XIM +SUBDIRS += kls_xim +endif + +if SQ_HAVE_UTAH +SUBDIRS += kls_utah +endif + +if SQ_HAVE_PICT +SUBDIRS += kls_pict +endif + +if SQ_HAVE_MAC +SUBDIRS += kls_mac +endif + +if SQ_HAVE_IFF +SUBDIRS += kls_iff +endif + +if SQ_HAVE_FIG +SUBDIRS += kls_fig +endif + +if SQ_HAVE_LJPEG +SUBDIRS += kls_ljpeg +endif + +if SQ_HAVE_DICOM +SUBDIRS += kls_dicom +endif + +if SQ_HAVE_EPS +SUBDIRS += kls_eps +endif + +# unstable/buggy codecs - for developers only +if SQ_DEVEL +SUBDIRS += kls_msp +endif + +# install headers +install-data-am: + $(mkinstalldirs) $(DESTDIR)$(pkgincludedir) + $(INSTALL_HEADER) include/ksquirrel-libs/fileio.h $(DESTDIR)$(pkgincludedir)/fileio.h + $(INSTALL_HEADER) include/ksquirrel-libs/error.h $(DESTDIR)$(pkgincludedir)/error.h + $(INSTALL_HEADER) include/ksquirrel-libs/fmt_utils.h $(DESTDIR)$(pkgincludedir)/fmt_utils.h + $(INSTALL_HEADER) include/ksquirrel-libs/fmt_types.h $(DESTDIR)$(pkgincludedir)/fmt_types.h + $(INSTALL_HEADER) include/ksquirrel-libs/fmt_defs.h $(DESTDIR)$(pkgincludedir)/fmt_defs.h + $(INSTALL_HEADER) include/ksquirrel-libs/fmt_codec_base.h $(DESTDIR)$(pkgincludedir)/fmt_codec_base.h + $(INSTALL_HEADER) include/ksquirrel-libs/settings.h $(DESTDIR)$(pkgincludedir)/settings.h diff --git a/kernel/generate b/kernel/generate new file mode 100755 index 0000000..59e5ce5 --- /dev/null +++ b/kernel/generate @@ -0,0 +1,223 @@ +#!/bin/sh + +# Generate new development directory for image format +# +# Usage: +# $ ./generate +# + + +name=$1 +mkdir $name +mkdir include > /dev/null 2>&1 +cd $name + +cat << EOF > Makefile.am +INCLUDES = -I../include + +lib_LTLIBRARIES = lib${name}.la + +lib${name}_la_SOURCES = fmt_codec_${name}.cpp fmt_codec_${name}_defs.h + +lib${name}_la_LDFLAGS = +EOF + +cat << EOF > ../include/fmt_codec_${name}.h +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_${name}_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_${name}_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + // define variables you need here +}; + +#endif +EOF + +cat << EOF > fmt_codec_${name}_defs.h +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_${name} +#define KSQUIRREL_CODEC_DEFS_${name} + +// define constants here + +#endif +EOF + +cat << EOF > fmt_codec_${name}.cpp +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" + +#include "fmt_codec_${name}_defs.h" +#include "fmt_codec_${name}.h" + +#include "ksquirrel-libs/fmt_utils.h" +#include "ksquirrel-libs/error.h" + +#include "../xpm/codec_${name}.xpm" +EOF + +cat << EOF >> fmt_codec_${name}.cpp + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.1.0"; + o->name = ""; + o->filter = "*. "; + o->mime = ""; + o->pixmap = codec_${name}; + o->config = ""; + o->readable = true; + o->writestatic = false; + o->writeanimated = false; + o->canbemultiple = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + read_error = false; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + +/* + image.w = + image.h = + image.bpp = +*/ + + image.compression = ""; + image.colorspace = ""; + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + RGBA rgba; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" +EOF + +echo +echo "All done!" +echo +echo "Don't forget to insert your copyrights and edit Makefile.am" +echo diff --git a/kernel/include/fmt_codec_avs.h b/kernel/include/fmt_codec_avs.h new file mode 100644 index 0000000..8bc4f9f --- /dev/null +++ b/kernel/include/fmt_codec_avs.h @@ -0,0 +1,39 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_avs_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_avs_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + WRITE_CODEC_DECLARATIONS + + private: + // define variables you need here +}; + +#endif diff --git a/kernel/include/fmt_codec_bmp.h b/kernel/include/fmt_codec_bmp.h new file mode 100644 index 0000000..e49f351 --- /dev/null +++ b/kernel/include/fmt_codec_bmp.h @@ -0,0 +1,46 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_BMP_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_BMP_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + WRITE_CODEC_DECLARATIONS + + private: + RGB pal[256]; + s32 pal_entr; + u16 filler; + BITMAPFILE_HEADER bfh; + BITMAPINFO_HEADER bih; + s32 m_FILLER; + BITMAPFILE_HEADER m_bfh; + BITMAPINFO_HEADER m_bih; +}; + +#endif diff --git a/kernel/include/fmt_codec_cd_func.h b/kernel/include/fmt_codec_cd_func.h new file mode 100644 index 0000000..da38f56 --- /dev/null +++ b/kernel/include/fmt_codec_cd_func.h @@ -0,0 +1,35 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_create_destroy_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_create_destroy_H + +extern "C" fmt_codec_base* codec_create() +{ + return (new fmt_codec); +} + +extern "C" void codec_destroy(fmt_codec_base *p) +{ + delete p; +} + +#endif diff --git a/kernel/include/fmt_codec_cut.h b/kernel/include/fmt_codec_cut.h new file mode 100644 index 0000000..df8f099 --- /dev/null +++ b/kernel/include/fmt_codec_cut.h @@ -0,0 +1,38 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_CUT_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_CUT_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + RGB pal[256]; + u8 *bits; +}; + +#endif diff --git a/kernel/include/fmt_codec_dds.h b/kernel/include/fmt_codec_dds.h new file mode 100644 index 0000000..6def2c5 --- /dev/null +++ b/kernel/include/fmt_codec_dds.h @@ -0,0 +1,39 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2007 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_dds_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_dds_H + +#include "dds.h" + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + DDSINFO dds; +}; + +#endif diff --git a/kernel/include/fmt_codec_fli.h b/kernel/include/fmt_codec_fli.h new file mode 100644 index 0000000..cea637c --- /dev/null +++ b/kernel/include/fmt_codec_fli.h @@ -0,0 +1,42 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_FLI_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_FLI_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + bool skip_flood(ifstreamK &s); + + private: + FLICHEADER flic; + RGB pal[768]; + u8 **buf; +}; + +#endif diff --git a/kernel/include/fmt_codec_gif.h b/kernel/include/fmt_codec_gif.h new file mode 100644 index 0000000..f04077b --- /dev/null +++ b/kernel/include/fmt_codec_gif.h @@ -0,0 +1,45 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_GIF_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_GIF_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + GifFileType *gif; + GifRecordType record; + GifByteType *Extension; + u8 *buf; + RGBA *saved; + s32 i, j, Error, Row, Col, Width, Height, lastRow, lastCol, lastWidth, lastHeight, ExtCode, Count, + transIndex, Lines_h, curLine, linesz, disposal, lastDisposal, currentImage, currentPass; + RGBA **Lines, back, **Last; + ColorMapObject *map; +}; + +#endif diff --git a/kernel/include/fmt_codec_hdr.h b/kernel/include/fmt_codec_hdr.h new file mode 100644 index 0000000..c6759ed --- /dev/null +++ b/kernel/include/fmt_codec_hdr.h @@ -0,0 +1,42 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_hdr_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_hdr_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + bool read_scan(u8 *s, const s32 w); + bool getHdrHead(); + + private: + u8 *scanline; + hdr_header hdr; +}; + +#endif diff --git a/kernel/include/fmt_codec_ico.h b/kernel/include/fmt_codec_ico.h new file mode 100644 index 0000000..73cbaa1 --- /dev/null +++ b/kernel/include/fmt_codec_ico.h @@ -0,0 +1,43 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_ICO_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_ICO_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + u8 *bAND; + ICO_HEADER ifh; + ICO_DIRENTRY *ide; + BITMAPINFO_HEADER bih; + s32 pixel; + RGB pal[256]; + s32 pal_entr; +}; + +#endif diff --git a/kernel/include/fmt_codec_iff.h b/kernel/include/fmt_codec_iff.h new file mode 100644 index 0000000..62012f9 --- /dev/null +++ b/kernel/include/fmt_codec_iff.h @@ -0,0 +1,41 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_IFF_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_IFF_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + RGB *pal; + s32 pal_entr; + CHUNK_BMHD bmhd; + u8 **tile; + u8 *dline; +}; + +#endif diff --git a/kernel/include/fmt_codec_jbig.h b/kernel/include/fmt_codec_jbig.h new file mode 100644 index 0000000..d2429bd --- /dev/null +++ b/kernel/include/fmt_codec_jbig.h @@ -0,0 +1,34 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_jbig_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_jbig_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS +}; + +#endif diff --git a/kernel/include/fmt_codec_jpeg.h b/kernel/include/fmt_codec_jpeg.h new file mode 100644 index 0000000..b54e7b9 --- /dev/null +++ b/kernel/include/fmt_codec_jpeg.h @@ -0,0 +1,48 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_JPEG_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_JPEG_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + WRITE_CODEC_DECLARATIONS + + private: + struct jpeg_decompress_struct cinfo; + struct my_error_mgr jerr; + JSAMPARRAY buffer; + FILE *fptr; + + FILE *m_fptr; + struct jpeg_compress_struct m_cinfo; + struct jpeg_error_mgr m_jerr; + JSAMPROW row_pointer; + bool zerror; +}; + +#endif diff --git a/kernel/include/fmt_codec_jpeg2000.h b/kernel/include/fmt_codec_jpeg2000.h new file mode 100644 index 0000000..23e9ac1 --- /dev/null +++ b/kernel/include/fmt_codec_jpeg2000.h @@ -0,0 +1,51 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_jpeg2000_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_jpeg2000_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +typedef struct +{ + jas_image_t *image; + s32 cmptlut[MAXCMPTS]; + jas_image_t *altimage; + jas_matrix_t *data[3]; + jas_seqent_t *d[3]; + +} gs_t; + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + bool convert_colorspace(); + + private: + gs_t gs; + jas_stream_t *in; +}; + +#endif diff --git a/kernel/include/fmt_codec_koala.h b/kernel/include/fmt_codec_koala.h new file mode 100644 index 0000000..24a55b4 --- /dev/null +++ b/kernel/include/fmt_codec_koala.h @@ -0,0 +1,39 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_koala_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_koala_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + koala_t koala; + u8 pixel_mask[4], pixel_displ[4], foundcolor; + s32 index, pixel, colorindex; +}; + +#endif diff --git a/kernel/include/fmt_codec_lif.h b/kernel/include/fmt_codec_lif.h new file mode 100644 index 0000000..489b057 --- /dev/null +++ b/kernel/include/fmt_codec_lif.h @@ -0,0 +1,39 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_lif_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_lif_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + RGBA pal[256]; + lif_header lif; + s32 bytes; +}; + +#endif diff --git a/kernel/include/fmt_codec_mac.h b/kernel/include/fmt_codec_mac.h new file mode 100644 index 0000000..f65dcaf --- /dev/null +++ b/kernel/include/fmt_codec_mac.h @@ -0,0 +1,37 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_mac_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_mac_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + u8 bytes[72], byte[8]; +}; + +#endif diff --git a/kernel/include/fmt_codec_mdl.h b/kernel/include/fmt_codec_mdl.h new file mode 100644 index 0000000..c24134b --- /dev/null +++ b/kernel/include/fmt_codec_mdl.h @@ -0,0 +1,40 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_mdl_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_mdl_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + TEX_HEAD tex; + RGB pal[256]; + s32 numtex, texoff, texdataoff; + fstream::pos_type opos; +}; + +#endif diff --git a/kernel/include/fmt_codec_mng.h b/kernel/include/fmt_codec_mng.h new file mode 100644 index 0000000..ff4b546 --- /dev/null +++ b/kernel/include/fmt_codec_mng.h @@ -0,0 +1,51 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_mng_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_mng_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +struct mngstuff; + +struct _priv +{ + RGBA *frame; + int w, ms; + +}priv; + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + mngstuff *mymng; + mng_handle mng; + s32 total; + + public: + _priv priv; +}; + +#endif diff --git a/kernel/include/fmt_codec_msp.h b/kernel/include/fmt_codec_msp.h new file mode 100644 index 0000000..5ef6f7c --- /dev/null +++ b/kernel/include/fmt_codec_msp.h @@ -0,0 +1,41 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_msp_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_msp_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + msp_header msp; + std::vector scanmap; + s32 version; + u8 *bytes; + u8 byte[8]; +}; + +#endif diff --git a/kernel/include/fmt_codec_mtv.h b/kernel/include/fmt_codec_mtv.h new file mode 100644 index 0000000..77062a3 --- /dev/null +++ b/kernel/include/fmt_codec_mtv.h @@ -0,0 +1,39 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_mtv_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_mtv_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + WRITE_CODEC_DECLARATIONS + + private: + // define variables you need here +}; + +#endif diff --git a/kernel/include/fmt_codec_openexr.h b/kernel/include/fmt_codec_openexr.h new file mode 100644 index 0000000..a08e370 --- /dev/null +++ b/kernel/include/fmt_codec_openexr.h @@ -0,0 +1,45 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_openexr_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_openexr_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +#include +#include + +using namespace Imf; + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + Array2D *pixels; + std::string file, ref; + RgbaOutputFile *out; + Rgba *hs; +}; + +#endif diff --git a/kernel/include/fmt_codec_pcx.h b/kernel/include/fmt_codec_pcx.h new file mode 100644 index 0000000..4daedb6 --- /dev/null +++ b/kernel/include/fmt_codec_pcx.h @@ -0,0 +1,40 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_PCX_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_PCX_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + PCX_HEADER pfh; + s16 TotalBytesLine; + RGB pal[256]; + s32 pal_entr; +}; + +#endif diff --git a/kernel/include/fmt_codec_pix.h b/kernel/include/fmt_codec_pix.h new file mode 100644 index 0000000..58c23a1 --- /dev/null +++ b/kernel/include/fmt_codec_pix.h @@ -0,0 +1,34 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_PIX_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_PIX_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS +}; + +#endif diff --git a/kernel/include/fmt_codec_png.h b/kernel/include/fmt_codec_png.h new file mode 100644 index 0000000..2051187 --- /dev/null +++ b/kernel/include/fmt_codec_png.h @@ -0,0 +1,63 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_PNG_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_PNG_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + +#ifdef CODEC_ANOTHER + virtual void fill_default_settings(); +#endif + +#ifdef CODEC_PNG + WRITE_CODEC_DECLARATIONS +#endif + + private: + png_structp png_ptr; + png_infop info_ptr; + png_uint_32 width, height, number_passes; + s32 color_type; + png_bytep *cur, *prev, *frame; + FILE *fptr; + s32 bit_depth, interlace_type; + s32 frames; + fmt_image img; + + png_uint_32 next_frame_width, next_frame_height, next_frame_x_offset, next_frame_y_offset; + png_uint_16 next_frame_delay_num, next_frame_delay_den; + png_byte next_frame_dispose_op, next_frame_blend_op; + + FILE *m_fptr; + png_structp m_png_ptr; + png_infop m_info_ptr; + png_bytep m_row_pointer; + bool zerror, m_zerror; +}; + +#endif diff --git a/kernel/include/fmt_codec_pnm.h b/kernel/include/fmt_codec_pnm.h new file mode 100644 index 0000000..d2e9c60 --- /dev/null +++ b/kernel/include/fmt_codec_pnm.h @@ -0,0 +1,48 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_PNM_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_PNM_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + +#ifdef CODEC_ANOTHER + virtual void fill_default_settings(); +#endif + +#ifdef CODEC_PNM + WRITE_CODEC_DECLARATIONS +#endif + + private: + s32 pnm; + FILE *fptr; + s8 format[10]; + double koeff; +}; + +#endif diff --git a/kernel/include/fmt_codec_psd.h b/kernel/include/fmt_codec_psd.h new file mode 100644 index 0000000..94ee1f2 --- /dev/null +++ b/kernel/include/fmt_codec_psd.h @@ -0,0 +1,41 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_PSD_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_PSD_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + u32 width, height; + u16 channels, depth, mode, compression; + RGBA **last; + u8 *L; + RGB pal[256]; +}; + +#endif diff --git a/kernel/include/fmt_codec_psp.h b/kernel/include/fmt_codec_psp.h new file mode 100644 index 0000000..730269b --- /dev/null +++ b/kernel/include/fmt_codec_psp.h @@ -0,0 +1,53 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_psp_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_psp_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + bool iGetPspHead(); + bool iCheckPsp(); + bool ReadGenAttributes(); + bool ParseChunks(); + bool ReadLayerBlock(); + bool ReadAlphaBlock(); + ILubyte *GetChannel(); + bool UncompRLE(ILubyte *CompData, ILubyte *Data, ILuint CompLen); + bool ReadPalette(); + + private: + GENATT_CHUNK AttChunk; + PSPHEAD Header; + ILuint NumChannels; + ILubyte **Channels; + ILubyte *Alpha; + RGBA *pal; +}; + +#endif diff --git a/kernel/include/fmt_codec_pxr.h b/kernel/include/fmt_codec_pxr.h new file mode 100644 index 0000000..af1a9a0 --- /dev/null +++ b/kernel/include/fmt_codec_pxr.h @@ -0,0 +1,34 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_pxr_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_pxr_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS +}; + +#endif diff --git a/kernel/include/fmt_codec_ras.h b/kernel/include/fmt_codec_ras.h new file mode 100644 index 0000000..6c60ab7 --- /dev/null +++ b/kernel/include/fmt_codec_ras.h @@ -0,0 +1,43 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_RAS_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_RAS_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + RGB pal[256]; + RAS_HEADER rfh; + bool rle, isRGB; + u16 fill; + u8 fillchar; + u16 linelength; + u8 *buf; +}; + +#endif diff --git a/kernel/include/fmt_codec_rawrgb.h b/kernel/include/fmt_codec_rawrgb.h new file mode 100644 index 0000000..db756e2 --- /dev/null +++ b/kernel/include/fmt_codec_rawrgb.h @@ -0,0 +1,40 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_rawrgb_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_rawrgb_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + WRITE_CODEC_DECLARATIONS + + private: + // define variables you need here +}; + +#endif + diff --git a/kernel/include/fmt_codec_sct.h b/kernel/include/fmt_codec_sct.h new file mode 100644 index 0000000..416a780 --- /dev/null +++ b/kernel/include/fmt_codec_sct.h @@ -0,0 +1,37 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_sct_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_sct_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + sct_header sct; +}; + +#endif diff --git a/kernel/include/fmt_codec_sgi.h b/kernel/include/fmt_codec_sgi.h new file mode 100644 index 0000000..ce65fb7 --- /dev/null +++ b/kernel/include/fmt_codec_sgi.h @@ -0,0 +1,40 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_SGI_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_SGI_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + u32 *starttab, *lengthtab; + SGI_HEADER sfh; + s32 rle_row; + s8 *channel[4]; +}; + +#endif diff --git a/kernel/include/fmt_codec_sun.h b/kernel/include/fmt_codec_sun.h new file mode 100644 index 0000000..3fc730b --- /dev/null +++ b/kernel/include/fmt_codec_sun.h @@ -0,0 +1,38 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_sun_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_sun_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + u32 validbits; +}; + +#endif + diff --git a/kernel/include/fmt_codec_tga.h b/kernel/include/fmt_codec_tga.h new file mode 100644 index 0000000..535d108 --- /dev/null +++ b/kernel/include/fmt_codec_tga.h @@ -0,0 +1,40 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_TGA_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_TGA_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + s32 pal_entr; + RGB pal[256]; + TGA_FILEHEADER tfh; + bool fliph; +}; + +#endif diff --git a/kernel/include/fmt_codec_tiff.h b/kernel/include/fmt_codec_tiff.h new file mode 100644 index 0000000..713a8d6 --- /dev/null +++ b/kernel/include/fmt_codec_tiff.h @@ -0,0 +1,46 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_TIFF_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_TIFF_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +#include + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + WRITE_CODEC_DECLARATIONS + + void fill_default_settings(); + + private: + TIFF *ftiff, *out; + TIFFRGBAImage img; + s32 dircount, line, pages; + std::map compr; +}; + +#endif diff --git a/kernel/include/fmt_codec_ttf.h b/kernel/include/fmt_codec_ttf.h new file mode 100644 index 0000000..d97df91 --- /dev/null +++ b/kernel/include/fmt_codec_ttf.h @@ -0,0 +1,34 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_ttf_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_ttf_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS +}; + +#endif diff --git a/kernel/include/fmt_codec_utah.h b/kernel/include/fmt_codec_utah.h new file mode 100644 index 0000000..5076afb --- /dev/null +++ b/kernel/include/fmt_codec_utah.h @@ -0,0 +1,38 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_utah_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_utah_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + UTAH_HEADER utah; +}; + +#endif + diff --git a/kernel/include/fmt_codec_wal.h b/kernel/include/fmt_codec_wal.h new file mode 100644 index 0000000..5496bdc --- /dev/null +++ b/kernel/include/fmt_codec_wal.h @@ -0,0 +1,39 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_wal_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_wal_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + wal_header wal; + s32 neww, newh; + u8 *bits; +}; + +#endif diff --git a/kernel/include/fmt_codec_wbmp.h b/kernel/include/fmt_codec_wbmp.h new file mode 100644 index 0000000..cdaa382 --- /dev/null +++ b/kernel/include/fmt_codec_wbmp.h @@ -0,0 +1,49 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_wbmp_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_wbmp_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class Wbmp; + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + s32 putmbi(s32 i, ofstreamK &f); + s32 getmbi(ifstreamK &f); + s32 skipheader(ifstreamK &f); + + Wbmp* createwbmp(s32 width, s32 height, s32 color); + + s32 writewbmp(Wbmp *wbmp, ofstreamK &out); + + private: + Wbmp wbmp; +}; + +#endif + diff --git a/kernel/include/fmt_codec_wmf.h b/kernel/include/fmt_codec_wmf.h new file mode 100644 index 0000000..aa5d373 --- /dev/null +++ b/kernel/include/fmt_codec_wmf.h @@ -0,0 +1,39 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_wmf_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_wmf_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + u8 *buf; + s32 w, h; +}; + +#endif + diff --git a/kernel/include/fmt_codec_xbm.h b/kernel/include/fmt_codec_xbm.h new file mode 100644 index 0000000..5a36dbf --- /dev/null +++ b/kernel/include/fmt_codec_xbm.h @@ -0,0 +1,40 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_XBM_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_XBM_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + FILE *fptr; + RGB pal[2]; + s32 lscan; + s32 version; +}; + +#endif diff --git a/kernel/include/fmt_codec_xcur.h b/kernel/include/fmt_codec_xcur.h new file mode 100644 index 0000000..6f4fd16 --- /dev/null +++ b/kernel/include/fmt_codec_xcur.h @@ -0,0 +1,43 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_XCUR_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_XCUR_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + s32 currentToc; + bool lastToc; + + XCUR_HEADER xcur_h; + XCUR_CHUNK_DESC *tocs; + XCUR_CHUNK_HEADER xcur_chunk; + XCUR_CHUNK_IMAGE xcur_im; +}; + +#endif diff --git a/kernel/include/fmt_codec_xpm.h b/kernel/include/fmt_codec_xpm.h new file mode 100644 index 0000000..277f438 --- /dev/null +++ b/kernel/include/fmt_codec_xpm.h @@ -0,0 +1,44 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_XPM_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_XPM_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + void fillmap(); + RGBA hex2rgb(const s8 *hex); + + private: + s32 numcolors; + s32 cpp; + std::map named; + std::map file; +}; + +#endif diff --git a/kernel/include/fmt_codec_xwd.h b/kernel/include/fmt_codec_xwd.h new file mode 100644 index 0000000..690afa7 --- /dev/null +++ b/kernel/include/fmt_codec_xwd.h @@ -0,0 +1,38 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_XWD_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_XWD_H + +#include "ksquirrel-libs/fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + BASE_CODEC_DECLARATIONS + + private: + s32 pal_entr, filler; + RGB *pal; +}; + +#endif diff --git a/kernel/include/ksquirrel-libs/error.h b/kernel/include/ksquirrel-libs/error.h new file mode 100644 index 0000000..bfeec9e --- /dev/null +++ b/kernel/include/ksquirrel-libs/error.h @@ -0,0 +1,49 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) libraries + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_ERROR_CODES_H +#define KSQUIRREL_LIBS_ERROR_CODES_H + + +/////////////////////////////////// +// // +// Error codes for libraries // +// // +/////////////////////////////////// + + +#define SQE_NOTOK 0 +#define SQE_OK 1 + +#define SQE_R_NOFILE 1024 +#define SQE_R_BADFILE 1025 +#define SQE_R_NOMEMORY 1026 +#define SQE_R_NOTSUPPORTED 1027 +#define SQE_R_WRONGDIM 1028 + +#define SQE_W_NOFILE 1029 +#define SQE_W_NOMEMORY SQE_R_NOMEMORY +#define SQE_W_NOTSUPPORTED 1032 +#define SQE_W_ERROR 1033 +#define SQE_W_WRONGPARAMS 1034 +#define SQE_W_WRONGDIM SQE_R_WRONGDIM + +#endif diff --git a/kernel/include/ksquirrel-libs/fileio.h b/kernel/include/ksquirrel-libs/fileio.h new file mode 100644 index 0000000..3bf3921 --- /dev/null +++ b/kernel/include/ksquirrel-libs/fileio.h @@ -0,0 +1,73 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_FIO_H +#define KSQUIRREL_LIBS_FIO_H + +#include + +using namespace std; + +#include + +//////////////////////////////// +// // +// Binary-oriented file i/o // +// // +//////////////////////////////// + + +// read binary data +class ifstreamK : public ifstream +{ + public: + ifstreamK(); + + // read 'size' bytes of binary data and store it into 'data'. + // return true if reading was successful, and false otherwise + bool readK(void *data, int size); + + // read string from file + bool getS(char *, const int); + + // read ascii hex value from file + bool readCHex(u32 &hex); + + // big-endian-oriented reading + bool be_getchar(u8 *c); + bool be_getshort(u16 *s); + bool be_getlong(u32 *l); + + void close(); +}; + +// write binary data +class ofstreamK : public ofstream +{ + public: + ofstreamK(); + + bool writeK(void *data, int size); + + void close(); +}; + +#endif diff --git a/kernel/include/ksquirrel-libs/fmt_codec_base.h b/kernel/include/ksquirrel-libs/fmt_codec_base.h new file mode 100644 index 0000000..cae04ea --- /dev/null +++ b/kernel/include/ksquirrel-libs/fmt_codec_base.h @@ -0,0 +1,258 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_H + +#include +#include +#include + +////////////////////////////////// +// // +// Base class for all // +// codecs // +// // +////////////////////////////////// + + +class fmt_codec_base +{ + public: + fmt_codec_base() + {} + + virtual ~fmt_codec_base() + {} + + // version of the library, e.g. "1.2.2", etc. + // + // tell clients that fmt_codec_base couldn't be + // instantianted + virtual void options(codec_options *) = 0; + + // return file extension for a given bpp + virtual std::string extension(const s32 bpp); + + /* + * read methods + */ + + // fmt_read_init: do what you need before decoding + virtual s32 read_init(const std::string &file); + + // fmt_read_next: seek to correct file offset, do other initialization stuff. + // this method should be (and will be) called before image is about to + // be decoded. + virtual s32 read_next(); + + // fmt_read_next_pass: do somethimg important before the next pass + // will be decoded (usually do nothing, if the image has only 1 pass (like BMP, PCX ...), + // or adjust variables if the image is interlaced, with passes > 1 (like GIF, PNG)) + virtual s32 read_next_pass(); + + // fmt_readscanline: read one scanline from file + virtual s32 read_scanline(RGBA *scan); + + // fmt_read_close: close all handles, free memory, etc. + virtual void read_close(); + + /* + * write methods + */ + + // fmt_getwriteoptions: return write options for this image format + virtual void getwriteoptions(fmt_writeoptionsabs *); + + // fmt_write_init: init writing + virtual s32 write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt); + + virtual s32 write_next(); + + virtual s32 write_next_pass(); + + // fmt_write_scanline: write scanline + virtual s32 write_scanline(RGBA *scan); + + // fmt_write_close: close writing(close descriptors, free memory, etc.) + virtual void write_close(); + + fmt_info information() const; + + fmt_image* image(const int index); + + void addmeta(const fmt_metaentry &m); + + void settempfile(const std::string &t); + + // fill fmt_settings with values + void set_settings(const fmt_settings &sett); + + fmt_settings settings() const; + + virtual void fill_default_settings() + {} + + protected: + // image index in finfo.image + s32 currentImage; + + // fmt_info structure + fmt_info finfo; + + // input stream + ifstreamK frs; + + // output stream + ofstreamK fws; + + // some additional error checkers + bool read_error, write_error; + + // line and layer indexes - needed by some + // interlaced or layered images + s32 line, layer; + + // error code + s32 write_error_code; + + // write options + fmt_writeoptions writeopt; + + // saved fmt_image + fmt_image writeimage; + + // path to temporary file + // should be set by the highlevel application + // with settempfile() + std::string tmp; + + fmt_settings m_settings; +}; + +inline +fmt_settings fmt_codec_base::settings() const +{ + return m_settings; +} + +inline +void fmt_codec_base::set_settings(const fmt_settings &sett) +{ + m_settings = sett; +} + +inline +fmt_info fmt_codec_base::information() const +{ + return finfo; +} + +inline +fmt_image* fmt_codec_base::image(const int index) +{ + return &finfo.image[index]; +} + +inline +void fmt_codec_base::addmeta(const fmt_metaentry &m) +{ + finfo.meta.push_back(m); +} + +inline +void fmt_codec_base::settempfile(const std::string &t) +{ + tmp = t; +} + +inline +std::string fmt_codec_base::extension(const s32) +{ + return std::string(""); +} + +inline +s32 fmt_codec_base::read_init(const std::string &) +{ return 1; } + +inline +s32 fmt_codec_base::read_next() +{ return 1; } + +inline +s32 fmt_codec_base::read_next_pass() +{ return 1; } + +inline +s32 fmt_codec_base::read_scanline(RGBA *) +{ return 1; } + +inline +void fmt_codec_base::read_close() +{} + +inline +void fmt_codec_base::getwriteoptions(fmt_writeoptionsabs *) +{} + +inline +s32 fmt_codec_base::write_init(const std::string &, const fmt_image &, const fmt_writeoptions &) +{ return 1; } + +inline +s32 fmt_codec_base::write_next() +{ return 1; } + +inline +s32 fmt_codec_base::write_next_pass() +{ return 1; } + +inline +s32 fmt_codec_base::write_scanline(RGBA *) +{ return 1; } + +inline +void fmt_codec_base::write_close() +{} + +#define BASE_CODEC_DECLARATIONS \ + fmt_codec(); \ + ~fmt_codec(); \ + \ + virtual void options(codec_options *o); \ + virtual s32 read_init(const std::string &file);\ + virtual s32 read_next(); \ + virtual s32 read_next_pass(); \ + virtual s32 read_scanline(RGBA *scan); \ + virtual void read_close(); + +#define WRITE_CODEC_DECLARATIONS \ + virtual std::string extension(const s32 bpp); \ + virtual void getwriteoptions(fmt_writeoptionsabs *); \ + virtual s32 write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt); \ + virtual s32 write_next(); \ + virtual s32 write_next_pass(); \ + virtual s32 write_scanline(RGBA *scan); \ + virtual void write_close(); + +#endif + diff --git a/kernel/include/ksquirrel-libs/fmt_defs.h b/kernel/include/ksquirrel-libs/fmt_defs.h new file mode 100644 index 0000000..a2bbd6c --- /dev/null +++ b/kernel/include/ksquirrel-libs/fmt_defs.h @@ -0,0 +1,242 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_DEFS_H +#define KSQUIRREL_LIBS_DEFS_H + +#include +#include + +#include + +struct codec_options +{ + std::string version, + name, + filter, + mime, + mimetype, + config; + + void *pixmap; + + bool readable, + canbemultiple, + writestatic, + writeanimated, + needtempfile; +}; + +/* Metainfo support */ + +struct fmt_metaentry +{ + std::string group; + std::string data; +}; + +/* RGBA and RGB pixels */ + +struct RGBA +{ + RGBA() : r(0), g(0), b(0), a(0) + {} + + RGBA(s32 r1, s32 g1, s32 b1, s32 a1) : r(r1), g(g1), b(b1), a(a1) + {} + + u8 r; + u8 g; + u8 b; + u8 a; + +}PACKED; + +struct RGB +{ + RGB() : r(0), g(0), b(0) + {} + + RGB(s32 r1, s32 g1, s32 b1) : r(r1), g(g1), b(b1) + {} + + u8 r; + u8 g; + u8 b; + +}PACKED; + +/* Image decription */ +struct fmt_image +{ + fmt_image() : w(0), h(0), bpp(0), hasalpha(false), needflip(false), delay(0), + interlaced(false), passes(1) + {} + + // width and height + s32 w; + s32 h; + + // bit depth + s32 bpp; + + // has alpha channel ? + bool hasalpha; + + // need to be flipped ? + bool needflip; + + // if it's a frame in animated sequence, + // 'delay' will define a delay time + s32 delay; + + // interlaced or normal ? + bool interlaced; + + // if interlaced, 'passes' stores the number + // of passes. if no, passes should be 1 + s32 passes; + + // some useful info about image. + // this is a replacement for 'dump' in older versions of ksquirrel-libs + // -------------------------------------------------------------------- + + // color space (RGB, RGBA, CMYK, LAB ...) + std::string colorspace; + + // compression type (RLE, JPEG, Deflate ...) + std::string compression; + + // palette types + enum fmt_palette { monochrome = 1, indexed4 = 2, indexed8 = 4, indexed15 = 8, + indexed16 = 16, pure24 = 32, pure32 = 64, internal = 128 }; + + // palette, if exists + std::vector palette; +}; + +/* General description */ +struct fmt_info +{ + fmt_info() : animated(false) + {} + + /* + * TODO: make 'image' and 'meta' implicitly shared ? + */ + + // array of images + std::vector image; + + // array of metainfo entries + std::vector meta; + + // animated or static + bool animated; +}; + +/* Internal cmpression. + E.g. compression_level will be + passed to internal routines, + No compression RLE compression for ex. in libjpeg, libpng. +*/ +enum fmt_compression { CompressionNo = 1, CompressionRLE = 2, CompressionInternal = 4 }; +/* Note: if the image can be compressed + with RLE encoding and with only RLE + encoding, compression_scheme should be + CompressionInternal +*/ + +/* Write options for image format */ +struct fmt_writeoptionsabs +{ + // can be interlaced ? + bool interlaced; + + // if interlaced, this value should store preferred number of passes. + s32 passes; + + // if the image should be flipped before writing + bool needflip; + + // with which compression it can be encoded ? + // for example: CompressionNo | CompressionRLE. + // it means, that image can be encoded with RLE + // method or can be saved uncompressed. + s32 compression_scheme; + + // minimum compression level, maximum and default + // For example, JPEG library has minimum = 0, + // maximum = 100 and default = 25. + s32 compression_min, compression_max, compression_def; + + // with which bit depth it can be encoded ? + // 1 means support of this bit depth, + // and 0 otherwise. This param cann't be null. + // + // bits 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + // bit depth 32 24 16 15 8 4 1 + u8 palette_flags; + +}PACKED; + +/* this information will be passed to writing function */ +struct fmt_writeoptions +{ + // write interlaced image or normal ? + bool interlaced; + + // with which compression encode the image ? + fmt_compression compression_scheme; + + // compression level + s32 compression_level; + + // has alpha channel ? + // If no, A channel in RGBA image will be ignored + bool alpha; + + s32 bitdepth; + +}PACKED; + +#if defined SQ_NEED_OPERATOR_RGBA_RGBA +static s32 operator== (const RGBA &rgba1, const RGBA &rgba2) +{ + return (rgba1.r == rgba2.r && rgba1.g == rgba2.g && rgba1.b == rgba2.b && rgba1.a == rgba2.a); +} +#endif + +#if defined SQ_NEED_OPERATOR_RGB_RGBA +static s32 operator== (const RGB &rgb, const RGBA &rgba) +{ + return (rgb.r == rgba.r && rgb.g == rgba.g && rgb.b == rgba.b); +} +#endif + +#if defined SQ_NEED_OPERATOR_RGBA_RGB +static s32 operator== (const RGBA &rgba, const RGB &rgb) +{ + return (rgba.r == rgb.r && rgba.g == rgb.g && rgba.b == rgb.b); +} +#endif + +#endif diff --git a/kernel/include/ksquirrel-libs/fmt_types.h b/kernel/include/ksquirrel-libs/fmt_types.h new file mode 100644 index 0000000..75b6f02 --- /dev/null +++ b/kernel/include/ksquirrel-libs/fmt_types.h @@ -0,0 +1,36 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_TYPES_H +#define KSQUIRREL_LIBS_TYPES_H + +typedef char s8; +typedef unsigned char u8; + +typedef short s16; +typedef unsigned short u16; + +typedef int s32; +typedef unsigned int u32; + +#define PACKED __attribute__ ((packed)) + +#endif diff --git a/kernel/include/ksquirrel-libs/fmt_utils.h b/kernel/include/ksquirrel-libs/fmt_utils.h new file mode 100644 index 0000000..1ab42e3 --- /dev/null +++ b/kernel/include/ksquirrel-libs/fmt_utils.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_UTILS_H +#define KSQUIRREL_LIBS_UTILS_H + +#include + +using namespace std; + +#include + +struct RGBA; + +//////////////////////// +// // +// Helper namespace // +// // +//////////////////////// + + +namespace fmt_utils +{ + void fillAlpha(RGBA *scan, int w, u8 value = 255); + + // flip the image vertically + // usually BMP, SGI (or some other formats) need to be flipped + void flipv(s8 *image, s32 bytes_w, s32 h); + + // flip the image horizontally + void fliph(s8 *image, s32 w, s32 h, s32 bpp); + + // Big endian to Little endian conversion + u16 konvertWord(u16 a); + u32 konvertLong(u32 a); + + // return color system name by bpp. + // for example 32 bpp means RGBA image, 1 bpp - monochrome + std::string colorSpaceByBpp(const s32 bpp); + + void expandMono1Byte(const u32 byte, u8 *array); + void expandMono2Byte(const u32 byte, u8 *array); + void expandMono4Byte(const u32 byte, u8 *array); +} + +#endif diff --git a/kernel/include/ksquirrel-libs/settings.h b/kernel/include/ksquirrel-libs/settings.h new file mode 100644 index 0000000..b8472c6 --- /dev/null +++ b/kernel/include/ksquirrel-libs/settings.h @@ -0,0 +1,69 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2007 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_LIBS_CODEC_SETTINGS_H +#define KSQUIRREL_LIBS_CODEC_SETTINGS_H + +#include +#include + +struct settings_value +{ + enum settings_value_type { v_bool, v_int, v_double, v_string }; + + settings_value() + : type(v_int), bVal(false), iVal(0), dVal(0.0) + {} + + settings_value(bool _b) + : type(v_bool), bVal(_b) + {} + + settings_value(int _i) + : type(v_int), iVal(_i) + {} + + settings_value(double _d) + : type(v_double), dVal(_d) + {} + + settings_value(const std::string &_s) + : type(v_string), sVal(_s) + {} + + settings_value_type type; + + // means QCheckBox + bool bVal; + + // means KNumInput or QGroupBox + int iVal; + + // means KDoubleNumInput + double dVal; + + // means QLineEdit + std::string sVal; +}; + +typedef std::map fmt_settings; + +#endif diff --git a/kernel/kls_avs/Makefile.am b/kernel/kls_avs/Makefile.am new file mode 100644 index 0000000..0de3431 --- /dev/null +++ b/kernel/kls_avs/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_avs.la + +libkls_avs_la_SOURCES = fmt_codec_avs.cpp fmt_codec_avs_defs.h + +libkls_avs_la_LDFLAGS = ${SQ_RELEASE} + +libkls_avs_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_avs/fmt_codec_avs.cpp b/kernel/kls_avs/fmt_codec_avs.cpp new file mode 100644 index 0000000..4d93352 --- /dev/null +++ b/kernel/kls_avs/fmt_codec_avs.cpp @@ -0,0 +1,207 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" + +#include "fmt_codec_avs_defs.h" +#include "fmt_codec_avs.h" + +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "../xpm/codec_avs.xpm" + +/* + * + * AVS X + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.1.1"; + o->name = "AVS X image"; + o->filter = "*.x "; + o->mime = ""; + o->mimetype = "image/x-avs"; + o->config = ""; + o->pixmap = codec_avs; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + read_error = false; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + if(!frs.readK(&image.w, sizeof(s32))) return SQE_R_BADFILE; + if(!frs.readK(&image.h, sizeof(s32))) return SQE_R_BADFILE; + + image.w = fmt_utils::konvertLong(image.w); + image.h = fmt_utils::konvertLong(image.h); + image.bpp = 32; + + image.compression = "-"; + image.colorspace = fmt_utils::colorSpaceByBpp(32); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + for(s32 i = 0;i < im->w;i++) + { + if(!frs.readK(&a, sizeof(u8))) return SQE_R_BADFILE; + if(!frs.readK(&rgb, sizeof(RGB))) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->passes = 1; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + s32 w = fmt_utils::konvertLong(writeimage.w); + s32 h = fmt_utils::konvertLong(writeimage.h); + + if(!fws.writeK(&w, sizeof(s32))) return SQE_W_ERROR; + if(!fws.writeK(&h, sizeof(s32))) return SQE_W_ERROR; + + return SQE_OK; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + RGBA rgba; + + for(s32 i = 0;i < writeimage.w;i++) + { + rgba.r = scan[i].a; + rgba.g = scan[i].r; + rgba.b = scan[i].g; + rgba.a = scan[i].b; + + if(!fws.writeK(&rgba, sizeof(RGBA))) return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("x"); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_avs/fmt_codec_avs_defs.h b/kernel/kls_avs/fmt_codec_avs_defs.h new file mode 100644 index 0000000..3f998ba --- /dev/null +++ b/kernel/kls_avs/fmt_codec_avs_defs.h @@ -0,0 +1,27 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_avs +#define KSQUIRREL_CODEC_DEFS_avs + +// define constants here + +#endif diff --git a/kernel/kls_bmp/Makefile.am b/kernel/kls_bmp/Makefile.am new file mode 100644 index 0000000..a53cbdf --- /dev/null +++ b/kernel/kls_bmp/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_bmp.la + +libkls_bmp_la_SOURCES = fmt_codec_bmp.cpp fmt_codec_bmp_defs.h + +libkls_bmp_la_LDFLAGS = ${SQ_RELEASE} + +libkls_bmp_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_bmp/fmt_codec_bmp.cpp b/kernel/kls_bmp/fmt_codec_bmp.cpp new file mode 100644 index 0000000..c7be886 --- /dev/null +++ b/kernel/kls_bmp/fmt_codec_bmp.cpp @@ -0,0 +1,445 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_bmp_defs.h" +#include "fmt_codec_bmp.h" + +#include "../xpm/codec_bmp.xpm" + +/* + * + * This library works with the graphics-file formats used by the Microsoft Windows(tm) + * operating system. + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "1.1.2"; + o->name = "Windows Bitmap"; + o->filter = "*.bmp *.dib "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-bmp"; + o->pixmap = codec_bmp; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + pal_entr = 0; + currentImage = -1; + read_error = false; + + if(!frs.readK(&bfh, sizeof(BITMAPFILE_HEADER))) + return SQE_R_BADFILE; + + if(!frs.readK(&bih, sizeof(BITMAPINFO_HEADER))) + return SQE_R_BADFILE; + + if(bfh.Type != BMP_IDENTIFIER || bih.Size != 40) + return SQE_R_BADFILE; + + if(bih.Compression != BI_RGB) + return SQE_R_NOTSUPPORTED; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + RGBA rgba; + s32 i, j, scanShouldBe; + + if(bih.BitCount < 16) + pal_entr = 1 << bih.BitCount; + else + pal_entr = 0; + + image.w = bih.Width; + image.h = bih.Height; + image.bpp = bih.BitCount; + scanShouldBe = bih.Width; + + switch(image.bpp) + { + case 1: + { + s32 _tmp = scanShouldBe; + scanShouldBe /= 8; + scanShouldBe = scanShouldBe + ((_tmp%8)?1:0); + } + break; + + case 4: scanShouldBe = ((image.w)%2)?((scanShouldBe+1)/2):(scanShouldBe/2); break; + case 8: break; + case 16: scanShouldBe *= 2; break; + case 24: scanShouldBe *= 3; break; + case 32: break; + + default: + return SQE_R_BADFILE; + } + + for(j = 0;j < 4;j++) + if((scanShouldBe+j)%4 == 0) + { + filler = j; + break; + } + + if(image.bpp < 16) + { + /* read palette */ + for(i = 0;i < pal_entr;i++) + { + if(!frs.readK(&rgba, sizeof(RGBA))) + return SQE_R_BADFILE; + + (pal)[i].r = rgba.b; + (pal)[i].g = rgba.g; + (pal)[i].b = rgba.r; + } + } + + /* fseek to image bits */ + frs.seekg(bfh.OffBits, ios::beg); + + image.needflip = true; + image.colorspace = (pal_entr ? "Color indexed":"RGB"); + image.compression = "-"; + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + u16 remain, scanShouldBe, j, counter = 0; + u8 bt, dummy; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(im->bpp) + { + case 1: + { + u8 index; + remain=((im->w)<=8)?(0):((im->w)%8); + scanShouldBe = im->w; + + s32 _tmp = scanShouldBe; + scanShouldBe /= 8; + scanShouldBe = scanShouldBe + ((_tmp%8)?1:0); + + // @todo get rid of miltiple 'if' + for(j = 0;j < scanShouldBe;j++) + { + if(!frs.readK(&bt, 1)) + return SQE_R_BADFILE; + + if(j==scanShouldBe-1 && (remain-0)<=0 && remain)break; index = (bt & 128) >> 7; memcpy(scan+(counter++), (pal)+index, sizeof(RGB)); + if(j==scanShouldBe-1 && (remain-1)<=0 && remain)break; index = (bt & 64) >> 6; memcpy(scan+(counter++), (pal)+index, sizeof(RGB)); + if(j==scanShouldBe-1 && (remain-2)<=0 && remain)break; index = (bt & 32) >> 5; memcpy(scan+(counter++), (pal)+index, sizeof(RGB)); + if(j==scanShouldBe-1 && (remain-3)<=0 && remain)break; index = (bt & 16) >> 4; memcpy(scan+(counter++), (pal)+index, sizeof(RGB)); + if(j==scanShouldBe-1 && (remain-4)<=0 && remain)break; index = (bt & 8) >> 3; memcpy(scan+(counter++), (pal)+index, sizeof(RGB)); + if(j==scanShouldBe-1 && (remain-5)<=0 && remain)break; index = (bt & 4) >> 2; memcpy(scan+(counter++), (pal)+index, sizeof(RGB)); + if(j==scanShouldBe-1 && (remain-6)<=0 && remain)break; index = (bt & 2) >> 1; memcpy(scan+(counter++), (pal)+index, sizeof(RGB)); + if(j==scanShouldBe-1 && (remain-7)<=0 && remain)break; index = (bt & 1); memcpy(scan+(counter++), (pal)+index, sizeof(RGB)); + } + + for(j = 0;j < filler;j++) + { + if(!frs.readK(&dummy, 1)) + return SQE_R_BADFILE; + } + } + break; + + case 4: + { + u8 index; + remain = (im->w)%2; + + s32 ck = (im->w%2)?(im->w + 1):(im->w); + ck /= 2; + + for(j = 0;j < ck-1;j++) + { + if(!frs.readK(&bt, 1)) + return SQE_R_BADFILE; + + index = (bt & 0xf0) >> 4; + memcpy(scan+(counter++), (pal)+index, 3); + index = bt & 0xf; + memcpy(scan+(counter++), (pal)+index, 3); + } + + if(!frs.readK(&bt, 1)) + return SQE_R_BADFILE; + + index = (bt & 0xf0) >> 4; + memcpy(scan+(counter++), (pal)+index, 3); + + if(!remain) + { + index = bt & 0xf; + memcpy(scan+(counter++), (pal)+index, 3); + } + + for(j = 0;j < filler;j++) + { + if(!frs.readK(&dummy, 1)) + return SQE_R_BADFILE; + } + } + break; + + case 8: + { + for(j = 0;j < im->w;j++) + { + if(!frs.readK(&bt, 1)) + return SQE_R_BADFILE; + + memcpy(scan+(counter++), (pal)+bt, 3); + } + + for(j = 0;j < filler;j++) + { + if(!frs.readK(&dummy, 1)) + return SQE_R_BADFILE; + } + } + break; + + case 16: + { + u16 word; + + for(j = 0;j < im->w;j++) + { + if(!frs.readK(&word, 2)) + return SQE_R_BADFILE; + + scan[counter].b = (word&0x1f) << 3; + scan[counter].g = ((word&0x3e0) >> 5) << 3; + scan[counter++].r = ((word&0x7c00)>>10) << 3; + } + + for(j = 0;j < filler;j++) + { + if(!frs.readK(&dummy, 1)) + return SQE_R_BADFILE; + } + } + break; + + case 24: + { + RGB rgb; + + for(j = 0;j < im->w;j++) + { + if(!frs.readK(&rgb, sizeof(RGB))) + return SQE_R_BADFILE; + + scan[counter].r = rgb.b; + scan[counter].g = rgb.g; + scan[counter].b = rgb.r; + counter++; + } + + for(j = 0;j < filler;j++) + { + if(!frs.readK(&dummy, 1)) + return SQE_R_BADFILE; + } + } + break; + + case 32: + { + RGBA rgba; + + for(j = 0;j < im->w;j++) + { + if(!frs.readK(&rgba, sizeof(RGBA))) + return SQE_R_BADFILE; + + scan[j].r = rgba.b; + scan[j].g = rgba.g; + scan[j].b = rgba.r; + } + } + break; + + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = true; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + m_FILLER = (image.w < 4) ? (4-image.w) : image.w%4; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + m_bfh.Type = BMP_IDENTIFIER; + m_bfh.Size = 0; + m_bfh.Reserved1 = 0; + m_bfh.OffBits = sizeof(BITMAPFILE_HEADER) + sizeof(BITMAPINFO_HEADER); + + m_bih.Size = 40; + m_bih.Width = writeimage.w; + m_bih.Height = writeimage.h; + m_bih.Planes = 1; + m_bih.BitCount = 24; + m_bih.Compression = BI_RGB; + m_bih.SizeImage = 0; + m_bih.XPelsPerMeter = 0; + m_bih.YPelsPerMeter = 0; + m_bih.ClrUsed = 0; + m_bih.ClrImportant = 0; + + if(!fws.writeK(&m_bfh, sizeof(BITMAPFILE_HEADER))) + return SQE_W_ERROR; + + if(!fws.writeK(&m_bih, sizeof(BITMAPINFO_HEADER))) + return SQE_W_ERROR; + + return SQE_OK; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + s8 fillchar = '0'; + RGB rgb; + + for(s32 x = 0;x < writeimage.w;x++) + { + rgb.r = scan[x].b; + rgb.g = scan[x].g; + rgb.b = scan[x].r; + + if(!fws.writeK(&rgb, sizeof(RGB))) + return SQE_W_ERROR; + } + + if(m_FILLER) + { + for(s32 s = 0;s < m_FILLER;s++) + fws.writeK(&fillchar, sizeof(s8)); + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("bmp"); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_bmp/fmt_codec_bmp_defs.h b/kernel/kls_bmp/fmt_codec_bmp_defs.h new file mode 100644 index 0000000..12bc3be --- /dev/null +++ b/kernel/kls_bmp/fmt_codec_bmp_defs.h @@ -0,0 +1,58 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQIURREL_READ_IMAGE_bmp +#define KSQUIRREL_READ_IMAGE_bmp + +/* Compression type */ +#define BI_RGB 0L +#define BI_RLE8 1L +#define BI_RLE4 2L +#define BI_BITFIELDS 3L + +#define BMP_IDENTIFIER 0x4D42 + +struct BITMAPFILE_HEADER +{ + u16 Type; /* "BM" */ + u32 Size; + u32 Reserved1; + u32 OffBits; + +}PACKED; + +struct BITMAPINFO_HEADER +{ + u32 Size; + u32 Width; + u32 Height; + u16 Planes; + u16 BitCount; + u32 Compression; + u32 SizeImage; + u32 XPelsPerMeter; + u32 YPelsPerMeter; + u32 ClrUsed; + u32 ClrImportant; + +}PACKED; + +#endif diff --git a/kernel/kls_camera/Makefile.am b/kernel/kls_camera/Makefile.am new file mode 100644 index 0000000..275b9c4 --- /dev/null +++ b/kernel/kls_camera/Makefile.am @@ -0,0 +1,39 @@ +INCLUDES = -I../include + +# shut up gcc +CFLAGS = -O4 + +bin_PROGRAMS = ksquirrel-libs-dcraw +bin_SCRIPTS = ksquirrel-libs-camera2ppm + +ksquirrel_libs_dcraw_SOURCES = dcraw.c + +if CAMERA_NO_JPEG +camera_jpeg = -DNO_JPEG +else +nojpeg_opt = -ljpeg +endif + +if CAMERA_NO_CMS +camera_cms = -DNO_LCMS +else +nocms_opt = ${lcms_LIBS} +endif + +ksquirrel_libs_dcraw_LDADD = ${nojpeg_opt} ${nocms_opt} -lm +ksquirrel_libs_dcraw_CFLAGS = ${camera_jpeg} ${camera_cms} ${lcms_CFLAGS} + +pkglib_LTLIBRARIES = libkls_camera.la + +libkls_camera_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_camera_la_LDFLAGS = ${SQ_RELEASE} +libkls_camera_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = ${camera_cms} -DCAMERA_UI=\"${pkgdatadir}/libkls_camera.so.ui\" -DCODEC_CAMERA -DCODEC_ANOTHER -DKLDCRAW_S=\"${bindir}/ksquirrel-libs-camera2ppm\" -DKLDCRAW=\"${bindir}/ksquirrel-libs-dcraw\" + +EXTRA_DIST = libkls_camera.so.ui ksquirrel-libs-camera2ppm.in + +install-data-am: + $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) + $(INSTALL) --mode=0644 libkls_camera.so.ui $(DESTDIR)$(pkgdatadir)/libkls_camera.so.ui diff --git a/kernel/kls_camera/dcraw.c b/kernel/kls_camera/dcraw.c new file mode 100644 index 0000000..0eea8e1 --- /dev/null +++ b/kernel/kls_camera/dcraw.c @@ -0,0 +1,8269 @@ +/* + dcraw.c -- Dave Coffin's raw photo decoder + Copyright 1997-2007 by Dave Coffin, dcoffin a cybercom o net + + This is a command-line ANSI C program to convert raw photos from + any digital camera on any computer running any operating system. + + No license is required to download and use dcraw.c. However, + to lawfully redistribute dcraw, you must either (a) offer, at + no extra charge, full source code* for all executable files + containing RESTRICTED functions, (b) distribute this code under + the GPL Version 2 or later, (c) remove all RESTRICTED functions, + re-implement them, or copy them from an earlier, unrestricted + Revision of dcraw.c, or (d) purchase a license from the author. + + The functions that process Foveon images have been RESTRICTED + since Revision 1.237. All other code remains free for all uses. + + *If you have not modified dcraw.c in any way, a link to my + homepage qualifies as "full source code". + + $Revision: 1.394 $ + $Date: 2007/11/04 02:18:54 $ + */ + +#define VERSION "8.79" + +#define _GNU_SOURCE +#define _USE_MATH_DEFINES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* + NO_JPEG disables decoding of compressed Kodak DC120 files. + NO_LCMS disables the "-p" option. + */ +#ifndef NO_JPEG +#include +#endif +#ifndef NO_LCMS +#include +#endif +#ifdef LOCALEDIR +#include +#define _(String) gettext(String) +#else +#define _(String) (String) +#endif +#define fgetc getc_unlocked +#ifdef DJGPP +#define fseeko fseek +#define ftello ftell +#endif +#ifdef __CYGWIN__ +#include +#endif +#ifdef WIN32 +#include +#include +#pragma comment(lib, "ws2_32.lib") +#define snprintf _snprintf +#define strcasecmp stricmp +#define strncasecmp strnicmp +typedef __int64 INT64; +typedef unsigned __int64 UINT64; +#else +#include +#include +#include +typedef long long INT64; +typedef unsigned long long UINT64; +#endif + +#ifdef LJPEG_DECODE +#error Please compile dcraw.c by itself. +#error Do not link it with ljpeg_decode. +#endif + +#ifndef LONG_BIT +#define LONG_BIT (8 * sizeof (long)) +#endif + +#define ushort UshORt +typedef unsigned char uchar; +typedef unsigned short ushort; + +/* + All global variables are defined here, and all functions that + access them are prefixed with "CLASS". Note that a thread-safe + C++ class cannot have non-const static local variables. + */ +FILE *ifp; +short order; +char *ifname, *meta_data; +char cdesc[5], desc[512], make[64], model[64], model2[64], artist[64]; +float flash_used, canon_ev, iso_speed, shutter, aperture, focal_len; +time_t timestamp; +unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id; +off_t strip_offset, data_offset; +off_t thumb_offset, meta_offset, profile_offset; +unsigned thumb_length, meta_length, profile_length; +unsigned thumb_misc, *oprof, fuji_layout, shot_select=0, multi_out=0; +unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress; +unsigned black, maximum, mix_green, raw_color, use_gamma, zero_is_bad; +unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error; +unsigned tile_width, tile_length; +ushort raw_height, raw_width, height, width, top_margin, left_margin; +ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height; +int flip, tiff_flip, colors; +double pixel_aspect, aber[4]={1,1,1,1}; +ushort (*image)[4], white[8][8], curve[0x4001], cr2_slice[3], sraw_mul[4]; +float bright=1, user_mul[4]={0,0,0,0}, threshold=0; +int half_size=0, four_color_rgb=0, document_mode=0, highlight=0; +int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=-1; +int output_color=1, output_bps=8, output_tiff=0, med_passes=0; +unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX }; +float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4]; +const double xyz_rgb[3][3] = { /* XYZ from RGB */ + { 0.412453, 0.357580, 0.180423 }, + { 0.212671, 0.715160, 0.072169 }, + { 0.019334, 0.119193, 0.950227 } }; +const float d65_white[3] = { 0.950456, 1, 1.088754 }; +int histogram[4][0x2000]; +void (*write_thumb)(FILE *), (*write_fun)(FILE *); +void (*load_raw)(), (*thumb_load_raw)(); +jmp_buf failure; + +struct decode { + struct decode *branch[2]; + int leaf; +} first_decode[2048], *second_decode, *free_decode; + +struct { + int width, height, bps, comp, phint, offset, flip, samples, bytes; +} tiff_ifd[10]; + +struct { + int format, key_off, black, black_off, split_col, tag_21a; + float tag_210; +} ph1; + +#define CLASS + +#define FORC3 for (c=0; c < 3; c++) +#define FORC4 for (c=0; c < 4; c++) +#define FORCC for (c=0; c < colors; c++) + +#define SQR(x) ((x)*(x)) +#define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define LIM(x,min,max) MAX(min,MIN(x,max)) +#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y)) +#define CLIP(x) LIM(x,0,65535) +#define SWAP(a,b) { a ^= b; a ^= (b ^= a); } + +/* + In order to inline this calculation, I make the risky + assumption that all filter patterns can be described + by a repeating pattern of eight rows and two columns + + Do not use the FC or BAYER macros with the Leaf CatchLight, + because its pattern is 16x16, not 2x8. + + Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2 + + PowerShot 600 PowerShot A50 PowerShot Pro70 Pro90 & G1 + 0xe1e4e1e4: 0x1b4e4b1e: 0x1e4b4e1b: 0xb4b4b4b4: + + 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 + 0 G M G M G M 0 C Y C Y C Y 0 Y C Y C Y C 0 G M G M G M + 1 C Y C Y C Y 1 M G M G M G 1 M G M G M G 1 Y C Y C Y C + 2 M G M G M G 2 Y C Y C Y C 2 C Y C Y C Y + 3 C Y C Y C Y 3 G M G M G M 3 G M G M G M + 4 C Y C Y C Y 4 Y C Y C Y C + PowerShot A5 5 G M G M G M 5 G M G M G M + 0x1e4e1e4e: 6 Y C Y C Y C 6 C Y C Y C Y + 7 M G M G M G 7 M G M G M G + 0 1 2 3 4 5 + 0 C Y C Y C Y + 1 G M G M G M + 2 C Y C Y C Y + 3 M G M G M G + + All RGB cameras use one of these Bayer grids: + + 0x16161616: 0x61616161: 0x49494949: 0x94949494: + + 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 + 0 B G B G B G 0 G R G R G R 0 G B G B G B 0 R G R G R G + 1 G R G R G R 1 B G B G B G 1 R G R G R G 1 G B G B G B + 2 B G B G B G 2 G R G R G R 2 G B G B G B 2 R G R G R G + 3 G R G R G R 3 B G B G B G 3 R G R G R G 3 G B G B G B + */ + +#define FC(row,col) \ + (filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) + +#define BAYER(row,col) \ + image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)] + +#define BAYER2(row,col) \ + image[((row) >> shrink)*iwidth + ((col) >> shrink)][fc(row,col)] + +int CLASS fc (int row, int col) +{ + static const char filter[16][16] = + { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 }, + { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 }, + { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 }, + { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 }, + { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 }, + { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 }, + { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 }, + { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 }, + { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 }, + { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 }, + { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 }, + { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 }, + { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 }, + { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 }, + { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 }, + { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } }; + + if (filters != 1) return FC(row,col); + return filter[(row+top_margin) & 15][(col+left_margin) & 15]; +} + +#ifndef __GLIBC__ +char *my_memmem (char *haystack, size_t haystacklen, + char *needle, size_t needlelen) +{ + char *c; + for (c = haystack; c <= haystack + haystacklen - needlelen; c++) + if (!memcmp (c, needle, needlelen)) + return c; + return 0; +} +#define memmem my_memmem +#endif + +void CLASS merror (void *ptr, char *where) +{ + if (ptr) return; + fprintf (stderr,_("%s: Out of memory in %s\n"), ifname, where); + longjmp (failure, 1); +} + +void CLASS derror() +{ + if (!data_error) { + fprintf (stderr, "%s: ", ifname); + if (feof(ifp)) + fprintf (stderr,_("Unexpected end of file\n")); + else + fprintf (stderr,_("Corrupt data near 0x%llx\n"), (INT64) ftello(ifp)); + } + data_error = 1; +} + +ushort CLASS sget2 (uchar *s) +{ + if (order == 0x4949) /* "II" means little-endian */ + return s[0] | s[1] << 8; + else /* "MM" means big-endian */ + return s[0] << 8 | s[1]; +} + +ushort CLASS get2() +{ + uchar str[2] = { 0xff,0xff }; + fread (str, 1, 2, ifp); + return sget2(str); +} + +unsigned CLASS sget4 (uchar *s) +{ + if (order == 0x4949) + return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; + else + return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]; +} +#define sget4(s) sget4((uchar *)s) + +unsigned CLASS get4() +{ + uchar str[4] = { 0xff,0xff,0xff,0xff }; + fread (str, 1, 4, ifp); + return sget4(str); +} + +unsigned CLASS getint (int type) +{ + return type == 3 ? get2() : get4(); +} + +float CLASS int_to_float (int i) +{ + union { int i; float f; } u; + u.i = i; + return u.f; +} + +double CLASS getreal (int type) +{ + union { char c[8]; double d; } u; + int i, rev; + + switch (type) { + case 3: return (unsigned short) get2(); + case 4: return (unsigned int) get4(); + case 5: u.d = (unsigned int) get4(); + return u.d / (unsigned int) get4(); + case 8: return (signed short) get2(); + case 9: return (signed int) get4(); + case 10: u.d = (signed int) get4(); + return u.d / (signed int) get4(); + case 11: return int_to_float (get4()); + case 12: + rev = 7 * ((order == 0x4949) == (ntohs(0x1234) == 0x1234)); + for (i=0; i < 8; i++) + u.c[i ^ rev] = fgetc(ifp); + return u.d; + default: return fgetc(ifp); + } +} +#define getrat() getreal(10) + +void CLASS read_shorts (ushort *pixel, int count) +{ + if (fread (pixel, 2, count, ifp) < count) derror(); + if ((order == 0x4949) == (ntohs(0x1234) == 0x1234)) + swab (pixel, pixel, count*2); +} + +void CLASS canon_600_fixed_wb (int temp) +{ + static const short mul[4][5] = { + { 667, 358,397,565,452 }, + { 731, 390,367,499,517 }, + { 1119, 396,348,448,537 }, + { 1399, 485,431,508,688 } }; + int lo, hi, i; + float frac=0; + + for (lo=4; --lo; ) + if (*mul[lo] <= temp) break; + for (hi=0; hi < 3; hi++) + if (*mul[hi] >= temp) break; + if (lo != hi) + frac = (float) (temp - *mul[lo]) / (*mul[hi] - *mul[lo]); + for (i=1; i < 5; i++) + pre_mul[i-1] = 1 / (frac * mul[hi][i] + (1-frac) * mul[lo][i]); +} + +/* Return values: 0 = white 1 = near white 2 = not white */ +int CLASS canon_600_color (int ratio[2], int mar) +{ + int clipped=0, target, miss; + + if (flash_used) { + if (ratio[1] < -104) + { ratio[1] = -104; clipped = 1; } + if (ratio[1] > 12) + { ratio[1] = 12; clipped = 1; } + } else { + if (ratio[1] < -264 || ratio[1] > 461) return 2; + if (ratio[1] < -50) + { ratio[1] = -50; clipped = 1; } + if (ratio[1] > 307) + { ratio[1] = 307; clipped = 1; } + } + target = flash_used || ratio[1] < 197 + ? -38 - (398 * ratio[1] >> 10) + : -123 + (48 * ratio[1] >> 10); + if (target - mar <= ratio[0] && + target + 20 >= ratio[0] && !clipped) return 0; + miss = target - ratio[0]; + if (abs(miss) >= mar*4) return 2; + if (miss < -20) miss = -20; + if (miss > mar) miss = mar; + ratio[0] = target - miss; + return 1; +} + +void CLASS canon_600_auto_wb() +{ + int mar, row, col, i, j, st, count[] = { 0,0 }; + int test[8], total[2][8], ratio[2][2], stat[2]; + + memset (&total, 0, sizeof total); + i = canon_ev + 0.5; + if (i < 10) mar = 150; + else if (i > 12) mar = 20; + else mar = 280 - 20 * i; + if (flash_used) mar = 80; + for (row=14; row < height-14; row+=4) + for (col=10; col < width; col+=2) { + for (i=0; i < 8; i++) + test[(i & 4) + FC(row+(i >> 1),col+(i & 1))] = + BAYER(row+(i >> 1),col+(i & 1)); + for (i=0; i < 8; i++) + if (test[i] < 150 || test[i] > 1500) goto next; + for (i=0; i < 4; i++) + if (abs(test[i] - test[i+4]) > 50) goto next; + for (i=0; i < 2; i++) { + for (j=0; j < 4; j+=2) + ratio[i][j >> 1] = ((test[i*4+j+1]-test[i*4+j]) << 10) / test[i*4+j]; + stat[i] = canon_600_color (ratio[i], mar); + } + if ((st = stat[0] | stat[1]) > 1) goto next; + for (i=0; i < 2; i++) + if (stat[i]) + for (j=0; j < 2; j++) + test[i*4+j*2+1] = test[i*4+j*2] * (0x400 + ratio[i][j]) >> 10; + for (i=0; i < 8; i++) + total[st][i] += test[i]; + count[st]++; +next: ; + } + if (count[0] | count[1]) { + st = count[0]*200 < count[1]; + for (i=0; i < 4; i++) + pre_mul[i] = 1.0 / (total[st][i] + total[st][i+4]); + } +} + +void CLASS canon_600_coeff() +{ + static const short table[6][12] = { + { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 }, + { -1203,1715,-1136,1648, 1388,-876,267,245, -1641,2153,3921,-3409 }, + { -615,1127,-1563,2075, 1437,-925,509,3, -756,1268,2519,-2007 }, + { -190,702,-1886,2398, 2153,-1641,763,-251, -452,964,3040,-2528 }, + { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 }, + { -807,1319,-1785,2297, 1388,-876,769,-257, -230,742,2067,-1555 } }; + int t=0, i, c; + float mc, yc; + + mc = pre_mul[1] / pre_mul[2]; + yc = pre_mul[3] / pre_mul[2]; + if (mc > 1 && mc <= 1.28 && yc < 0.8789) t=1; + if (mc > 1.28 && mc <= 2) { + if (yc < 0.8789) t=3; + else if (yc <= 2) t=4; + } + if (flash_used) t=5; + for (raw_color = i=0; i < 3; i++) + FORCC rgb_cam[i][c] = table[t][i*4 + c] / 1024.0; +} + +void CLASS canon_600_load_raw() +{ + uchar data[1120], *dp; + ushort pixel[896], *pix; + int irow, row, col, val; + static const short mul[4][2] = + { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } }; + + for (irow=row=0; irow < height; irow++) { + if (fread (data, 1, raw_width*5/4, ifp) < raw_width*5/4) derror(); + for (dp=data, pix=pixel; dp < data+1120; dp+=10, pix+=8) { + pix[0] = (dp[0] << 2) + (dp[1] >> 6 ); + pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3); + pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3); + pix[3] = (dp[4] << 2) + (dp[1] & 3); + pix[4] = (dp[5] << 2) + (dp[9] & 3); + pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3); + pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3); + pix[7] = (dp[8] << 2) + (dp[9] >> 6 ); + } + for (col=0; col < width; col++) + BAYER(row,col) = pixel[col]; + for (col=width; col < raw_width; col++) + black += pixel[col]; + if ((row+=2) > height) row = 1; + } + if (raw_width > width) + black = black / ((raw_width - width) * height) - 4; + for (row=0; row < height; row++) + for (col=0; col < width; col++) { + if ((val = BAYER(row,col) - black) < 0) val = 0; + val = val * mul[row & 3][col & 1] >> 9; + BAYER(row,col) = val; + } + canon_600_fixed_wb(1311); + canon_600_auto_wb(); + canon_600_coeff(); + maximum = (0x3ff - black) * 1109 >> 9; + black = 0; +} + +void CLASS remove_zeroes() +{ + unsigned row, col, tot, n, r, c; + + for (row=0; row < height; row++) + for (col=0; col < width; col++) + if (BAYER(row,col) == 0) { + tot = n = 0; + for (r = row-2; r <= row+2; r++) + for (c = col-2; c <= col+2; c++) + if (r < height && c < width && + FC(r,c) == FC(row,col) && BAYER(r,c)) + tot += (n++,BAYER(r,c)); + if (n) BAYER(row,col) = tot/n; + } +} + +int CLASS canon_s2is() +{ + unsigned row; + + for (row=0; row < 100; row++) { + fseek (ifp, row*3340 + 3284, SEEK_SET); + if (getc(ifp) > 15) return 1; + } + return 0; +} + +void CLASS canon_a5_load_raw() +{ + ushort data[2335], *dp, pixel; + int vbits=0, buf=0, row, col, bc=0; + + order = 0x4949; + for (row=-top_margin; row < raw_height-top_margin; row++) { + read_shorts (dp=data, raw_width * 10 / 16); + for (col=-left_margin; col < raw_width-left_margin; col++) { + if (vbits < 10) + buf = (vbits += 16, (buf << 16) + *dp++); + pixel = buf >> (vbits -= 10) & 0x3ff; + if ((unsigned) row < height && (unsigned) col < width) + BAYER(row,col) = pixel; + else if (col > 1-left_margin && col != width) + black += (bc++,pixel); + } + } + if (bc) black /= bc; + maximum = 0x3ff; + if (raw_width > 1600) remove_zeroes(); +} + +/* + getbits(-1) initializes the buffer + getbits(n) where 0 <= n <= 25 returns an n-bit integer + */ +unsigned CLASS getbits (int nbits) +{ + static unsigned bitbuf=0; + static int vbits=0, reset=0; + unsigned c; + + if (nbits == -1) + return bitbuf = vbits = reset = 0; + if (nbits == 0 || reset) return 0; + while (vbits < nbits) { + if ((c = fgetc(ifp)) == EOF) derror(); + if ((reset = zero_after_ff && c == 0xff && fgetc(ifp))) return 0; + bitbuf = (bitbuf << 8) + (uchar) c; + vbits += 8; + } + vbits -= nbits; + return bitbuf << (32-nbits-vbits) >> (32-nbits); +} + +void CLASS init_decoder() +{ + memset (first_decode, 0, sizeof first_decode); + free_decode = first_decode; +} + +/* + Construct a decode tree according the specification in *source. + The first 16 bytes specify how many codes should be 1-bit, 2-bit + 3-bit, etc. Bytes after that are the leaf values. + + For example, if the source is + + { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, + 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff }, + + then the code is + + 00 0x04 + 010 0x03 + 011 0x05 + 100 0x06 + 101 0x02 + 1100 0x07 + 1101 0x01 + 11100 0x08 + 11101 0x09 + 11110 0x00 + 111110 0x0a + 1111110 0x0b + 1111111 0xff + */ +uchar * CLASS make_decoder (const uchar *source, int level) +{ + struct decode *cur; + static int leaf; + int i, next; + + if (level==0) leaf=0; + cur = free_decode++; + if (free_decode > first_decode+2048) { + fprintf (stderr,_("%s: decoder table overflow\n"), ifname); + longjmp (failure, 2); + } + for (i=next=0; i <= leaf && next < 16; ) + i += source[next++]; + if (i > leaf) { + if (level < next) { + cur->branch[0] = free_decode; + make_decoder (source, level+1); + cur->branch[1] = free_decode; + make_decoder (source, level+1); + } else + cur->leaf = source[16 + leaf++]; + } + return (uchar *) source + 16 + leaf; +} + +void CLASS crw_init_tables (unsigned table) +{ + static const uchar first_tree[3][29] = { + { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, + 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff }, + { 0,2,2,3,1,1,1,1,2,0,0,0,0,0,0,0, + 0x03,0x02,0x04,0x01,0x05,0x00,0x06,0x07,0x09,0x08,0x0a,0x0b,0xff }, + { 0,0,6,3,1,1,2,0,0,0,0,0,0,0,0,0, + 0x06,0x05,0x07,0x04,0x08,0x03,0x09,0x02,0x00,0x0a,0x01,0x0b,0xff }, + }; + static const uchar second_tree[3][180] = { + { 0,2,2,2,1,4,2,1,2,5,1,1,0,0,0,139, + 0x03,0x04,0x02,0x05,0x01,0x06,0x07,0x08, + 0x12,0x13,0x11,0x14,0x09,0x15,0x22,0x00,0x21,0x16,0x0a,0xf0, + 0x23,0x17,0x24,0x31,0x32,0x18,0x19,0x33,0x25,0x41,0x34,0x42, + 0x35,0x51,0x36,0x37,0x38,0x29,0x79,0x26,0x1a,0x39,0x56,0x57, + 0x28,0x27,0x52,0x55,0x58,0x43,0x76,0x59,0x77,0x54,0x61,0xf9, + 0x71,0x78,0x75,0x96,0x97,0x49,0xb7,0x53,0xd7,0x74,0xb6,0x98, + 0x47,0x48,0x95,0x69,0x99,0x91,0xfa,0xb8,0x68,0xb5,0xb9,0xd6, + 0xf7,0xd8,0x67,0x46,0x45,0x94,0x89,0xf8,0x81,0xd5,0xf6,0xb4, + 0x88,0xb1,0x2a,0x44,0x72,0xd9,0x87,0x66,0xd4,0xf5,0x3a,0xa7, + 0x73,0xa9,0xa8,0x86,0x62,0xc7,0x65,0xc8,0xc9,0xa1,0xf4,0xd1, + 0xe9,0x5a,0x92,0x85,0xa6,0xe7,0x93,0xe8,0xc1,0xc6,0x7a,0x64, + 0xe1,0x4a,0x6a,0xe6,0xb3,0xf1,0xd3,0xa5,0x8a,0xb2,0x9a,0xba, + 0x84,0xa4,0x63,0xe5,0xc5,0xf3,0xd2,0xc4,0x82,0xaa,0xda,0xe4, + 0xf2,0xca,0x83,0xa3,0xa2,0xc3,0xea,0xc2,0xe2,0xe3,0xff,0xff }, + { 0,2,2,1,4,1,4,1,3,3,1,0,0,0,0,140, + 0x02,0x03,0x01,0x04,0x05,0x12,0x11,0x06, + 0x13,0x07,0x08,0x14,0x22,0x09,0x21,0x00,0x23,0x15,0x31,0x32, + 0x0a,0x16,0xf0,0x24,0x33,0x41,0x42,0x19,0x17,0x25,0x18,0x51, + 0x34,0x43,0x52,0x29,0x35,0x61,0x39,0x71,0x62,0x36,0x53,0x26, + 0x38,0x1a,0x37,0x81,0x27,0x91,0x79,0x55,0x45,0x28,0x72,0x59, + 0xa1,0xb1,0x44,0x69,0x54,0x58,0xd1,0xfa,0x57,0xe1,0xf1,0xb9, + 0x49,0x47,0x63,0x6a,0xf9,0x56,0x46,0xa8,0x2a,0x4a,0x78,0x99, + 0x3a,0x75,0x74,0x86,0x65,0xc1,0x76,0xb6,0x96,0xd6,0x89,0x85, + 0xc9,0xf5,0x95,0xb4,0xc7,0xf7,0x8a,0x97,0xb8,0x73,0xb7,0xd8, + 0xd9,0x87,0xa7,0x7a,0x48,0x82,0x84,0xea,0xf4,0xa6,0xc5,0x5a, + 0x94,0xa4,0xc6,0x92,0xc3,0x68,0xb5,0xc8,0xe4,0xe5,0xe6,0xe9, + 0xa2,0xa3,0xe3,0xc2,0x66,0x67,0x93,0xaa,0xd4,0xd5,0xe7,0xf8, + 0x88,0x9a,0xd7,0x77,0xc4,0x64,0xe2,0x98,0xa5,0xca,0xda,0xe8, + 0xf3,0xf6,0xa9,0xb2,0xb3,0xf2,0xd2,0x83,0xba,0xd3,0xff,0xff }, + { 0,0,6,2,1,3,3,2,5,1,2,2,8,10,0,117, + 0x04,0x05,0x03,0x06,0x02,0x07,0x01,0x08, + 0x09,0x12,0x13,0x14,0x11,0x15,0x0a,0x16,0x17,0xf0,0x00,0x22, + 0x21,0x18,0x23,0x19,0x24,0x32,0x31,0x25,0x33,0x38,0x37,0x34, + 0x35,0x36,0x39,0x79,0x57,0x58,0x59,0x28,0x56,0x78,0x27,0x41, + 0x29,0x77,0x26,0x42,0x76,0x99,0x1a,0x55,0x98,0x97,0xf9,0x48, + 0x54,0x96,0x89,0x47,0xb7,0x49,0xfa,0x75,0x68,0xb6,0x67,0x69, + 0xb9,0xb8,0xd8,0x52,0xd7,0x88,0xb5,0x74,0x51,0x46,0xd9,0xf8, + 0x3a,0xd6,0x87,0x45,0x7a,0x95,0xd5,0xf6,0x86,0xb4,0xa9,0x94, + 0x53,0x2a,0xa8,0x43,0xf5,0xf7,0xd4,0x66,0xa7,0x5a,0x44,0x8a, + 0xc9,0xe8,0xc8,0xe7,0x9a,0x6a,0x73,0x4a,0x61,0xc7,0xf4,0xc6, + 0x65,0xe9,0x72,0xe6,0x71,0x91,0x93,0xa6,0xda,0x92,0x85,0x62, + 0xf3,0xc5,0xb2,0xa4,0x84,0xba,0x64,0xa5,0xb3,0xd2,0x81,0xe5, + 0xd3,0xaa,0xc4,0xca,0xf2,0xb1,0xe4,0xd1,0x83,0x63,0xea,0xc3, + 0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff } + }; + if (table > 2) table = 2; + init_decoder(); + make_decoder ( first_tree[table], 0); + second_decode = free_decode; + make_decoder (second_tree[table], 0); +} + +/* + Return 0 if the image starts with compressed data, + 1 if it starts with uncompressed low-order bits. + + In Canon compressed data, 0xff is always followed by 0x00. + */ +int CLASS canon_has_lowbits() +{ + uchar test[0x4000]; + int ret=1, i; + + fseek (ifp, 0, SEEK_SET); + fread (test, 1, sizeof test, ifp); + for (i=540; i < sizeof test - 1; i++) + if (test[i] == 0xff) { + if (test[i+1]) return 1; + ret=0; + } + return ret; +} + +void CLASS canon_compressed_load_raw() +{ + ushort *pixel, *prow; + int nblocks, lowbits, i, row, r, col, save, val; + unsigned irow, icol; + struct decode *decode, *dindex; + int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2]; + uchar c; + + crw_init_tables (tiff_compress); + pixel = (ushort *) calloc (raw_width*8, sizeof *pixel); + merror (pixel, "canon_compressed_load_raw()"); + lowbits = canon_has_lowbits(); + if (!lowbits) maximum = 0x3ff; + fseek (ifp, 540 + lowbits*raw_height*raw_width/4, SEEK_SET); + zero_after_ff = 1; + getbits(-1); + for (row=0; row < raw_height; row+=8) { + nblocks = MIN (8, raw_height-row) * raw_width >> 6; + for (block=0; block < nblocks; block++) { + memset (diffbuf, 0, sizeof diffbuf); + decode = first_decode; + for (i=0; i < 64; i++ ) { + for (dindex=decode; dindex->branch[0]; ) + dindex = dindex->branch[getbits(1)]; + leaf = dindex->leaf; + decode = second_decode; + if (leaf == 0 && i) break; + if (leaf == 0xff) continue; + i += leaf >> 4; + len = leaf & 15; + if (len == 0) continue; + diff = getbits(len); + if ((diff & (1 << (len-1))) == 0) + diff -= (1 << len) - 1; + if (i < 64) diffbuf[i] = diff; + } + diffbuf[0] += carry; + carry = diffbuf[0]; + for (i=0; i < 64; i++ ) { + if (pnum++ % raw_width == 0) + base[0] = base[1] = 512; + if ((pixel[(block << 6) + i] = base[i & 1] += diffbuf[i]) >> 10) + derror(); + } + } + if (lowbits) { + save = ftell(ifp); + fseek (ifp, 26 + row*raw_width/4, SEEK_SET); + for (prow=pixel, i=0; i < raw_width*2; i++) { + c = fgetc(ifp); + for (r=0; r < 8; r+=2, prow++) { + val = (*prow << 2) + ((c >> r) & 3); + if (raw_width == 2672 && val < 512) val += 2; + *prow = val; + } + } + fseek (ifp, save, SEEK_SET); + } + for (r=0; r < 8; r++) { + irow = row - top_margin + r; + if (irow >= height) continue; + for (col=0; col < raw_width; col++) { + icol = col - left_margin; + if (icol < width) + BAYER(irow,icol) = pixel[r*raw_width+col]; + else + black += pixel[r*raw_width+col]; + } + } + } + free (pixel); + if (raw_width > width) + black /= (raw_width - width) * height; +} + +/* + Not a full implementation of Lossless JPEG, just + enough to decode Canon, Kodak and Adobe DNG images. + */ +struct jhead { + int bits, high, wide, clrs, psv, restart, vpred[4]; + struct decode *huff[4]; + ushort *row; +}; + +int CLASS ljpeg_start (struct jhead *jh, int info_only) +{ + int i, tag, len; + uchar data[0x10000], *dp; + + init_decoder(); + memset (jh, 0, sizeof *jh); + for (i=0; i < 4; i++) + jh->huff[i] = free_decode; + jh->restart = INT_MAX; + fread (data, 2, 1, ifp); + if (data[1] != 0xd8) return 0; + do { + fread (data, 2, 2, ifp); + tag = data[0] << 8 | data[1]; + len = (data[2] << 8 | data[3]) - 2; + if (tag <= 0xff00) return 0; + fread (data, 1, len, ifp); + switch (tag) { + case 0xffc0: data[7] = 0; + case 0xffc3: + jh->bits = data[0]; + jh->high = data[1] << 8 | data[2]; + jh->wide = data[3] << 8 | data[4]; + jh->clrs = data[5] + (data[7] == 0x21); + if (len == 9 && !dng_version) getc(ifp); + break; + case 0xffc4: + if (info_only) break; + for (dp = data; dp < data+len && *dp < 4; ) { + jh->huff[*dp] = free_decode; + dp = make_decoder (++dp, 0); + } + break; + case 0xffda: + jh->psv = data[1+data[0]*2]; + break; + case 0xffdd: + jh->restart = data[0] << 8 | data[1]; + } + } while (tag != 0xffda); + if (info_only) return 1; + if (jh->clrs == 4) { + jh->huff[3] = jh->huff[2] = jh->huff[1]; + jh->huff[1] = jh->huff[0]; + } + jh->row = (ushort *) calloc (jh->wide*jh->clrs, 4); + merror (jh->row, "ljpeg_start()"); + return zero_after_ff = 1; +} + +int CLASS ljpeg_diff (struct decode *dindex) +{ + int len, diff; + + while (dindex->branch[0]) + dindex = dindex->branch[getbits(1)]; + len = dindex->leaf; + if (len == 16 && (!dng_version || dng_version >= 0x1010000)) + return -32768; + diff = getbits(len); + if ((diff & (1 << (len-1))) == 0) + diff -= (1 << len) - 1; + return diff; +} + +ushort * CLASS ljpeg_row (int jrow, struct jhead *jh) +{ + int col, c, diff, pred; + ushort mark=0, *row[3]; + + if (jrow * jh->wide % jh->restart == 0) { + FORC4 jh->vpred[c] = 1 << (jh->bits-1); + if (jrow) + do mark = (mark << 8) + (c = fgetc(ifp)); + while (c != EOF && mark >> 4 != 0xffd); + getbits(-1); + } + FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1); + for (col=0; col < jh->wide; col++) + for (c=0; c < jh->clrs; c++) { + diff = ljpeg_diff (jh->huff[c]); + if (jh->clrs == 4 && c < 2 && (col | c)) + pred = row[0][(c << 1)-3]; + else if (col) pred = row[0][-jh->clrs]; + else pred = (jh->vpred[c] += diff) - diff; + if (jrow && col) switch (jh->psv) { + case 1: break; + case 2: pred = row[1][0]; break; + case 3: pred = row[1][-jh->clrs]; break; + case 4: pred = pred + row[1][0] - row[1][-jh->clrs]; break; + case 5: pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1); break; + case 6: pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1); break; + case 7: pred = (pred + row[1][0]) >> 1; break; + default: pred = 0; + } + if ((**row = pred + diff) >> jh->bits) derror(); + row[0]++; row[1]++; + } + return row[2]; +} + +void CLASS lossless_jpeg_load_raw() +{ + int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0; + struct jhead jh; + int min=INT_MAX; + ushort *rp; + + if (!ljpeg_start (&jh, 0)) return; + jwide = jh.wide * jh.clrs; + + for (jrow=0; jrow < jh.high; jrow++) { + rp = ljpeg_row (jrow, &jh); + for (jcol=0; jcol < jwide; jcol++) { + val = *rp++; + if (jh.bits <= 12) + val = curve[val]; + if (cr2_slice[0]) { + jidx = jrow*jwide + jcol; + i = jidx / (cr2_slice[1]*jh.high); + if ((j = i >= cr2_slice[0])) + i = cr2_slice[0]; + jidx -= i * (cr2_slice[1]*jh.high); + row = jidx / cr2_slice[1+j]; + col = jidx % cr2_slice[1+j] + i*cr2_slice[1]; + } + if (raw_width == 3984 && (col -= 2) < 0) + col += (row--,raw_width); + if ((unsigned) (row-top_margin) < height) { + if ((unsigned) (col-left_margin) < width) { + BAYER(row-top_margin,col-left_margin) = val; + if (min > val) min = val; + } else black += val; + } + if (++col >= raw_width) + col = (row++,0); + } + } + free (jh.row); + if (raw_width > width) + black /= (raw_width - width) * height; + if (!strcasecmp(make,"KODAK")) + black = min; +} + +void CLASS canon_sraw_load_raw() +{ + struct jhead jh; + short *rp=0, *ip; + int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c; + + if (!ljpeg_start (&jh, 0)) return; + jwide = (jh.wide >>= 1) * 4; + + for (ecol=slice=0; slice <= cr2_slice[0]; slice++) { + scol = ecol; + ecol += cr2_slice[1] >> 1; + if (!cr2_slice[0] || ecol > width-1) ecol = width & -2; + for (row=0; row < height; row++) { + ip = (short *) image[row*width+scol]; + for (col=scol; col < ecol; col+=2, jcol+=4, ip+=8) { + if ((jcol %= jwide) == 0) + rp = (short *) ljpeg_row (jrow++, &jh); + ip[0] = rp[jcol]; + ip[4] = rp[jcol+1]; + ip[1] = (short) (rp[jcol+2] << 2) >> 2; + ip[2] = (short) (rp[jcol+3] << 2) >> 2; + } + } + } + for (row=0; row < height; row++) { + ip = (short *) image[row*width+1]; + for (col=1; col < width-1; col+=2, ip+=8) { + ip[1] = (ip[-3] + ip[5] + 1) >> 1; + ip[2] = (ip[-2] + ip[6] + 1) >> 1; + } + if (col < width) { ip[1] = ip[-3]; ip[2] = ip[-2]; } + ip = (short *) image[row*width]; + for (col=0; col < width; col++, ip+=4) { + pix[0] = ip[2] + ip[0]; + pix[2] = ip[1] + ip[0]; + pix[1] = ((ip[0] << 12) - ip[1]*778 - (ip[2] << 11)) >> 12; + FORC3 ip[c] = CLIP((pix[c] - 512) * sraw_mul[c] >> 10); + } + } + free (jh.row); + maximum = 0x3fff; +} + +void CLASS adobe_copy_pixel (int row, int col, ushort **rp) +{ + unsigned r, c; + + r = row -= top_margin; + c = col -= left_margin; + if (is_raw == 2 && shot_select) (*rp)++; + if (filters) { + if (fuji_width) { + r = row + fuji_width - 1 - (col >> 1); + c = row + ((col+1) >> 1); + } + if (r < height && c < width) + BAYER(r,c) = **rp < 0x1000 ? curve[**rp] : **rp; + *rp += is_raw; + } else { + if (r < height && c < width) + for (c=0; c < tiff_samples; c++) + image[row*width+col][c] = (*rp)[c] < 0x1000 ? curve[(*rp)[c]]:(*rp)[c]; + *rp += tiff_samples; + } + if (is_raw == 2 && shot_select) (*rp)--; +} + +void CLASS adobe_dng_load_raw_lj() +{ + unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col; + struct jhead jh; + ushort *rp; + + while (trow < raw_height) { + save = ftell(ifp); + if (tile_length < INT_MAX) + fseek (ifp, get4(), SEEK_SET); + if (!ljpeg_start (&jh, 0)) break; + jwide = jh.wide; + if (filters) jwide *= jh.clrs; + jwide /= is_raw; + for (row=col=jrow=0; jrow < jh.high; jrow++) { + rp = ljpeg_row (jrow, &jh); + for (jcol=0; jcol < jwide; jcol++) { + adobe_copy_pixel (trow+row, tcol+col, &rp); + if (++col >= tile_width || col >= raw_width) + row += 1 + (col = 0); + } + } + fseek (ifp, save+4, SEEK_SET); + if ((tcol += tile_width) >= raw_width) + trow += tile_length + (tcol = 0); + free (jh.row); + } +} + +void CLASS adobe_dng_load_raw_nc() +{ + ushort *pixel, *rp; + int row, col; + + pixel = (ushort *) calloc (raw_width * tiff_samples, sizeof *pixel); + merror (pixel, "adobe_dng_load_raw_nc()"); + for (row=0; row < raw_height; row++) { + if (tiff_bps == 16) + read_shorts (pixel, raw_width * tiff_samples); + else { + getbits(-1); + for (col=0; col < raw_width * tiff_samples; col++) + pixel[col] = getbits(tiff_bps); + } + for (rp=pixel, col=0; col < raw_width; col++) + adobe_copy_pixel (row, col, &rp); + } + free (pixel); +} + +void CLASS pentax_k10_load_raw() +{ + static const uchar pentax_tree[] = + { 0,2,3,1,1,1,1,1,1,2,0,0,0,0,0,0, + 3,4,2,5,1,6,0,7,8,9,10,11,12 }; + int row, col, diff; + ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2]; + + init_decoder(); + make_decoder (pentax_tree, 0); + getbits(-1); + for (row=0; row < height; row++) + for (col=0; col < raw_width; col++) { + diff = ljpeg_diff (first_decode); + if (col < 2) hpred[col] = vpred[row & 1][col] += diff; + else hpred[col & 1] += diff; + if (col < width) + BAYER(row,col) = hpred[col & 1]; + if (hpred[col & 1] >> 12) derror(); + } +} + +void CLASS nikon_compressed_load_raw() +{ + static const uchar nikon_tree[][32] = { + { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy */ + 5,4,3,6,2,7,1,0,8,9,11,10,12 }, + { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy after split */ + 0x39,0x5a,0x38,0x27,0x16,5,4,3,2,1,0,11,12,12 }, + { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, /* 12-bit lossless */ + 5,4,6,3,7,2,8,1,9,0,10,11,12 }, + { 0,1,4,3,1,1,1,1,1,2,0,0,0,0,0,0, /* 14-bit lossy */ + 5,6,4,7,8,3,9,2,1,0,10,11,12,13,14 }, + { 0,1,5,1,1,1,1,1,1,1,2,0,0,0,0,0, /* 14-bit lossy after split */ + 8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 }, + { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0, /* 14-bit lossless */ + 7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } }; + struct decode *dindex; + ushort ver0, ver1, vpred[2][2], hpred[2], csize; + int i, max, step=0, huff=0, split=0, row, col, len, shl, diff; + + fseek (ifp, meta_offset, SEEK_SET); + ver0 = fgetc(ifp); + ver1 = fgetc(ifp); + if (ver0 == 0x49 || ver1 == 0x58) + fseek (ifp, 2110, SEEK_CUR); + if (ver0 == 0x46) huff = 2; + if (tiff_bps == 14) huff += 3; + read_shorts (vpred[0], 4); + max = 1 << tiff_bps & 0x7fff; + if ((csize = get2()) > 1) + step = max / (csize-1); + if (ver0 == 0x44 && ver1 == 0x20 && step > 0) { + for (i=0; i < csize; i++) + curve[i*step] = get2(); + for (i=0; i < max; i++) + curve[i] = ( curve[i-i%step]*(step-i%step) + + curve[i-i%step+step]*(i%step) ) / step; + fseek (ifp, meta_offset+562, SEEK_SET); + split = get2(); + } else if (ver0 != 0x46 && csize <= 0x4001) + read_shorts (curve, max=csize); + init_decoder(); + make_decoder (nikon_tree[huff], 0); + fseek (ifp, data_offset, SEEK_SET); + getbits(-1); + for (row=0; row < height; row++) { + if (split && row == split) { + init_decoder(); + make_decoder (nikon_tree[huff+1], 0); + } + for (col=0; col < raw_width; col++) { + for (dindex=first_decode; dindex->branch[0]; ) + dindex = dindex->branch[getbits(1)]; + len = dindex->leaf & 15; + shl = dindex->leaf >> 4; + diff = ((getbits(len-shl) << 1) + 1) << shl >> 1; + if ((diff & (1 << (len-1))) == 0) + diff -= (1 << len) - !shl; + if (col < 2) hpred[col] = vpred[row & 1][col] += diff; + else hpred[col & 1] += diff; + if (hpred[col & 1] >= max) derror(); + if ((unsigned) (col-left_margin) < width) + BAYER(row,col-left_margin) = curve[hpred[col & 1] & 0x3fff]; + } + } +} + +void CLASS nikon_load_raw() +{ + int irow, row, col, i; + + getbits(-1); + for (irow=0; irow < height; irow++) { + row = irow; + if (make[0] == 'O' || model[0] == 'E') { + row = irow * 2 % height + irow / (height/2); + if (row == 1 && data_offset == 0) { + fseek (ifp, 0, SEEK_END); + fseek (ifp, ftell(ifp)/2, SEEK_SET); + getbits(-1); + } + } + for (col=0; col < raw_width; col++) { + i = getbits(12); + if ((unsigned) (col-left_margin) < width) + BAYER(row,col-left_margin) = i; + if (tiff_compress > 32768 && (col % 10) == 9) + if (getbits(8)) derror(); + } + } +} + +/* + Figure out if a NEF file is compressed. These fancy heuristics + are only needed for the D100, thanks to a bug in some cameras + that tags all images as "compressed". + */ +int CLASS nikon_is_compressed() +{ + uchar test[256]; + int i; + + fseek (ifp, data_offset, SEEK_SET); + fread (test, 1, 256, ifp); + for (i=15; i < 256; i+=16) + if (test[i]) return 1; + return 0; +} + +/* + Returns 1 for a Coolpix 995, 0 for anything else. + */ +int CLASS nikon_e995() +{ + int i, histo[256]; + const uchar often[] = { 0x00, 0x55, 0xaa, 0xff }; + + memset (histo, 0, sizeof histo); + fseek (ifp, -2000, SEEK_END); + for (i=0; i < 2000; i++) + histo[fgetc(ifp)]++; + for (i=0; i < 4; i++) + if (histo[often[i]] < 200) + return 0; + return 1; +} + +/* + Returns 1 for a Coolpix 2100, 0 for anything else. + */ +int CLASS nikon_e2100() +{ + uchar t[12]; + int i; + + fseek (ifp, 0, SEEK_SET); + for (i=0; i < 1024; i++) { + fread (t, 1, 12, ifp); + if (((t[2] & t[4] & t[7] & t[9]) >> 4 + & t[1] & t[6] & t[8] & t[11] & 3) != 3) + return 0; + } + return 1; +} + +void CLASS nikon_3700() +{ + int bits, i; + uchar dp[24]; + static const struct { + int bits; + char make[12], model[15]; + } table[] = { + { 0x00, "PENTAX", "Optio 33WR" }, + { 0x03, "NIKON", "E3200" }, + { 0x32, "NIKON", "E3700" }, + { 0x33, "OLYMPUS", "C740UZ" } }; + + fseek (ifp, 3072, SEEK_SET); + fread (dp, 1, 24, ifp); + bits = (dp[8] & 3) << 4 | (dp[20] & 3); + for (i=0; i < sizeof table / sizeof *table; i++) + if (bits == table[i].bits) { + strcpy (make, table[i].make ); + strcpy (model, table[i].model); + } +} + +/* + Separates a Minolta DiMAGE Z2 from a Nikon E4300. + */ +int CLASS minolta_z2() +{ + int i; + char tail[424]; + + fseek (ifp, -sizeof tail, SEEK_END); + fread (tail, 1, sizeof tail, ifp); + for (i=0; i < sizeof tail; i++) + if (tail[i]) return 1; + return 0; +} + +/* Here raw_width is in bytes, not pixels. */ +void CLASS nikon_e900_load_raw() +{ + int offset=0, irow, row, col; + + for (irow=0; irow < height; irow++) { + row = irow * 2 % height; + if (row == 1) + offset = - (-offset & -4096); + fseek (ifp, offset, SEEK_SET); + offset += raw_width; + getbits(-1); + for (col=0; col < width; col++) + BAYER(row,col) = getbits(10); + } +} + +void CLASS nikon_e2100_load_raw() +{ + uchar data[4608], *dp; + ushort pixel[3072], *pix; + int row, col; + + for (row=0; row <= height; row+=2) { + if (row == height) { + fseek (ifp, 0, SEEK_END); + fseek (ifp, ftell(ifp)/2, SEEK_SET); + row = 1; + } + fread (data, 1, width*3/2, ifp); + for (dp=data, pix=pixel; pix < pixel+width; dp+=12, pix+=8) { + pix[0] = (dp[2] >> 4) + (dp[ 3] << 4); + pix[1] = (dp[2] << 8) + dp[ 1]; + pix[2] = (dp[7] >> 4) + (dp[ 0] << 4); + pix[3] = (dp[7] << 8) + dp[ 6]; + pix[4] = (dp[4] >> 4) + (dp[ 5] << 4); + pix[5] = (dp[4] << 8) + dp[11]; + pix[6] = (dp[9] >> 4) + (dp[10] << 4); + pix[7] = (dp[9] << 8) + dp[ 8]; + } + for (col=0; col < width; col++) + BAYER(row,col) = (pixel[col] & 0xfff); + } +} + +/* + The Fuji Super CCD is just a Bayer grid rotated 45 degrees. + */ +void CLASS fuji_load_raw() +{ + ushort *pixel; + int wide, row, col, r, c; + + fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR); + wide = fuji_width << !fuji_layout; + pixel = (ushort *) calloc (wide, sizeof *pixel); + merror (pixel, "fuji_load_raw()"); + for (row=0; row < raw_height; row++) { + read_shorts (pixel, wide); + fseek (ifp, 2*(raw_width - wide), SEEK_CUR); + for (col=0; col < wide; col++) { + if (fuji_layout) { + r = fuji_width - 1 - col + (row >> 1); + c = col + ((row+1) >> 1); + } else { + r = fuji_width - 1 + row - (col >> 1); + c = row + ((col+1) >> 1); + } + BAYER(r,c) = pixel[col]; + } + } + free (pixel); +} + +void CLASS jpeg_thumb (FILE *tfp); + +void CLASS ppm_thumb (FILE *tfp) +{ + char *thumb; + thumb_length = thumb_width*thumb_height*3; + thumb = (char *) malloc (thumb_length); + merror (thumb, "ppm_thumb()"); + fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height); + fread (thumb, 1, thumb_length, ifp); + fwrite (thumb, 1, thumb_length, tfp); + free (thumb); +} + +void CLASS layer_thumb (FILE *tfp) +{ + int i, c; + char *thumb, map[][4] = { "012","102" }; + + colors = thumb_misc >> 5 & 7; + thumb_length = thumb_width*thumb_height; + thumb = (char *) calloc (colors, thumb_length); + merror (thumb, "layer_thumb()"); + fprintf (tfp, "P%d\n%d %d\n255\n", + 5 + (colors >> 1), thumb_width, thumb_height); + fread (thumb, thumb_length, colors, ifp); + for (i=0; i < thumb_length; i++) + FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], tfp); + free (thumb); +} + +void CLASS rollei_thumb (FILE *tfp) +{ + unsigned i; + ushort *thumb; + + thumb_length = thumb_width * thumb_height; + thumb = (ushort *) calloc (thumb_length, 2); + merror (thumb, "rollei_thumb()"); + fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height); + read_shorts (thumb, thumb_length); + for (i=0; i < thumb_length; i++) { + putc (thumb[i] << 3, tfp); + putc (thumb[i] >> 5 << 2, tfp); + putc (thumb[i] >> 11 << 3, tfp); + } + free (thumb); +} + +void CLASS rollei_load_raw() +{ + uchar pixel[10]; + unsigned iten=0, isix, i, buffer=0, row, col, todo[16]; + + isix = raw_width * raw_height * 5 / 8; + while (fread (pixel, 1, 10, ifp) == 10) { + for (i=0; i < 10; i+=2) { + todo[i] = iten++; + todo[i+1] = pixel[i] << 8 | pixel[i+1]; + buffer = pixel[i] >> 2 | buffer << 6; + } + for ( ; i < 16; i+=2) { + todo[i] = isix++; + todo[i+1] = buffer >> (14-i)*5; + } + for (i=0; i < 16; i+=2) { + row = todo[i] / raw_width - top_margin; + col = todo[i] % raw_width - left_margin; + if (row < height && col < width) + BAYER(row,col) = (todo[i+1] & 0x3ff); + } + } + maximum = 0x3ff; +} + +int CLASS bayer (unsigned row, unsigned col) +{ + return (row < height && col < width) ? BAYER(row,col) : 0; +} + +void CLASS phase_one_flat_field (int is_float, int nc) +{ + ushort head[8]; + unsigned wide, y, x, c, rend, cend, row, col; + float *mrow, num, mult[4]; + + read_shorts (head, 8); + wide = head[2] / head[4]; + mrow = (float *) calloc (nc*wide, sizeof *mrow); + merror (mrow, "phase_one_flat_field()"); + for (y=0; y < head[3] / head[5]; y++) { + for (x=0; x < wide; x++) + for (c=0; c < nc; c+=2) { + num = is_float ? getreal(11) : get2()/32768.0; + if (y==0) mrow[c*wide+x] = num; + else mrow[(c+1)*wide+x] = (num - mrow[c*wide+x]) / head[5]; + } + if (y==0) continue; + rend = head[1]-top_margin + y*head[5]; + for (row = rend-head[5]; row < height && row < rend; row++) { + for (x=1; x < wide; x++) { + for (c=0; c < nc; c+=2) { + mult[c] = mrow[c*wide+x-1]; + mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4]; + } + cend = head[0]-left_margin + x*head[4]; + for (col = cend-head[4]; col < width && col < cend; col++) { + c = nc > 2 ? FC(row,col) : 0; + if (!(c & 1)) { + c = BAYER(row,col) * mult[c]; + BAYER(row,col) = LIM(c,0,65535); + } + for (c=0; c < nc; c+=2) + mult[c] += mult[c+1]; + } + } + for (x=0; x < wide; x++) + for (c=0; c < nc; c+=2) + mrow[c*wide+x] += mrow[(c+1)*wide+x]; + } + } + free (mrow); +} + +void CLASS phase_one_correct() +{ + unsigned entries, tag, data, save, col, row, type; + int len, i, j, k, cip, val[4], dev[4], sum, max; + int head[9], diff, mindiff=INT_MAX, off_412=0; + static const signed char dir[12][2] = + { {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0}, + {-2,-2}, {-2,2}, {2,-2}, {2,2} }; + float poly[8], num, cfrac, frac, mult[2], *yval[2]; + ushort curve[0x10000], *xval[2]; + + if (half_size || !meta_length) return; + if (verbose) fprintf (stderr,_("Phase One correction...\n")); + fseek (ifp, meta_offset, SEEK_SET); + order = get2(); + fseek (ifp, 6, SEEK_CUR); + fseek (ifp, meta_offset+get4(), SEEK_SET); + entries = get4(); get4(); + while (entries--) { + tag = get4(); + len = get4(); + data = get4(); + save = ftell(ifp); + fseek (ifp, meta_offset+data, SEEK_SET); + if (tag == 0x419) { /* Polynomial curve */ + for (get4(), i=0; i < 8; i++) + poly[i] = getreal(11); + poly[3] += (ph1.tag_210 - poly[7]) * poly[6] + 1; + for (i=0; i < 0x10000; i++) { + num = (poly[5]*i + poly[3])*i + poly[1]; + curve[i] = LIM(num,0,65535); + } goto apply; /* apply to right half */ + } else if (tag == 0x41a) { /* Polynomial curve */ + for (i=0; i < 4; i++) + poly[i] = getreal(11); + for (i=0; i < 0x10000; i++) { + for (num=0, j=4; j--; ) + num = num * i + poly[j]; + curve[i] = LIM(num+i,0,65535); + } apply: /* apply to whole image */ + for (row=0; row < height; row++) + for (col = (tag & 1)*ph1.split_col; col < width; col++) + BAYER(row,col) = curve[BAYER(row,col)]; + } else if (tag == 0x400) { /* Sensor defects */ + while ((len -= 8) >= 0) { + col = get2() - left_margin; + row = get2() - top_margin; + type = get2(); get2(); + if (col >= width) continue; + if (type == 131) /* Bad column */ + for (row=0; row < height; row++) + if (FC(row,col) == 1) { + for (sum=i=0; i < 4; i++) + sum += val[i] = bayer (row+dir[i][0], col+dir[i][1]); + for (max=i=0; i < 4; i++) { + dev[i] = abs((val[i] << 2) - sum); + if (dev[max] < dev[i]) max = i; + } + BAYER(row,col) = (sum - val[max])/3.0 + 0.5; + } else { + for (sum=0, i=8; i < 12; i++) + sum += bayer (row+dir[i][0], col+dir[i][1]); + BAYER(row,col) = 0.5 + sum * 0.0732233 + + (bayer(row,col-2) + bayer(row,col+2)) * 0.3535534; + } + else if (type == 129) { /* Bad pixel */ + if (row >= height) continue; + j = (FC(row,col) != 1) * 4; + for (sum=0, i=j; i < j+8; i++) + sum += bayer (row+dir[i][0], col+dir[i][1]); + BAYER(row,col) = (sum + 4) >> 3; + } + } + } else if (tag == 0x401) { /* All-color flat fields */ + phase_one_flat_field (1, 2); + } else if (tag == 0x416 || tag == 0x410) { + phase_one_flat_field (0, 2); + } else if (tag == 0x40b) { /* Red+blue flat field */ + phase_one_flat_field (0, 4); + } else if (tag == 0x412) { + fseek (ifp, 36, SEEK_CUR); + diff = abs (get2() - ph1.tag_21a); + if (mindiff > diff) { + mindiff = diff; + off_412 = ftell(ifp) - 38; + } + } + fseek (ifp, save, SEEK_SET); + } + if (off_412) { + fseek (ifp, off_412, SEEK_SET); + for (i=0; i < 9; i++) head[i] = get4() & 0x7fff; + yval[0] = (float *) calloc (head[1]*head[3] + head[2]*head[4], 6); + merror (yval[0], "phase_one_correct()"); + yval[1] = (float *) (yval[0] + head[1]*head[3]); + xval[0] = (ushort *) (yval[1] + head[2]*head[4]); + xval[1] = (ushort *) (xval[0] + head[1]*head[3]); + get2(); + for (i=0; i < 2; i++) + for (j=0; j < head[i+1]*head[i+3]; j++) + yval[i][j] = getreal(11); + for (i=0; i < 2; i++) + for (j=0; j < head[i+1]*head[i+3]; j++) + xval[i][j] = get2(); + for (row=0; row < height; row++) + for (col=0; col < width; col++) { + cfrac = (float) col * head[3] / raw_width; + cfrac -= cip = cfrac; + num = BAYER(row,col) * 0.5; + for (i=cip; i < cip+2; i++) { + for (k=j=0; j < head[1]; j++) + if (num < xval[0][k = head[1]*i+j]) break; + frac = (j == 0 || j == head[1]) ? 0 : + (xval[0][k] - num) / (xval[0][k] - xval[0][k-1]); + mult[i-cip] = yval[0][k-1] * frac + yval[0][k] * (1-frac); + } + i = ((mult[0] * (1-cfrac) + mult[1] * cfrac) + * (row + top_margin) + num) * 2; + BAYER(row,col) = LIM(i,0,65535); + } + free (yval[0]); + } +} + +void CLASS phase_one_load_raw() +{ + int row, col, a, b; + ushort *pixel, akey, bkey, mask; + + fseek (ifp, ph1.key_off, SEEK_SET); + akey = get2(); + bkey = get2(); + mask = ph1.format == 1 ? 0x5555:0x1354; + fseek (ifp, data_offset + top_margin*raw_width*2, SEEK_SET); + pixel = (ushort *) calloc (raw_width, sizeof *pixel); + merror (pixel, "phase_one_load_raw()"); + for (row=0; row < height; row++) { + read_shorts (pixel, raw_width); + for (col=0; col < raw_width; col+=2) { + a = pixel[col+0] ^ akey; + b = pixel[col+1] ^ bkey; + pixel[col+0] = (a & mask) | (b & ~mask); + pixel[col+1] = (b & mask) | (a & ~mask); + } + for (col=0; col < width; col++) + BAYER(row,col) = pixel[col+left_margin]; + } + free (pixel); + phase_one_correct(); +} + +unsigned CLASS ph1_bits (int nbits) +{ + static UINT64 bitbuf=0; + static int vbits=0; + + if (nbits == -1) + return bitbuf = vbits = 0; + if (nbits == 0) return 0; + if (vbits < nbits) { + bitbuf = bitbuf << 32 | get4(); + vbits += 32; + } + vbits -= nbits; + return bitbuf << (64-nbits-vbits) >> (64-nbits); +} + +void CLASS phase_one_load_raw_c() +{ + static const int length[] = { 8,7,6,9,11,10,5,12,14,13 }; + int *offset, len[2], pred[2], row, col, i, j; + ushort *pixel; + short (*black)[2]; + + pixel = (ushort *) calloc (raw_width + raw_height*4, 2); + merror (pixel, "phase_one_load_raw_c()"); + offset = (int *) (pixel + raw_width); + fseek (ifp, strip_offset, SEEK_SET); + for (row=0; row < raw_height; row++) + offset[row] = get4(); + black = (short (*)[2]) offset + raw_height; + fseek (ifp, ph1.black_off, SEEK_SET); + if (ph1.black_off) + read_shorts ((ushort *) black[0], raw_height*2); + for (i=0; i < 256; i++) + curve[i] = i*i / 3.969 + 0.5; + for (row=0; row < raw_height; row++) { + fseek (ifp, data_offset + offset[row], SEEK_SET); + ph1_bits(-1); + pred[0] = pred[1] = 0; + for (col=0; col < raw_width; col++) { + if (col >= (raw_width & -8)) + len[0] = len[1] = 14; + else if ((col & 7) == 0) + for (i=0; i < 2; i++) { + for (j=0; j < 5 && !ph1_bits(1); j++); + if (j--) len[i] = length[j*2 + ph1_bits(1)]; + } + if ((i = len[col & 1]) == 14) + pixel[col] = pred[col & 1] = ph1_bits(16); + else + pixel[col] = pred[col & 1] += ph1_bits(i) + 1 - (1 << (i - 1)); + if (pred[col & 1] >> 16) derror(); + if (ph1.format == 5 && pixel[col] < 256) + pixel[col] = curve[pixel[col]]; + } + if ((unsigned) (row-top_margin) < height) + for (col=0; col < width; col++) { + i = (pixel[col+left_margin] << 2) + - ph1.black + black[row][col >= ph1.split_col]; + if (i > 0) BAYER(row-top_margin,col) = i; + } + } + free (pixel); + phase_one_correct(); + maximum = 0xfffc - ph1.black; +} + +void CLASS hasselblad_load_raw() +{ + struct jhead jh; + struct decode *dindex; + int row, col, pred[2], len[2], diff, i; + + if (!ljpeg_start (&jh, 0)) return; + free (jh.row); + ph1_bits(-1); + for (row=0; row < height; row++) { + pred[0] = pred[1] = 0x8000; + for (col=0; col < width; col+=2) { + for (i=0; i < 2; i++) { + for (dindex=jh.huff[0]; dindex->branch[0]; ) + dindex = dindex->branch[ph1_bits(1)]; + len[i] = dindex->leaf; + } + for (i=0; i < 2; i++) { + diff = ph1_bits(len[i]); + if ((diff & (1 << (len[i]-1))) == 0) + diff -= (1 << len[i]) - 1; + BAYER(row,col+i) = pred[i] += diff; + } + } + } + maximum = 0xffff; +} + +void CLASS leaf_hdr_load_raw() +{ + ushort *pixel; + unsigned tile=0, r, c, row, col; + + pixel = (ushort *) calloc (raw_width, sizeof *pixel); + merror (pixel, "leaf_hdr_load_raw()"); + for (c=0; c < tiff_samples; c++) { + for (r=0; r < raw_height; r++) { + if (r % tile_length == 0) { + fseek (ifp, data_offset + 4*tile++, SEEK_SET); + fseek (ifp, get4() + 2*left_margin, SEEK_SET); + } + if (filters && c != shot_select) continue; + read_shorts (pixel, raw_width); + if ((row = r - top_margin) >= height) continue; + for (col=0; col < width; col++) + if (filters) BAYER(row,col) = pixel[col]; + else image[row*width+col][c] = pixel[col]; + } + } + free (pixel); + if (!filters) { + maximum = 0xffff; + raw_color = 1; + } +} + +void CLASS unpacked_load_raw(); + +void CLASS sinar_4shot_load_raw() +{ + ushort *pixel; + unsigned shot, row, col, r, c; + + if ((shot = shot_select) || half_size) { + if (shot) shot--; + if (shot > 3) shot = 3; + fseek (ifp, data_offset + shot*4, SEEK_SET); + fseek (ifp, get4(), SEEK_SET); + unpacked_load_raw(); + return; + } + free (image); + image = (ushort (*)[4]) + calloc ((iheight=height)*(iwidth=width), sizeof *image); + merror (image, "sinar_4shot_load_raw()"); + pixel = (ushort *) calloc (raw_width, sizeof *pixel); + merror (pixel, "sinar_4shot_load_raw()"); + for (shot=0; shot < 4; shot++) { + fseek (ifp, data_offset + shot*4, SEEK_SET); + fseek (ifp, get4(), SEEK_SET); + for (row=0; row < raw_height; row++) { + read_shorts (pixel, raw_width); + if ((r = row-top_margin - (shot >> 1 & 1)) >= height) continue; + for (col=0; col < raw_width; col++) { + if ((c = col-left_margin - (shot & 1)) >= width) continue; + image[r*width+c][FC(row,col)] = pixel[col]; + } + } + } + free (pixel); + shrink = filters = 0; +} + +void CLASS imacon_full_load_raw() +{ + int row, col; + + for (row=0; row < height; row++) + for (col=0; col < width; col++) + read_shorts (image[row*width+col], 3); +} + +void CLASS packed_12_load_raw() +{ + int row, col; + + if (raw_width * 2 < width * 3) + raw_width = raw_width * 3 / 2; /* Convert raw_width to bytes */ + getbits(-1); + for (row=0; row < height; row++) { + for (col=0; col < left_margin; col++) + getbits(12); + for (col=0; col < width; col++) + BAYER(row,col) = getbits(12); + for (col = (width+left_margin)*3/2; col < raw_width; col++) + if (getbits(8) && raw_width-col < 35 && width != 3896) derror(); + } +} + +void CLASS unpacked_load_raw() +{ + ushort *pixel; + int row, col, bits=0; + + while (1 << ++bits < maximum); + fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR); + pixel = (ushort *) calloc (width, sizeof *pixel); + merror (pixel, "unpacked_load_raw()"); + for (row=0; row < height; row++) { + read_shorts (pixel, width); + fseek (ifp, 2*(raw_width - width), SEEK_CUR); + for (col=0; col < width; col++) + if ((BAYER2(row,col) = pixel[col]) >> bits) derror(); + } + free (pixel); +} + +void CLASS olympus_e300_load_raw() +{ + uchar *data, *dp; + ushort *pixel, *pix; + int dwide, row, col; + + dwide = raw_width * 16 / 10; + fseek (ifp, dwide*top_margin, SEEK_CUR); + data = (uchar *) malloc (dwide + raw_width*2); + merror (data, "olympus_e300_load_raw()"); + pixel = (ushort *) (data + dwide); + for (row=0; row < height; row++) { + if (fread (data, 1, dwide, ifp) < dwide) derror(); + for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=3, pix+=2) { + if (((dp-data) & 15) == 15) + if (*dp++ && pix < pixel+width+left_margin) derror(); + pix[0] = dp[1] << 8 | dp[0]; + pix[1] = dp[2] << 4 | dp[1] >> 4; + } + for (col=0; col < width; col++) + BAYER(row,col) = (pixel[col+left_margin] & 0xfff); + } + free (data); + maximum >>= 4; + black >>= 4; +} + +void CLASS olympus_e410_load_raw() +{ + int row, col, nbits, sign, low, high, i, w, n, nw; + int acarry[2][3], *carry, pred, diff; + + fseek (ifp, 7, SEEK_CUR); + getbits(-1); + for (row=0; row < height; row++) { + memset (acarry, 0, sizeof acarry); + for (col=0; col < width; col++) { + carry = acarry[col & 1]; + i = 2 * (carry[2] < 3); + for (nbits=2+i; (ushort) carry[0] >> (nbits+i); nbits++); + sign = getbits(1) * -1; + low = getbits(2); + for (high=0; high < 12; high++) + if (getbits(1)) break; + if (high == 12) + high = getbits(16-nbits) >> 1; + carry[0] = (high << nbits) | getbits(nbits); + diff = (carry[0] ^ sign) + carry[1]; + carry[1] = (diff*3 + carry[1]) >> 5; + carry[2] = carry[0] > 16 ? 0 : carry[2]+1; + if (row < 2 && col < 2) pred = 0; + else if (row < 2) pred = BAYER(row,col-2); + else if (col < 2) pred = BAYER(row-2,col); + else { + w = BAYER(row,col-2); + n = BAYER(row-2,col); + nw = BAYER(row-2,col-2); + if ((w < nw && nw < n) || (n < nw && nw < w)) { + if (ABS(w-nw) > 32 || ABS(n-nw) > 32) + pred = w + n - nw; + else pred = (w + n) >> 1; + } else pred = ABS(w-nw) > ABS(n-nw) ? w : n; + } + if ((BAYER(row,col) = pred + ((diff << 2) | low)) >> 12) derror(); + } + } +} + +void CLASS olympus_cseries_load_raw() +{ + int irow, row, col; + + for (irow=0; irow < height; irow++) { + row = irow * 2 % height + irow / (height/2); + if (row < 2) { + fseek (ifp, data_offset - row*(-width*height*3/4 & -2048), SEEK_SET); + getbits(-1); + } + for (col=0; col < width; col++) + BAYER(row,col) = getbits(12); + } + black >>= 4; +} + +void CLASS minolta_rd175_load_raw() +{ + uchar pixel[768]; + unsigned irow, box, row, col; + + for (irow=0; irow < 1481; irow++) { + if (fread (pixel, 1, 768, ifp) < 768) derror(); + box = irow / 82; + row = irow % 82 * 12 + ((box < 12) ? box | 1 : (box-12)*2); + switch (irow) { + case 1477: case 1479: continue; + case 1476: row = 984; break; + case 1480: row = 985; break; + case 1478: row = 985; box = 1; + } + if ((box < 12) && (box & 1)) { + for (col=0; col < 1533; col++, row ^= 1) + if (col != 1) BAYER(row,col) = (col+1) & 2 ? + pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1; + BAYER(row,1) = pixel[1] << 1; + BAYER(row,1533) = pixel[765] << 1; + } else + for (col=row & 1; col < 1534; col+=2) + BAYER(row,col) = pixel[col/2] << 1; + } + maximum = 0xff << 1; +} + +void CLASS casio_qv5700_load_raw() +{ + uchar data[3232], *dp; + ushort pixel[2576], *pix; + int row, col; + + for (row=0; row < height; row++) { + fread (data, 1, 3232, ifp); + for (dp=data, pix=pixel; dp < data+3220; dp+=5, pix+=4) { + pix[0] = (dp[0] << 2) + (dp[1] >> 6); + pix[1] = (dp[1] << 4) + (dp[2] >> 4); + pix[2] = (dp[2] << 6) + (dp[3] >> 2); + pix[3] = (dp[3] << 8) + (dp[4] ); + } + for (col=0; col < width; col++) + BAYER(row,col) = (pixel[col] & 0x3ff); + } + maximum = 0x3fc; +} + +void CLASS quicktake_100_load_raw() +{ + uchar pixel[484][644]; + static const short gstep[16] = + { -89,-60,-44,-32,-22,-15,-8,-2,2,8,15,22,32,44,60,89 }; + static const short rstep[6][4] = + { { -3,-1,1,3 }, { -5,-1,1,5 }, { -8,-2,2,8 }, + { -13,-3,3,13 }, { -19,-4,4,19 }, { -28,-6,6,28 } }; + static const short curve[256] = + { 0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27, + 28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,53, + 54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78, + 79,80,81,82,83,84,86,88,90,92,94,97,99,101,103,105,107,110,112,114,116, + 118,120,123,125,127,129,131,134,136,138,140,142,144,147,149,151,153,155, + 158,160,162,164,166,168,171,173,175,177,179,181,184,186,188,190,192,195, + 197,199,201,203,205,208,210,212,214,216,218,221,223,226,230,235,239,244, + 248,252,257,261,265,270,274,278,283,287,291,296,300,305,309,313,318,322, + 326,331,335,339,344,348,352,357,361,365,370,374,379,383,387,392,396,400, + 405,409,413,418,422,426,431,435,440,444,448,453,457,461,466,470,474,479, + 483,487,492,496,500,508,519,531,542,553,564,575,587,598,609,620,631,643, + 654,665,676,687,698,710,721,732,743,754,766,777,788,799,810,822,833,844, + 855,866,878,889,900,911,922,933,945,956,967,978,989,1001,1012,1023 }; + int rb, row, col, sharp, val=0; + + getbits(-1); + memset (pixel, 0x80, sizeof pixel); + for (row=2; row < height+2; row++) { + for (col=2+(row & 1); col < width+2; col+=2) { + val = ((pixel[row-1][col-1] + 2*pixel[row-1][col+1] + + pixel[row][col-2]) >> 2) + gstep[getbits(4)]; + pixel[row][col] = val = LIM(val,0,255); + if (col < 4) + pixel[row][col-2] = pixel[row+1][~row & 1] = val; + if (row == 2) + pixel[row-1][col+1] = pixel[row-1][col+3] = val; + } + pixel[row][col] = val; + } + for (rb=0; rb < 2; rb++) + for (row=2+rb; row < height+2; row+=2) + for (col=3-(row & 1); col < width+2; col+=2) { + if (row < 4 || col < 4) sharp = 2; + else { + val = ABS(pixel[row-2][col] - pixel[row][col-2]) + + ABS(pixel[row-2][col] - pixel[row-2][col-2]) + + ABS(pixel[row][col-2] - pixel[row-2][col-2]); + sharp = val < 4 ? 0 : val < 8 ? 1 : val < 16 ? 2 : + val < 32 ? 3 : val < 48 ? 4 : 5; + } + val = ((pixel[row-2][col] + pixel[row][col-2]) >> 1) + + rstep[sharp][getbits(2)]; + pixel[row][col] = val = LIM(val,0,255); + if (row < 4) pixel[row-2][col+2] = val; + if (col < 4) pixel[row+2][col-2] = val; + } + for (row=2; row < height+2; row++) + for (col=3-(row & 1); col < width+2; col+=2) { + val = ((pixel[row][col-1] + (pixel[row][col] << 2) + + pixel[row][col+1]) >> 1) - 0x100; + pixel[row][col] = LIM(val,0,255); + } + for (row=0; row < height; row++) + for (col=0; col < width; col++) + BAYER(row,col) = curve[pixel[row+2][col+2]]; + maximum = 0x3ff; +} + +const int * CLASS make_decoder_int (const int *source, int level) +{ + struct decode *cur; + + cur = free_decode++; + if (level < source[0]) { + cur->branch[0] = free_decode; + source = make_decoder_int (source, level+1); + cur->branch[1] = free_decode; + source = make_decoder_int (source, level+1); + } else { + cur->leaf = source[1]; + source += 2; + } + return source; +} + +int CLASS radc_token (int tree) +{ + int t; + static struct decode *dstart[18], *dindex; + static const int *s, source[] = { + 1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8, + 1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8, + 2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8, + 2,0, 2,1, 2,3, 3,2, 4,4, 5,6, 6,7, 7,5, 7,8, + 2,1, 2,4, 3,0, 3,2, 3,3, 4,7, 5,5, 6,6, 6,8, + 2,3, 3,1, 3,2, 3,4, 3,5, 3,6, 4,7, 5,0, 5,8, + 2,3, 2,6, 3,0, 3,1, 4,4, 4,5, 4,7, 5,2, 5,8, + 2,4, 2,7, 3,3, 3,6, 4,1, 4,2, 4,5, 5,0, 5,8, + 2,6, 3,1, 3,3, 3,5, 3,7, 3,8, 4,0, 5,2, 5,4, + 2,0, 2,1, 3,2, 3,3, 4,4, 4,5, 5,6, 5,7, 4,8, + 1,0, 2,2, 2,-2, + 1,-3, 1,3, + 2,-17, 2,-5, 2,5, 2,17, + 2,-7, 2,2, 2,9, 2,18, + 2,-18, 2,-9, 2,-2, 2,7, + 2,-28, 2,28, 3,-49, 3,-9, 3,9, 4,49, 5,-79, 5,79, + 2,-1, 2,13, 2,26, 3,39, 4,-16, 5,55, 6,-37, 6,76, + 2,-26, 2,-13, 2,1, 3,-39, 4,16, 5,-55, 6,-76, 6,37 + }; + + if (free_decode == first_decode) + for (s=source, t=0; t < 18; t++) { + dstart[t] = free_decode; + s = make_decoder_int (s, 0); + } + if (tree == 18) { + if (kodak_cbpp == 243) + return (getbits(6) << 2) + 2; /* most DC50 photos */ + else + return (getbits(5) << 3) + 4; /* DC40, Fotoman Pixtura */ + } + for (dindex = dstart[tree]; dindex->branch[0]; ) + dindex = dindex->branch[getbits(1)]; + return dindex->leaf; +} + +#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--) + +#define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \ +: (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4) + +void CLASS kodak_radc_load_raw() +{ + int row, col, tree, nreps, rep, step, i, c, s, r, x, y, val; + short last[3] = { 16,16,16 }, mul[3], buf[3][3][386]; + + init_decoder(); + getbits(-1); + for (i=0; i < sizeof(buf)/sizeof(short); i++) + buf[0][0][i] = 2048; + for (row=0; row < height; row+=4) { + FORC3 mul[c] = getbits(6); + FORC3 { + val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c]; + s = val > 65564 ? 10:12; + x = ~(-1 << (s-1)); + val <<= 12-s; + for (i=0; i < sizeof(buf[0])/sizeof(short); i++) + buf[c][0][i] = (buf[c][0][i] * val + x) >> s; + last[c] = mul[c]; + for (r=0; r <= !c; r++) { + buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7; + for (tree=1, col=width/2; col > 0; ) { + if ((tree = radc_token(tree))) { + col -= 2; + if (tree == 8) + FORYX buf[c][y][x] = radc_token(tree+10) * mul[c]; + else + FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR; + } else + do { + nreps = (col > 2) ? radc_token(9) + 1 : 1; + for (rep=0; rep < 8 && rep < nreps && col > 0; rep++) { + col -= 2; + FORYX buf[c][y][x] = PREDICTOR; + if (rep & 1) { + step = radc_token(10) << 4; + FORYX buf[c][y][x] += step; + } + } + } while (nreps == 9); + } + for (y=0; y < 2; y++) + for (x=0; x < width/2; x++) { + val = (buf[c][y+1][x] << 4) / mul[c]; + if (val < 0) val = 0; + if (c) BAYER(row+y*2+c-1,x*2+2-c) = val; + else BAYER(row+r*2+y,x*2+y) = val; + } + memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c); + } + } + for (y=row; y < row+4; y++) + for (x=0; x < width; x++) + if ((x+y) & 1) { + r = x ? x-1 : x+1; + s = x+1 < width ? x+1 : x-1; + val = (BAYER(y,x)-2048)*2 + (BAYER(y,r)+BAYER(y,s))/2; + if (val < 0) val = 0; + BAYER(y,x) = val; + } + } + maximum = 0xfff; + use_gamma = 0; +} + +#undef FORYX +#undef PREDICTOR + +#ifdef NO_JPEG +void CLASS kodak_jpeg_load_raw() {} +#else + +METHODDEF(boolean) +fill_input_buffer (j_decompress_ptr cinfo) +{ + static uchar jpeg_buffer[4096]; + size_t nbytes; + + nbytes = fread (jpeg_buffer, 1, 4096, ifp); + swab (jpeg_buffer, jpeg_buffer, nbytes); + cinfo->src->next_input_byte = jpeg_buffer; + cinfo->src->bytes_in_buffer = nbytes; + return TRUE; +} + +void CLASS kodak_jpeg_load_raw() +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + JSAMPARRAY buf; + JSAMPLE (*pixel)[3]; + int row, col; + + cinfo.err = jpeg_std_error (&jerr); + jpeg_create_decompress (&cinfo); + jpeg_stdio_src (&cinfo, ifp); + cinfo.src->fill_input_buffer = fill_input_buffer; + jpeg_read_header (&cinfo, TRUE); + jpeg_start_decompress (&cinfo); + if ((cinfo.output_width != width ) || + (cinfo.output_height*2 != height ) || + (cinfo.output_components != 3 )) { + fprintf (stderr,_("%s: incorrect JPEG dimensions\n"), ifname); + jpeg_destroy_decompress (&cinfo); + longjmp (failure, 3); + } + buf = (*cinfo.mem->alloc_sarray) + ((j_common_ptr) &cinfo, JPOOL_IMAGE, width*3, 1); + + while (cinfo.output_scanline < cinfo.output_height) { + row = cinfo.output_scanline * 2; + jpeg_read_scanlines (&cinfo, buf, 1); + pixel = (JSAMPLE (*)[3]) buf[0]; + for (col=0; col < width; col+=2) { + BAYER(row+0,col+0) = pixel[col+0][1] << 1; + BAYER(row+1,col+1) = pixel[col+1][1] << 1; + BAYER(row+0,col+1) = pixel[col][0] + pixel[col+1][0]; + BAYER(row+1,col+0) = pixel[col][2] + pixel[col+1][2]; + } + } + jpeg_finish_decompress (&cinfo); + jpeg_destroy_decompress (&cinfo); + maximum = 0xff << 1; +} +#endif + +void CLASS kodak_dc120_load_raw() +{ + static const int mul[4] = { 162, 192, 187, 92 }; + static const int add[4] = { 0, 636, 424, 212 }; + uchar pixel[848]; + int row, shift, col; + + for (row=0; row < height; row++) { + if (fread (pixel, 1, 848, ifp) < 848) derror(); + shift = row * mul[row & 3] + add[row & 3]; + for (col=0; col < width; col++) + BAYER(row,col) = (ushort) pixel[(col + shift) % 848]; + } + maximum = 0xff; +} + +void CLASS eight_bit_load_raw() +{ + uchar *pixel; + unsigned row, col, val, lblack=0; + + pixel = (uchar *) calloc (raw_width, sizeof *pixel); + merror (pixel, "eight_bit_load_raw()"); + fseek (ifp, top_margin*raw_width, SEEK_CUR); + for (row=0; row < height; row++) { + if (fread (pixel, 1, raw_width, ifp) < raw_width) derror(); + for (col=0; col < raw_width; col++) { + val = curve[pixel[col]]; + if ((unsigned) (col-left_margin) < width) + BAYER(row,col-left_margin) = val; + else lblack += val; + } + } + free (pixel); + if (raw_width > width+1) + black = lblack / ((raw_width - width) * height); + if (!strncmp(model,"DC2",3)) + black = 0; + maximum = curve[0xff]; +} + +void CLASS kodak_262_load_raw() +{ + static const uchar kodak_tree[2][26] = + { { 0,1,5,1,1,2,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 }, + { 0,3,1,1,1,1,1,2,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 } }; + struct decode *decode[2]; + uchar *pixel; + int *strip, ns, i, row, col, chess, pi=0, pi1, pi2, pred, val; + + init_decoder(); + for (i=0; i < 2; i++) { + decode[i] = free_decode; + make_decoder (kodak_tree[i], 0); + } + ns = (raw_height+63) >> 5; + pixel = (uchar *) malloc (raw_width*32 + ns*4); + merror (pixel, "kodak_262_load_raw()"); + strip = (int *) (pixel + raw_width*32); + order = 0x4d4d; + for (i=0; i < ns; i++) + strip[i] = get4(); + for (row=0; row < raw_height; row++) { + if ((row & 31) == 0) { + fseek (ifp, strip[row >> 5], SEEK_SET); + getbits(-1); + pi = 0; + } + for (col=0; col < raw_width; col++) { + chess = (row + col) & 1; + pi1 = chess ? pi-2 : pi-raw_width-1; + pi2 = chess ? pi-2*raw_width : pi-raw_width+1; + if (col <= chess) pi1 = -1; + if (pi1 < 0) pi1 = pi2; + if (pi2 < 0) pi2 = pi1; + if (pi1 < 0 && col > 1) pi1 = pi2 = pi-2; + pred = (pi1 < 0) ? 0 : (pixel[pi1] + pixel[pi2]) >> 1; + pixel[pi] = val = pred + ljpeg_diff (decode[chess]); + if (val >> 8) derror(); + val = curve[pixel[pi++]]; + if ((unsigned) (col-left_margin) < width) + BAYER(row,col-left_margin) = val; + else black += val; + } + } + free (pixel); + if (raw_width > width) + black /= (raw_width - width) * height; +} + +int CLASS kodak_65000_decode (short *out, int bsize) +{ + uchar c, blen[768]; + ushort raw[6]; + INT64 bitbuf=0; + int save, bits=0, i, j, len, diff; + + save = ftell(ifp); + bsize = (bsize + 3) & -4; + for (i=0; i < bsize; i+=2) { + c = fgetc(ifp); + if ((blen[i ] = c & 15) > 12 || + (blen[i+1] = c >> 4) > 12 ) { + fseek (ifp, save, SEEK_SET); + for (i=0; i < bsize; i+=8) { + read_shorts (raw, 6); + out[i ] = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12; + out[i+1] = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12; + for (j=0; j < 6; j++) + out[i+2+j] = raw[j] & 0xfff; + } + return 1; + } + } + if ((bsize & 7) == 4) { + bitbuf = fgetc(ifp) << 8; + bitbuf += fgetc(ifp); + bits = 16; + } + for (i=0; i < bsize; i++) { + len = blen[i]; + if (bits < len) { + for (j=0; j < 32; j+=8) + bitbuf += (INT64) fgetc(ifp) << (bits+(j^8)); + bits += 32; + } + diff = bitbuf & (0xffff >> (16-len)); + bitbuf >>= len; + bits -= len; + if ((diff & (1 << (len-1))) == 0) + diff -= (1 << len) - 1; + out[i] = diff; + } + return 0; +} + +void CLASS kodak_65000_load_raw() +{ + short buf[256]; + int row, col, len, pred[2], ret, i; + + for (row=0; row < height; row++) + for (col=0; col < width; col+=256) { + pred[0] = pred[1] = 0; + len = MIN (256, width-col); + ret = kodak_65000_decode (buf, len); + for (i=0; i < len; i++) + if ((BAYER(row,col+i) = curve[ret ? buf[i] : + (pred[i & 1] += buf[i])]) >> 12) derror(); + } +} + +void CLASS kodak_ycbcr_load_raw() +{ + short buf[384], *bp; + int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3]; + ushort *ip; + + for (row=0; row < height; row+=2) + for (col=0; col < width; col+=128) { + len = MIN (128, width-col); + kodak_65000_decode (buf, len*3); + y[0][1] = y[1][1] = cb = cr = 0; + for (bp=buf, i=0; i < len; i+=2, bp+=2) { + cb += bp[4]; + cr += bp[5]; + rgb[1] = -((cb + cr + 2) >> 2); + rgb[2] = rgb[1] + cb; + rgb[0] = rgb[1] + cr; + for (j=0; j < 2; j++) + for (k=0; k < 2; k++) { + if ((y[j][k] = y[j][k^1] + *bp++) >> 10) derror(); + ip = image[(row+j)*width + col+i+k]; + FORC3 ip[c] = curve[LIM(y[j][k]+rgb[c], 0, 0xfff)]; + } + } + } +} + +void CLASS kodak_rgb_load_raw() +{ + short buf[768], *bp; + int row, col, len, c, i, rgb[3]; + ushort *ip=image[0]; + + for (row=0; row < height; row++) + for (col=0; col < width; col+=256) { + len = MIN (256, width-col); + kodak_65000_decode (buf, len*3); + memset (rgb, 0, sizeof rgb); + for (bp=buf, i=0; i < len; i++, ip+=4) + FORC3 if ((ip[c] = rgb[c] += *bp++) >> 12) derror(); + } +} + +void CLASS kodak_thumb_load_raw() +{ + int row, col; + colors = thumb_misc >> 5; + for (row=0; row < height; row++) + for (col=0; col < width; col++) + read_shorts (image[row*width+col], colors); + maximum = (1 << (thumb_misc & 31)) - 1; +} + +void CLASS sony_decrypt (unsigned *data, int len, int start, int key) +{ + static unsigned pad[128], p; + + if (start) { + for (p=0; p < 4; p++) + pad[p] = key = key * 48828125 + 1; + pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31; + for (p=4; p < 127; p++) + pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31; + for (p=0; p < 127; p++) + pad[p] = htonl(pad[p]); + } + while (len--) + *data++ ^= pad[p++ & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127]; +} + +void CLASS sony_load_raw() +{ + uchar head[40]; + ushort *pixel; + unsigned i, key, row, col; + + fseek (ifp, 200896, SEEK_SET); + fseek (ifp, (unsigned) fgetc(ifp)*4 - 1, SEEK_CUR); + order = 0x4d4d; + key = get4(); + fseek (ifp, 164600, SEEK_SET); + fread (head, 1, 40, ifp); + sony_decrypt ((unsigned int *) head, 10, 1, key); + for (i=26; i-- > 22; ) + key = key << 8 | head[i]; + fseek (ifp, data_offset, SEEK_SET); + pixel = (ushort *) calloc (raw_width, sizeof *pixel); + merror (pixel, "sony_load_raw()"); + for (row=0; row < height; row++) { + if (fread (pixel, 2, raw_width, ifp) < raw_width) derror(); + sony_decrypt ((unsigned int *) pixel, raw_width/2, !row, key); + for (col=9; col < left_margin; col++) + black += ntohs(pixel[col]); + for (col=0; col < width; col++) + if ((BAYER(row,col) = ntohs(pixel[col+left_margin])) >> 14) + derror(); + } + free (pixel); + if (left_margin > 9) + black /= (left_margin-9) * height; + maximum = 0x3ff0; +} + +void CLASS sony_arw_load_raw() +{ + int col, row, len, diff, sum=0; + + getbits(-1); + for (col = raw_width; col--; ) + for (row=0; row < raw_height+1; row+=2) { + if (row == raw_height) row = 1; + len = 4 - getbits(2); + if (len == 3 && getbits(1)) len = 0; + if (len == 4) + while (len < 17 && !getbits(1)) len++; + diff = getbits(len); + if ((diff & (1 << (len-1))) == 0) + diff -= (1 << len) - 1; + if ((sum += diff) >> 12) derror(); + if (row < height) BAYER(row,col) = sum; + } +} + +void CLASS sony_arw2_load_raw() +{ + uchar *data, *dp; + ushort pix[16]; + int row, col, val, max, min, imax, imin, sh, bit, i; + + data = (uchar *) malloc (raw_width*tiff_bps >> 3); + merror (data, "sony_arw2_load_raw()"); + for (row=0; row < height; row++) { + fread (data, 1, raw_width*tiff_bps >> 3, ifp); + if (tiff_bps == 8) { + for (dp=data, col=0; col < width-30; dp+=16) { + max = 0x7ff & (val = sget4(dp)); + min = 0x7ff & val >> 11; + imax = 0x0f & val >> 22; + imin = 0x0f & val >> 26; + for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++); + for (bit=30, i=0; i < 16; i++) + if (i == imax) pix[i] = max; + else if (i == imin) pix[i] = min; + else { + pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min; + if (pix[i] > 0x7ff) pix[i] = 0x7ff; + bit += 7; + } + for (i=0; i < 16; i++, col+=2) + BAYER(row,col) = curve[pix[i] << 1] >> 1; + col -= col & 1 ? 1:31; + } + } else if (tiff_bps == 12) + for (dp=data, col=0; col < width; dp+=3, col+=2) { + BAYER(row,col) = ((dp[1] << 8 | dp[0]) & 0xfff) << 1; + BAYER(row,col+1) = (dp[2] << 4 | dp[1] >> 4) << 1; + } + } + free (data); + maximum = 0x1fff; +} + +#define HOLE(row) ((holes >> (((row) - raw_height) & 7)) & 1) + +/* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */ +void CLASS smal_decode_segment (unsigned seg[2][2], int holes) +{ + uchar hist[3][13] = { + { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 }, + { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 }, + { 3, 3, 0, 0, 63, 47, 31, 15, 0 } }; + int low, high=0xff, carry=0, nbits=8; + int s, count, bin, next, i, sym[3]; + uchar diff, pred[]={0,0}; + ushort data=0, range=0; + unsigned pix, row, col; + + fseek (ifp, seg[0][1]+1, SEEK_SET); + getbits(-1); + for (pix=seg[0][0]; pix < seg[1][0]; pix++) { + for (s=0; s < 3; s++) { + data = data << nbits | getbits(nbits); + if (carry < 0) + carry = (nbits += carry+1) < 1 ? nbits-1 : 0; + while (--nbits >= 0) + if ((data >> nbits & 0xff) == 0xff) break; + if (nbits > 0) + data = ((data & ((1 << (nbits-1)) - 1)) << 1) | + ((data + (((data & (1 << (nbits-1)))) << 1)) & (-1 << nbits)); + if (nbits >= 0) { + data += getbits(1); + carry = nbits - 8; + } + count = ((((data-range+1) & 0xffff) << 2) - 1) / (high >> 4); + for (bin=0; hist[s][bin+5] > count; bin++); + low = hist[s][bin+5] * (high >> 4) >> 2; + if (bin) high = hist[s][bin+4] * (high >> 4) >> 2; + high -= low; + for (nbits=0; high << nbits < 128; nbits++); + range = (range+low) << nbits; + high <<= nbits; + next = hist[s][1]; + if (++hist[s][2] > hist[s][3]) { + next = (next+1) & hist[s][0]; + hist[s][3] = (hist[s][next+4] - hist[s][next+5]) >> 2; + hist[s][2] = 1; + } + if (hist[s][hist[s][1]+4] - hist[s][hist[s][1]+5] > 1) { + if (bin < hist[s][1]) + for (i=bin; i < hist[s][1]; i++) hist[s][i+5]--; + else if (next <= bin) + for (i=hist[s][1]; i < bin; i++) hist[s][i+5]++; + } + hist[s][1] = next; + sym[s] = bin; + } + diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3); + if (sym[0] & 4) + diff = diff ? -diff : 0x80; + if (ftell(ifp) + 12 >= seg[1][1]) + diff = 0; + pred[pix & 1] += diff; + row = pix / raw_width - top_margin; + col = pix % raw_width - left_margin; + if (row < height && col < width) + BAYER(row,col) = pred[pix & 1]; + if (!(pix & 1) && HOLE(row)) pix += 2; + } + maximum = 0xff; +} + +void CLASS smal_v6_load_raw() +{ + unsigned seg[2][2]; + + fseek (ifp, 16, SEEK_SET); + seg[0][0] = 0; + seg[0][1] = get2(); + seg[1][0] = raw_width * raw_height; + seg[1][1] = INT_MAX; + smal_decode_segment (seg, 0); + use_gamma = 0; +} + +int CLASS median4 (int *p) +{ + int min, max, sum, i; + + min = max = sum = p[0]; + for (i=1; i < 4; i++) { + sum += p[i]; + if (min > p[i]) min = p[i]; + if (max < p[i]) max = p[i]; + } + return (sum - min - max) >> 1; +} + +void CLASS fill_holes (int holes) +{ + int row, col, val[4]; + + for (row=2; row < height-2; row++) { + if (!HOLE(row)) continue; + for (col=1; col < width-1; col+=4) { + val[0] = BAYER(row-1,col-1); + val[1] = BAYER(row-1,col+1); + val[2] = BAYER(row+1,col-1); + val[3] = BAYER(row+1,col+1); + BAYER(row,col) = median4(val); + } + for (col=2; col < width-2; col+=4) + if (HOLE(row-2) || HOLE(row+2)) + BAYER(row,col) = (BAYER(row,col-2) + BAYER(row,col+2)) >> 1; + else { + val[0] = BAYER(row,col-2); + val[1] = BAYER(row,col+2); + val[2] = BAYER(row-2,col); + val[3] = BAYER(row+2,col); + BAYER(row,col) = median4(val); + } + } +} + +void CLASS smal_v9_load_raw() +{ + unsigned seg[256][2], offset, nseg, holes, i; + + fseek (ifp, 67, SEEK_SET); + offset = get4(); + nseg = fgetc(ifp); + fseek (ifp, offset, SEEK_SET); + for (i=0; i < nseg*2; i++) + seg[0][i] = get4() + data_offset*(i & 1); + fseek (ifp, 78, SEEK_SET); + holes = fgetc(ifp); + fseek (ifp, 88, SEEK_SET); + seg[nseg][0] = raw_height * raw_width; + seg[nseg][1] = get4() + data_offset; + for (i=0; i < nseg; i++) + smal_decode_segment (seg+i, holes); + if (holes) fill_holes (holes); +} + +/* RESTRICTED code starts here */ + +void CLASS foveon_decoder (unsigned size, unsigned code) +{ + static unsigned huff[1024]; + struct decode *cur; + int i, len; + + if (!code) { + for (i=0; i < size; i++) + huff[i] = get4(); + init_decoder(); + } + cur = free_decode++; + if (free_decode > first_decode+2048) { + fprintf (stderr,_("%s: decoder table overflow\n"), ifname); + longjmp (failure, 2); + } + if (code) + for (i=0; i < size; i++) + if (huff[i] == code) { + cur->leaf = i; + return; + } + if ((len = code >> 27) > 26) return; + code = (len+1) << 27 | (code & 0x3ffffff) << 1; + + cur->branch[0] = free_decode; + foveon_decoder (size, code); + cur->branch[1] = free_decode; + foveon_decoder (size, code+1); +} + +void CLASS foveon_thumb (FILE *tfp) +{ + unsigned bwide, row, col, bitbuf=0, bit=1, c, i; + char *buf; + struct decode *dindex; + short pred[3]; + + bwide = get4(); + fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height); + if (bwide > 0) { + if (bwide < thumb_width*3) return; + buf = (char *) malloc (bwide); + merror (buf, "foveon_thumb()"); + for (row=0; row < thumb_height; row++) { + fread (buf, 1, bwide, ifp); + fwrite (buf, 3, thumb_width, tfp); + } + free (buf); + return; + } + foveon_decoder (256, 0); + + for (row=0; row < thumb_height; row++) { + memset (pred, 0, sizeof pred); + if (!bit) get4(); + for (bit=col=0; col < thumb_width; col++) + FORC3 { + for (dindex=first_decode; dindex->branch[0]; ) { + if ((bit = (bit-1) & 31) == 31) + for (i=0; i < 4; i++) + bitbuf = (bitbuf << 8) + fgetc(ifp); + dindex = dindex->branch[bitbuf >> bit & 1]; + } + pred[c] += dindex->leaf; + fputc (pred[c], tfp); + } + } +} + +void CLASS foveon_load_camf() +{ + unsigned key, i, val; + + fseek (ifp, meta_offset, SEEK_SET); + key = get4(); + fread (meta_data, 1, meta_length, ifp); + for (i=0; i < meta_length; i++) { + key = (key * 1597 + 51749) % 244944; + val = key * (INT64) 301593171 >> 24; + meta_data[i] ^= ((((key << 8) - val) >> 1) + val) >> 17; + } +} + +void CLASS foveon_load_raw() +{ + struct decode *dindex; + short diff[1024]; + unsigned bitbuf=0; + int pred[3], fixed, row, col, bit=-1, c, i; + + fixed = get4(); + read_shorts ((ushort *) diff, 1024); + if (!fixed) foveon_decoder (1024, 0); + + for (row=0; row < height; row++) { + memset (pred, 0, sizeof pred); + if (!bit && !fixed && atoi(model+2) < 14) get4(); + for (col=bit=0; col < width; col++) { + if (fixed) { + bitbuf = get4(); + FORC3 pred[2-c] += diff[bitbuf >> c*10 & 0x3ff]; + } + else FORC3 { + for (dindex=first_decode; dindex->branch[0]; ) { + if ((bit = (bit-1) & 31) == 31) + for (i=0; i < 4; i++) + bitbuf = (bitbuf << 8) + fgetc(ifp); + dindex = dindex->branch[bitbuf >> bit & 1]; + } + pred[c] += diff[dindex->leaf]; + if (pred[c] >> 16 && ~pred[c] >> 16) derror(); + } + FORC3 image[row*width+col][c] = pred[c]; + } + } + if (document_mode) + for (i=0; i < height*width*4; i++) + if ((short) image[0][i] < 0) image[0][i] = 0; + foveon_load_camf(); +} + +const char * CLASS foveon_camf_param (const char *block, const char *param) +{ + unsigned idx, num; + char *pos, *cp, *dp; + + for (idx=0; idx < meta_length; idx += sget4(pos+8)) { + pos = meta_data + idx; + if (strncmp (pos, "CMb", 3)) break; + if (pos[3] != 'P') continue; + if (strcmp (block, pos+sget4(pos+12))) continue; + cp = pos + sget4(pos+16); + num = sget4(cp); + dp = pos + sget4(cp+4); + while (num--) { + cp += 8; + if (!strcmp (param, dp+sget4(cp))) + return dp+sget4(cp+4); + } + } + return 0; +} + +void * CLASS foveon_camf_matrix (unsigned dim[3], const char *name) +{ + unsigned i, idx, type, ndim, size, *mat; + char *pos, *cp, *dp; + double dsize; + + for (idx=0; idx < meta_length; idx += sget4(pos+8)) { + pos = meta_data + idx; + if (strncmp (pos, "CMb", 3)) break; + if (pos[3] != 'M') continue; + if (strcmp (name, pos+sget4(pos+12))) continue; + dim[0] = dim[1] = dim[2] = 1; + cp = pos + sget4(pos+16); + type = sget4(cp); + if ((ndim = sget4(cp+4)) > 3) break; + dp = pos + sget4(cp+8); + for (i=ndim; i--; ) { + cp += 12; + dim[i] = sget4(cp); + } + if ((dsize = (double) dim[0]*dim[1]*dim[2]) > meta_length/4) break; + mat = (unsigned *) malloc ((size = dsize) * 4); + merror (mat, "foveon_camf_matrix()"); + for (i=0; i < size; i++) + if (type && type != 6) + mat[i] = sget4(dp + i*4); + else + mat[i] = sget4(dp + i*2) & 0xffff; + return mat; + } + fprintf (stderr,_("%s: \"%s\" matrix not found!\n"), ifname, name); + return 0; +} + +int CLASS foveon_fixed (void *ptr, int size, const char *name) +{ + void *dp; + unsigned dim[3]; + + dp = foveon_camf_matrix (dim, name); + if (!dp) return 0; + memcpy (ptr, dp, size*4); + free (dp); + return 1; +} + +float CLASS foveon_avg (short *pix, int range[2], float cfilt) +{ + int i; + float val, min=FLT_MAX, max=-FLT_MAX, sum=0; + + for (i=range[0]; i <= range[1]; i++) { + sum += val = pix[i*4] + (pix[i*4]-pix[(i-1)*4]) * cfilt; + if (min > val) min = val; + if (max < val) max = val; + } + if (range[1] - range[0] == 1) return sum/2; + return (sum - min - max) / (range[1] - range[0] - 1); +} + +short * CLASS foveon_make_curve (double max, double mul, double filt) +{ + short *curve; + unsigned i, size; + double x; + + if (!filt) filt = 0.8; + size = 4*M_PI*max / filt; + if (size == UINT_MAX) size--; + curve = (short *) calloc (size+1, sizeof *curve); + merror (curve, "foveon_make_curve()"); + curve[0] = size; + for (i=0; i < size; i++) { + x = i*filt/max/4; + curve[i+1] = (cos(x)+1)/2 * tanh(i*filt/mul) * mul + 0.5; + } + return curve; +} + +void CLASS foveon_make_curves + (short **curvep, float dq[3], float div[3], float filt) +{ + double mul[3], max=0; + int c; + + FORC3 mul[c] = dq[c]/div[c]; + FORC3 if (max < mul[c]) max = mul[c]; + FORC3 curvep[c] = foveon_make_curve (max, mul[c], filt); +} + +int CLASS foveon_apply_curve (short *curve, int i) +{ + if (abs(i) >= curve[0]) return 0; + return i < 0 ? -curve[1-i] : curve[1+i]; +} + +#define image ((short (*)[4]) image) + +void CLASS foveon_interpolate() +{ + static const short hood[] = { -1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0, 1,1 }; + short *pix, prev[3], *curve[8], (*shrink)[3]; + float cfilt=0, ddft[3][3][2], ppm[3][3][3]; + float cam_xyz[3][3], correct[3][3], last[3][3], trans[3][3]; + float chroma_dq[3], color_dq[3], diag[3][3], div[3]; + float (*black)[3], (*sgain)[3], (*sgrow)[3]; + float fsum[3], val, frow, num; + int row, col, c, i, j, diff, sgx, irow, sum, min, max, limit; + int dscr[2][2], dstb[4], (*smrow[7])[3], total[4], ipix[3]; + int work[3][3], smlast, smred, smred_p=0, dev[3]; + int satlev[3], keep[4], active[4]; + unsigned dim[3], *badpix; + double dsum=0, trsum[3]; + char str[128]; + const char* cp; + + if (verbose) + fprintf (stderr,_("Foveon interpolation...\n")); + + foveon_fixed (dscr, 4, "DarkShieldColRange"); + foveon_fixed (ppm[0][0], 27, "PostPolyMatrix"); + foveon_fixed (satlev, 3, "SaturationLevel"); + foveon_fixed (keep, 4, "KeepImageArea"); + foveon_fixed (active, 4, "ActiveImageArea"); + foveon_fixed (chroma_dq, 3, "ChromaDQ"); + foveon_fixed (color_dq, 3, + foveon_camf_param ("IncludeBlocks", "ColorDQ") ? + "ColorDQ" : "ColorDQCamRGB"); + if (foveon_camf_param ("IncludeBlocks", "ColumnFilter")) + foveon_fixed (&cfilt, 1, "ColumnFilter"); + + memset (ddft, 0, sizeof ddft); + if (!foveon_camf_param ("IncludeBlocks", "DarkDrift") + || !foveon_fixed (ddft[1][0], 12, "DarkDrift")) + for (i=0; i < 2; i++) { + foveon_fixed (dstb, 4, i ? "DarkShieldBottom":"DarkShieldTop"); + for (row = dstb[1]; row <= dstb[3]; row++) + for (col = dstb[0]; col <= dstb[2]; col++) + FORC3 ddft[i+1][c][1] += (short) image[row*width+col][c]; + FORC3 ddft[i+1][c][1] /= (dstb[3]-dstb[1]+1) * (dstb[2]-dstb[0]+1); + } + + if (!(cp = foveon_camf_param ("WhiteBalanceIlluminants", model2))) + { fprintf (stderr,_("%s: Invalid white balance \"%s\"\n"), ifname, model2); + return; } + foveon_fixed (cam_xyz, 9, cp); + foveon_fixed (correct, 9, + foveon_camf_param ("WhiteBalanceCorrections", model2)); + memset (last, 0, sizeof last); + for (i=0; i < 3; i++) + for (j=0; j < 3; j++) + FORC3 last[i][j] += correct[i][c] * cam_xyz[c][j]; + + #define LAST(x,y) last[(i+x)%3][(c+y)%3] + for (i=0; i < 3; i++) + FORC3 diag[c][i] = LAST(1,1)*LAST(2,2) - LAST(1,2)*LAST(2,1); + #undef LAST + FORC3 div[c] = diag[c][0]*0.3127 + diag[c][1]*0.329 + diag[c][2]*0.3583; + sprintf (str, "%sRGBNeutral", model2); + if (foveon_camf_param ("IncludeBlocks", str)) + foveon_fixed (div, 3, str); + num = 0; + FORC3 if (num < div[c]) num = div[c]; + FORC3 div[c] /= num; + + memset (trans, 0, sizeof trans); + for (i=0; i < 3; i++) + for (j=0; j < 3; j++) + FORC3 trans[i][j] += rgb_cam[i][c] * last[c][j] * div[j]; + FORC3 trsum[c] = trans[c][0] + trans[c][1] + trans[c][2]; + dsum = (6*trsum[0] + 11*trsum[1] + 3*trsum[2]) / 20; + for (i=0; i < 3; i++) + FORC3 last[i][c] = trans[i][c] * dsum / trsum[i]; + memset (trans, 0, sizeof trans); + for (i=0; i < 3; i++) + for (j=0; j < 3; j++) + FORC3 trans[i][j] += (i==c ? 32 : -1) * last[c][j] / 30; + + foveon_make_curves (curve, color_dq, div, cfilt); + FORC3 chroma_dq[c] /= 3; + foveon_make_curves (curve+3, chroma_dq, div, cfilt); + FORC3 dsum += chroma_dq[c] / div[c]; + curve[6] = foveon_make_curve (dsum, dsum, cfilt); + curve[7] = foveon_make_curve (dsum*2, dsum*2, cfilt); + + sgain = (float (*)[3]) foveon_camf_matrix (dim, "SpatialGain"); + if (!sgain) return; + sgrow = (float (*)[3]) calloc (dim[1], sizeof *sgrow); + sgx = (width + dim[1]-2) / (dim[1]-1); + + black = (float (*)[3]) calloc (height, sizeof *black); + for (row=0; row < height; row++) { + for (i=0; i < 6; i++) + ddft[0][0][i] = ddft[1][0][i] + + row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]); + FORC3 black[row][c] = + ( foveon_avg (image[row*width]+c, dscr[0], cfilt) + + foveon_avg (image[row*width]+c, dscr[1], cfilt) * 3 + - ddft[0][c][0] ) / 4 - ddft[0][c][1]; + } + memcpy (black, black+8, sizeof *black*8); + memcpy (black+height-11, black+height-22, 11*sizeof *black); + memcpy (last, black, sizeof last); + + for (row=1; row < height-1; row++) { + FORC3 if (last[1][c] > last[0][c]) { + if (last[1][c] > last[2][c]) + black[row][c] = (last[0][c] > last[2][c]) ? last[0][c]:last[2][c]; + } else + if (last[1][c] < last[2][c]) + black[row][c] = (last[0][c] < last[2][c]) ? last[0][c]:last[2][c]; + memmove (last, last+1, 2*sizeof last[0]); + memcpy (last[2], black[row+1], sizeof last[2]); + } + FORC3 black[row][c] = (last[0][c] + last[1][c])/2; + FORC3 black[0][c] = (black[1][c] + black[3][c])/2; + + val = 1 - exp(-1/24.0); + memcpy (fsum, black, sizeof fsum); + for (row=1; row < height; row++) + FORC3 fsum[c] += black[row][c] = + (black[row][c] - black[row-1][c])*val + black[row-1][c]; + memcpy (last[0], black[height-1], sizeof last[0]); + FORC3 fsum[c] /= height; + for (row = height; row--; ) + FORC3 last[0][c] = black[row][c] = + (black[row][c] - fsum[c] - last[0][c])*val + last[0][c]; + + memset (total, 0, sizeof total); + for (row=2; row < height; row+=4) + for (col=2; col < width; col+=4) { + FORC3 total[c] += (short) image[row*width+col][c]; + total[3]++; + } + for (row=0; row < height; row++) + FORC3 black[row][c] += fsum[c]/2 + total[c]/(total[3]*100.0); + + for (row=0; row < height; row++) { + for (i=0; i < 6; i++) + ddft[0][0][i] = ddft[1][0][i] + + row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]); + pix = image[row*width]; + memcpy (prev, pix, sizeof prev); + frow = row / (height-1.0) * (dim[2]-1); + if ((irow = frow) == dim[2]-1) irow--; + frow -= irow; + for (i=0; i < dim[1]; i++) + FORC3 sgrow[i][c] = sgain[ irow *dim[1]+i][c] * (1-frow) + + sgain[(irow+1)*dim[1]+i][c] * frow; + for (col=0; col < width; col++) { + FORC3 { + diff = pix[c] - prev[c]; + prev[c] = pix[c]; + ipix[c] = pix[c] + floor ((diff + (diff*diff >> 14)) * cfilt + - ddft[0][c][1] - ddft[0][c][0] * ((float) col/width - 0.5) + - black[row][c] ); + } + FORC3 { + work[0][c] = ipix[c] * ipix[c] >> 14; + work[2][c] = ipix[c] * work[0][c] >> 14; + work[1][2-c] = ipix[(c+1) % 3] * ipix[(c+2) % 3] >> 14; + } + FORC3 { + for (val=i=0; i < 3; i++) + for ( j=0; j < 3; j++) + val += ppm[c][i][j] * work[i][j]; + ipix[c] = floor ((ipix[c] + floor(val)) * + ( sgrow[col/sgx ][c] * (sgx - col%sgx) + + sgrow[col/sgx+1][c] * (col%sgx) ) / sgx / div[c]); + if (ipix[c] > 32000) ipix[c] = 32000; + pix[c] = ipix[c]; + } + pix += 4; + } + } + free (black); + free (sgrow); + free (sgain); + + if ((badpix = (unsigned int *) foveon_camf_matrix (dim, "BadPixels"))) { + for (i=0; i < dim[0]; i++) { + col = (badpix[i] >> 8 & 0xfff) - keep[0]; + row = (badpix[i] >> 20 ) - keep[1]; + if ((unsigned)(row-1) > height-3 || (unsigned)(col-1) > width-3) + continue; + memset (fsum, 0, sizeof fsum); + for (sum=j=0; j < 8; j++) + if (badpix[i] & (1 << j)) { + FORC3 fsum[c] += (short) + image[(row+hood[j*2])*width+col+hood[j*2+1]][c]; + sum++; + } + if (sum) FORC3 image[row*width+col][c] = fsum[c]/sum; + } + free (badpix); + } + + /* Array for 5x5 Gaussian averaging of red values */ + smrow[6] = (int (*)[3]) calloc (width*5, sizeof **smrow); + merror (smrow[6], "foveon_interpolate()"); + for (i=0; i < 5; i++) + smrow[i] = smrow[6] + i*width; + + /* Sharpen the reds against these Gaussian averages */ + for (smlast=-1, row=2; row < height-2; row++) { + while (smlast < row+2) { + for (i=0; i < 6; i++) + smrow[(i+5) % 6] = smrow[i]; + pix = image[++smlast*width+2]; + for (col=2; col < width-2; col++) { + smrow[4][col][0] = + (pix[0]*6 + (pix[-4]+pix[4])*4 + pix[-8]+pix[8] + 8) >> 4; + pix += 4; + } + } + pix = image[row*width+2]; + for (col=2; col < width-2; col++) { + smred = ( 6 * smrow[2][col][0] + + 4 * (smrow[1][col][0] + smrow[3][col][0]) + + smrow[0][col][0] + smrow[4][col][0] + 8 ) >> 4; + if (col == 2) + smred_p = smred; + i = pix[0] + ((pix[0] - ((smred*7 + smred_p) >> 3)) >> 3); + if (i > 32000) i = 32000; + pix[0] = i; + smred_p = smred; + pix += 4; + } + } + + /* Adjust the brighter pixels for better linearity */ + min = 0xffff; + FORC3 { + i = satlev[c] / div[c]; + if (min > i) min = i; + } + limit = min * 9 >> 4; + for (pix=image[0]; pix < image[height*width]; pix+=4) { + if (pix[0] <= limit || pix[1] <= limit || pix[2] <= limit) + continue; + min = max = pix[0]; + for (c=1; c < 3; c++) { + if (min > pix[c]) min = pix[c]; + if (max < pix[c]) max = pix[c]; + } + if (min >= limit*2) { + pix[0] = pix[1] = pix[2] = max; + } else { + i = 0x4000 - ((min - limit) << 14) / limit; + i = 0x4000 - (i*i >> 14); + i = i*i >> 14; + FORC3 pix[c] += (max - pix[c]) * i >> 14; + } + } +/* + Because photons that miss one detector often hit another, + the sum R+G+B is much less noisy than the individual colors. + So smooth the hues without smoothing the total. + */ + for (smlast=-1, row=2; row < height-2; row++) { + while (smlast < row+2) { + for (i=0; i < 6; i++) + smrow[(i+5) % 6] = smrow[i]; + pix = image[++smlast*width+2]; + for (col=2; col < width-2; col++) { + FORC3 smrow[4][col][c] = (pix[c-4]+2*pix[c]+pix[c+4]+2) >> 2; + pix += 4; + } + } + pix = image[row*width+2]; + for (col=2; col < width-2; col++) { + FORC3 dev[c] = -foveon_apply_curve (curve[7], pix[c] - + ((smrow[1][col][c] + 2*smrow[2][col][c] + smrow[3][col][c]) >> 2)); + sum = (dev[0] + dev[1] + dev[2]) >> 3; + FORC3 pix[c] += dev[c] - sum; + pix += 4; + } + } + for (smlast=-1, row=2; row < height-2; row++) { + while (smlast < row+2) { + for (i=0; i < 6; i++) + smrow[(i+5) % 6] = smrow[i]; + pix = image[++smlast*width+2]; + for (col=2; col < width-2; col++) { + FORC3 smrow[4][col][c] = + (pix[c-8]+pix[c-4]+pix[c]+pix[c+4]+pix[c+8]+2) >> 2; + pix += 4; + } + } + pix = image[row*width+2]; + for (col=2; col < width-2; col++) { + for (total[3]=375, sum=60, c=0; c < 3; c++) { + for (total[c]=i=0; i < 5; i++) + total[c] += smrow[i][col][c]; + total[3] += total[c]; + sum += pix[c]; + } + if (sum < 0) sum = 0; + j = total[3] > 375 ? (sum << 16) / total[3] : sum * 174; + FORC3 pix[c] += foveon_apply_curve (curve[6], + ((j*total[c] + 0x8000) >> 16) - pix[c]); + pix += 4; + } + } + + /* Transform the image to a different colorspace */ + for (pix=image[0]; pix < image[height*width]; pix+=4) { + FORC3 pix[c] -= foveon_apply_curve (curve[c], pix[c]); + sum = (pix[0]+pix[1]+pix[1]+pix[2]) >> 2; + FORC3 pix[c] -= foveon_apply_curve (curve[c], pix[c]-sum); + FORC3 { + for (dsum=i=0; i < 3; i++) + dsum += trans[c][i] * pix[i]; + if (dsum < 0) dsum = 0; + if (dsum > 24000) dsum = 24000; + ipix[c] = dsum + 0.5; + } + FORC3 pix[c] = ipix[c]; + } + + /* Smooth the image bottom-to-top and save at 1/4 scale */ + shrink = (short (*)[3]) calloc ((width/4) * (height/4), sizeof *shrink); + merror (shrink, "foveon_interpolate()"); + for (row = height/4; row--; ) + for (col=0; col < width/4; col++) { + ipix[0] = ipix[1] = ipix[2] = 0; + for (i=0; i < 4; i++) + for (j=0; j < 4; j++) + FORC3 ipix[c] += image[(row*4+i)*width+col*4+j][c]; + FORC3 + if (row+2 > height/4) + shrink[row*(width/4)+col][c] = ipix[c] >> 4; + else + shrink[row*(width/4)+col][c] = + (shrink[(row+1)*(width/4)+col][c]*1840 + ipix[c]*141 + 2048) >> 12; + } + /* From the 1/4-scale image, smooth right-to-left */ + for (row=0; row < (height & ~3); row++) { + ipix[0] = ipix[1] = ipix[2] = 0; + if ((row & 3) == 0) + for (col = width & ~3 ; col--; ) + FORC3 smrow[0][col][c] = ipix[c] = + (shrink[(row/4)*(width/4)+col/4][c]*1485 + ipix[c]*6707 + 4096) >> 13; + + /* Then smooth left-to-right */ + ipix[0] = ipix[1] = ipix[2] = 0; + for (col=0; col < (width & ~3); col++) + FORC3 smrow[1][col][c] = ipix[c] = + (smrow[0][col][c]*1485 + ipix[c]*6707 + 4096) >> 13; + + /* Smooth top-to-bottom */ + if (row == 0) + memcpy (smrow[2], smrow[1], sizeof **smrow * width); + else + for (col=0; col < (width & ~3); col++) + FORC3 smrow[2][col][c] = + (smrow[2][col][c]*6707 + smrow[1][col][c]*1485 + 4096) >> 13; + + /* Adjust the chroma toward the smooth values */ + for (col=0; col < (width & ~3); col++) { + for (i=j=30, c=0; c < 3; c++) { + i += smrow[2][col][c]; + j += image[row*width+col][c]; + } + j = (j << 16) / i; + for (sum=c=0; c < 3; c++) { + ipix[c] = foveon_apply_curve (curve[c+3], + ((smrow[2][col][c] * j + 0x8000) >> 16) - image[row*width+col][c]); + sum += ipix[c]; + } + sum >>= 3; + FORC3 { + i = image[row*width+col][c] + ipix[c] - sum; + if (i < 0) i = 0; + image[row*width+col][c] = i; + } + } + } + free (shrink); + free (smrow[6]); + for (i=0; i < 8; i++) + free (curve[i]); + + /* Trim off the black border */ + active[1] -= keep[1]; + active[3] -= 2; + i = active[2] - active[0]; + for (row=0; row < active[3]-active[1]; row++) + memcpy (image[row*i], image[(row+active[1])*width+active[0]], + i * sizeof *image); + width = i; + height = row; +} +#undef image + +/* RESTRICTED code ends here */ + +/* + Seach from the current directory up to the root looking for + a ".badpixels" file, and fix those pixels now. + */ +void CLASS bad_pixels() +{ + FILE *fp=0; + char *fname, *cp, line[128]; + int len, time, row, col, r, c, rad, tot, n, fixed=0; + + if (!filters) return; + for (len=32 ; ; len *= 2) { + fname = (char *) malloc (len); + if (!fname) return; + if (getcwd (fname, len-16)) break; + free (fname); + if (errno != ERANGE) return; + } +#if defined(WIN32) || defined(DJGPP) + if (fname[1] == ':') + memmove (fname, fname+2, len-2); + for (cp=fname; *cp; cp++) + if (*cp == '\\') *cp = '/'; +#endif + cp = fname + strlen(fname); + if (cp[-1] == '/') cp--; + while (*fname == '/') { + strcpy (cp, "/.badpixels"); + if ((fp = fopen (fname, "r"))) break; + if (cp == fname) break; + while (*--cp != '/'); + } + free (fname); + if (!fp) return; + while (fgets (line, 128, fp)) { + cp = strchr (line, '#'); + if (cp) *cp = 0; + if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) continue; + if ((unsigned) col >= width || (unsigned) row >= height) continue; + if (time > timestamp) continue; + for (tot=n=0, rad=1; rad < 3 && n==0; rad++) + for (r = row-rad; r <= row+rad; r++) + for (c = col-rad; c <= col+rad; c++) + if ((unsigned) r < height && (unsigned) c < width && + (r != row || c != col) && fc(r,c) == fc(row,col)) { + tot += BAYER2(r,c); + n++; + } + BAYER2(row,col) = tot/n; + if (verbose) { + if (!fixed++) + fprintf (stderr,_("Fixed bad pixels at:")); + fprintf (stderr, " %d,%d", col, row); + } + } + if (fixed) fputc ('\n', stderr); + fclose (fp); +} + +void CLASS subtract (char *fname) +{ + FILE *fp; + int dim[3]={0,0,0}, comment=0, number=0, error=0, nd=0, c, row, col; + ushort *pixel; + + if (!(fp = fopen (fname, "rb"))) { + perror (fname); return; + } + if (fgetc(fp) != 'P' || fgetc(fp) != '5') error = 1; + while (!error && nd < 3 && (c = fgetc(fp)) != EOF) { + if (c == '#') comment = 1; + if (c == '\n') comment = 0; + if (comment) continue; + if (isdigit(c)) number = 1; + if (number) { + if (isdigit(c)) dim[nd] = dim[nd]*10 + c -'0'; + else if (isspace(c)) { + number = 0; nd++; + } else error = 1; + } + } + if (error || nd < 3) { + fprintf (stderr,_("%s is not a valid PGM file!\n"), fname); + fclose (fp); return; + } else if (dim[0] != width || dim[1] != height || dim[2] != 65535) { + fprintf (stderr,_("%s has the wrong dimensions!\n"), fname); + fclose (fp); return; + } + pixel = (ushort *) calloc (width, sizeof *pixel); + merror (pixel, "subtract()"); + for (row=0; row < height; row++) { + fread (pixel, 2, width, fp); + for (col=0; col < width; col++) + BAYER(row,col) = MAX (BAYER(row,col) - ntohs(pixel[col]), 0); + } + free (pixel); + black = 0; +} + +void CLASS pseudoinverse (double (*in)[3], double (*out)[3], int size) +{ + double work[3][6], num; + int i, j, k; + + for (i=0; i < 3; i++) { + for (j=0; j < 6; j++) + work[i][j] = j == i+3; + for (j=0; j < 3; j++) + for (k=0; k < size; k++) + work[i][j] += in[k][i] * in[k][j]; + } + for (i=0; i < 3; i++) { + num = work[i][i]; + for (j=0; j < 6; j++) + work[i][j] /= num; + for (k=0; k < 3; k++) { + if (k==i) continue; + num = work[k][i]; + for (j=0; j < 6; j++) + work[k][j] -= work[i][j] * num; + } + } + for (i=0; i < size; i++) + for (j=0; j < 3; j++) + for (out[i][j]=k=0; k < 3; k++) + out[i][j] += work[j][k+3] * in[i][k]; +} + +void CLASS cam_xyz_coeff (double cam_xyz[4][3]) +{ + double cam_rgb[4][3], inverse[4][3], num; + int i, j, k; + + for (i=0; i < colors; i++) /* Multiply out XYZ colorspace */ + for (j=0; j < 3; j++) + for (cam_rgb[i][j] = k=0; k < 3; k++) + cam_rgb[i][j] += cam_xyz[i][k] * xyz_rgb[k][j]; + + for (i=0; i < colors; i++) { /* Normalize cam_rgb so that */ + for (num=j=0; j < 3; j++) /* cam_rgb * (1,1,1) is (1,1,1,1) */ + num += cam_rgb[i][j]; + for (j=0; j < 3; j++) + cam_rgb[i][j] /= num; + pre_mul[i] = 1 / num; + } + pseudoinverse (cam_rgb, inverse, colors); + for (raw_color = i=0; i < 3; i++) + for (j=0; j < colors; j++) + rgb_cam[i][j] = inverse[j][i]; +} + +#ifdef COLORCHECK +void CLASS colorcheck() +{ +#define NSQ 24 +// Coordinates of the GretagMacbeth ColorChecker squares +// width, height, 1st_column, 1st_row + static const int cut[NSQ][4] = { + { 241, 231, 234, 274 }, + { 251, 235, 534, 274 }, + { 255, 239, 838, 272 }, + { 255, 240, 1146, 274 }, + { 251, 237, 1452, 278 }, + { 243, 238, 1758, 288 }, + { 253, 253, 218, 558 }, + { 255, 249, 524, 562 }, + { 261, 253, 830, 562 }, + { 260, 255, 1144, 564 }, + { 261, 255, 1450, 566 }, + { 247, 247, 1764, 576 }, + { 255, 251, 212, 862 }, + { 259, 259, 518, 862 }, + { 263, 261, 826, 864 }, + { 265, 263, 1138, 866 }, + { 265, 257, 1450, 872 }, + { 257, 255, 1762, 874 }, + { 257, 253, 212, 1164 }, + { 262, 251, 516, 1172 }, + { 263, 257, 826, 1172 }, + { 263, 255, 1136, 1176 }, + { 255, 252, 1452, 1182 }, + { 257, 253, 1760, 1180 } }; +// ColorChecker Chart under 6500-kelvin illumination + static const double gmb_xyY[NSQ][3] = { + { 0.400, 0.350, 10.1 }, // Dark Skin + { 0.377, 0.345, 35.8 }, // Light Skin + { 0.247, 0.251, 19.3 }, // Blue Sky + { 0.337, 0.422, 13.3 }, // Foliage + { 0.265, 0.240, 24.3 }, // Blue Flower + { 0.261, 0.343, 43.1 }, // Bluish Green + { 0.506, 0.407, 30.1 }, // Orange + { 0.211, 0.175, 12.0 }, // Purplish Blue + { 0.453, 0.306, 19.8 }, // Moderate Red + { 0.285, 0.202, 6.6 }, // Purple + { 0.380, 0.489, 44.3 }, // Yellow Green + { 0.473, 0.438, 43.1 }, // Orange Yellow + { 0.187, 0.129, 6.1 }, // Blue + { 0.305, 0.478, 23.4 }, // Green + { 0.539, 0.313, 12.0 }, // Red + { 0.448, 0.470, 59.1 }, // Yellow + { 0.364, 0.233, 19.8 }, // Magenta + { 0.196, 0.252, 19.8 }, // Cyan + { 0.310, 0.316, 90.0 }, // White + { 0.310, 0.316, 59.1 }, // Neutral 8 + { 0.310, 0.316, 36.2 }, // Neutral 6.5 + { 0.310, 0.316, 19.8 }, // Neutral 5 + { 0.310, 0.316, 9.0 }, // Neutral 3.5 + { 0.310, 0.316, 3.1 } }; // Black + double gmb_cam[NSQ][4], gmb_xyz[NSQ][3]; + double inverse[NSQ][3], cam_xyz[4][3], num; + int c, i, j, k, sq, row, col, count[4]; + + memset (gmb_cam, 0, sizeof gmb_cam); + for (sq=0; sq < NSQ; sq++) { + FORCC count[c] = 0; + for (row=cut[sq][3]; row < cut[sq][3]+cut[sq][1]; row++) + for (col=cut[sq][2]; col < cut[sq][2]+cut[sq][0]; col++) { + c = FC(row,col); + if (c >= colors) c -= 2; + gmb_cam[sq][c] += BAYER(row,col); + count[c]++; + } + FORCC gmb_cam[sq][c] = gmb_cam[sq][c]/count[c] - black; + gmb_xyz[sq][0] = gmb_xyY[sq][2] * gmb_xyY[sq][0] / gmb_xyY[sq][1]; + gmb_xyz[sq][1] = gmb_xyY[sq][2]; + gmb_xyz[sq][2] = gmb_xyY[sq][2] * + (1 - gmb_xyY[sq][0] - gmb_xyY[sq][1]) / gmb_xyY[sq][1]; + } + pseudoinverse (gmb_xyz, inverse, NSQ); + for (i=0; i < colors; i++) + for (j=0; j < 3; j++) + for (cam_xyz[i][j] = k=0; k < NSQ; k++) + cam_xyz[i][j] += gmb_cam[k][i] * inverse[k][j]; + cam_xyz_coeff (cam_xyz); + if (verbose) { + printf (" { \"%s %s\", %d,\n\t{", make, model, black); + num = 10000 / (cam_xyz[1][0] + cam_xyz[1][1] + cam_xyz[1][2]); + FORCC for (j=0; j < 3; j++) + printf ("%c%d", (c | j) ? ',':' ', (int) (cam_xyz[c][j] * num + 0.5)); + puts (" } },"); + } +#undef NSQ +} +#endif + +void CLASS hat_transform (float *temp, float *base, int st, int size, int sc) +{ + int i; + for (i=0; i < sc; i++) + temp[i] = 2*base[st*i] + base[st*(sc-i)] + base[st*(i+sc)]; + for (; i+sc < size; i++) + temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(i+sc)]; + for (; i < size; i++) + temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(2*size-2-(i+sc))]; +} + +void CLASS wavelet_denoise() +{ + float *fimg=0, *temp, thold, mul[2], avg, diff; + int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast; + ushort *window[4]; + static const float noise[] = + { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 }; + + if (verbose) fprintf (stderr,_("Wavelet denoising...\n")); + + while (maximum << scale < 0x10000) scale++; + maximum <<= --scale; + black <<= scale; + if ((size = iheight*iwidth) < 0x15550000) + fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg); + merror (fimg, "wavelet_denoise()"); + temp = fimg + size*3; + if ((nc = colors) == 3 && filters) nc++; + for (c=0; c < nc; c++) { /* denoise R,G1,B,G3 individually */ + for (i=0; i < size; i++) + fimg[i] = sqrt((unsigned) (image[i][c] << (scale+16))); + for (hpass=lev=0; lev < 5; lev++) { + lpass = size*((lev & 1)+1); + for (row=0; row < iheight; row++) { + hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev); + for (col=0; col < iwidth; col++) + fimg[lpass + row*iwidth + col] = temp[col] * 0.25; + } + for (col=0; col < iwidth; col++) { + hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev); + for (row=0; row < iheight; row++) + fimg[lpass + row*iwidth + col] = temp[row] * 0.25; + } + thold = threshold * noise[lev]; + for (i=0; i < size; i++) { + fimg[hpass+i] -= fimg[lpass+i]; + if (fimg[hpass+i] < -thold) fimg[hpass+i] += thold; + else if (fimg[hpass+i] > thold) fimg[hpass+i] -= thold; + else fimg[hpass+i] = 0; + if (hpass) fimg[i] += fimg[hpass+i]; + } + hpass = lpass; + } + for (i=0; i < size; i++) + image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000); + } + if (filters && colors == 3) { /* pull G1 and G3 closer together */ + for (row=0; row < 2; row++) + mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1]; + for (i=0; i < 4; i++) + window[i] = (ushort *) fimg + width*i; + for (wlast=-1, row=1; row < height-1; row++) { + while (wlast < row+1) { + for (wlast++, i=0; i < 4; i++) + window[(i+3) & 3] = window[i]; + for (col = FC(wlast,1) & 1; col < width; col+=2) + window[2][col] = BAYER(wlast,col); + } + thold = threshold/512; + for (col = (FC(row,0) & 1)+1; col < width-1; col+=2) { + avg = ( window[0][col-1] + window[0][col+1] + + window[2][col-1] + window[2][col+1] - black*4 ) + * mul[row & 1] + (window[1][col] - black) * 0.5 + black; + avg = avg < 0 ? 0 : sqrt(avg); + diff = sqrt(BAYER(row,col)) - avg; + if (diff < -thold) diff += thold; + else if (diff > thold) diff -= thold; + else diff = 0; + BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5); + } + } + } + free (fimg); +} + +void CLASS scale_colors() +{ + unsigned bottom, right, size, row, col, ur, uc, i, x, y, c, sum[8]; + int val, dblack; + double dsum[8], dmin, dmax; + float scale_mul[4], fr, fc; + ushort *img=0, *pix; + + if (user_mul[0]) + memcpy (pre_mul, user_mul, sizeof pre_mul); + if (use_auto_wb || (use_camera_wb && cam_mul[0] == -1)) { + memset (dsum, 0, sizeof dsum); + bottom = MIN (greybox[1]+greybox[3], height); + right = MIN (greybox[0]+greybox[2], width); + for (row=greybox[1]; row < bottom; row += 8) + for (col=greybox[0]; col < right; col += 8) { + memset (sum, 0, sizeof sum); + for (y=row; y < row+8 && y < bottom; y++) + for (x=col; x < col+8 && x < right; x++) + FORC4 { + if (filters) { + c = FC(y,x); + val = BAYER(y,x); + } else + val = image[y*width+x][c]; + if (val > maximum-25) goto skip_block; + if ((val -= black) < 0) val = 0; + sum[c] += val; + sum[c+4]++; + if (filters) break; + } + for (c=0; c < 8; c++) dsum[c] += sum[c]; +skip_block: ; + } + FORC4 if (dsum[c]) pre_mul[c] = dsum[c+4] / dsum[c]; + } + if (use_camera_wb && cam_mul[0] != -1) { + memset (sum, 0, sizeof sum); + for (row=0; row < 8; row++) + for (col=0; col < 8; col++) { + c = FC(row,col); + if ((val = white[row][col] - black) > 0) + sum[c] += val; + sum[c+4]++; + } + if (sum[0] && sum[1] && sum[2] && sum[3]) + FORC4 pre_mul[c] = (float) sum[c+4] / sum[c]; + else if (cam_mul[0] && cam_mul[2]) + memcpy (pre_mul, cam_mul, sizeof pre_mul); + else + fprintf (stderr,_("%s: Cannot use camera white balance.\n"), ifname); + } + if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1; + dblack = black; + if (threshold) wavelet_denoise(); + maximum -= black; + for (dmin=DBL_MAX, dmax=c=0; c < 4; c++) { + if (dmin > pre_mul[c]) + dmin = pre_mul[c]; + if (dmax < pre_mul[c]) + dmax = pre_mul[c]; + } + if (!highlight) dmax = dmin; + FORC4 scale_mul[c] = (pre_mul[c] /= dmax) * 65535.0 / maximum; + if (verbose) { + fprintf (stderr,_("Scaling with black %d, multipliers"), dblack); + FORC4 fprintf (stderr, " %f", pre_mul[c]); + fputc ('\n', stderr); + } + size = iheight*iwidth; + for (i=0; i < size*4; i++) { + val = image[0][i]; + if (!val) continue; + val -= black; + val *= scale_mul[i & 3]; + image[0][i] = CLIP(val); + } + if ((aber[0] != 1 || aber[2] != 1) && colors == 3) { + if (verbose) + fprintf (stderr,_("Correcting chromatic aberration...\n")); + for (c=0; c < 4; c+=2) { + if (aber[c] == 1) continue; + img = (ushort *) malloc (size * sizeof *img); + merror (img, "scale_colors()"); + for (i=0; i < size; i++) + img[i] = image[i][c]; + for (row=0; row < iheight; row++) { + ur = fr = (row - iheight*0.5) * aber[c] + iheight*0.5; + if (ur > iheight-2) continue; + fr -= ur; + for (col=0; col < iwidth; col++) { + uc = fc = (col - iwidth*0.5) * aber[c] + iwidth*0.5; + if (uc > iwidth-2) continue; + fc -= uc; + pix = img + ur*iwidth + uc; + image[row*iwidth+col][c] = + (pix[ 0]*(1-fc) + pix[ 1]*fc) * (1-fr) + + (pix[iwidth]*(1-fc) + pix[iwidth+1]*fc) * fr; + } + } + free(img); + } + } +} + +void CLASS pre_interpolate() +{ + ushort (*img)[4]; + int row, col, c; + + if (shrink) { + if (half_size) { + height = iheight; + width = iwidth; + } else { + img = (ushort (*)[4]) calloc (height*width, sizeof *img); + merror (img, "unshrink()"); + for (row=0; row < height; row++) + for (col=0; col < width; col++) { + c = fc(row,col); + img[row*width+col][c] = image[(row >> 1)*iwidth+(col >> 1)][c]; + } + free (image); + image = img; + shrink = 0; + } + } + if (filters && colors == 3) { + if ((mix_green = four_color_rgb)) colors++; + else { + for (row = FC(1,0) >> 1; row < height; row+=2) + for (col = FC(row,1) & 1; col < width; col+=2) + image[row*width+col][1] = image[row*width+col][3]; + filters &= ~((filters & 0x55555555) << 1); + } + } + if (half_size) filters = 0; +} + +void CLASS border_interpolate (int border) +{ + unsigned row, col, y, x, f, c, sum[8]; + + for (row=0; row < height; row++) + for (col=0; col < width; col++) { + if (col==border && row >= border && row < height-border) + col = width-border; + memset (sum, 0, sizeof sum); + for (y=row-1; y != row+2; y++) + for (x=col-1; x != col+2; x++) + if (y < height && x < width) { + f = fc(y,x); + sum[f] += image[y*width+x][f]; + sum[f+4]++; + } + f = fc(row,col); + FORCC if (c != f && sum[c+4]) + image[row*width+col][c] = sum[c] / sum[c+4]; + } +} + +void CLASS lin_interpolate() +{ + int code[16][16][32], *ip, sum[4]; + int c, i, x, y, row, col, shift, color; + ushort *pix; + + if (verbose) fprintf (stderr,_("Bilinear interpolation...\n")); + + border_interpolate(1); + for (row=0; row < 16; row++) + for (col=0; col < 16; col++) { + ip = code[row][col]; + memset (sum, 0, sizeof sum); + for (y=-1; y <= 1; y++) + for (x=-1; x <= 1; x++) { + shift = (y==0) + (x==0); + if (shift == 2) continue; + color = fc(row+y,col+x); + *ip++ = (width*y + x)*4 + color; + *ip++ = shift; + *ip++ = color; + sum[color] += 1 << shift; + } + FORCC + if (c != fc(row,col)) { + *ip++ = c; + *ip++ = 256 / sum[c]; + } + } + for (row=1; row < height-1; row++) + for (col=1; col < width-1; col++) { + pix = image[row*width+col]; + ip = code[row & 15][col & 15]; + memset (sum, 0, sizeof sum); + for (i=8; i--; ip+=3) + sum[ip[2]] += pix[ip[0]] << ip[1]; + for (i=colors; --i; ip+=2) + pix[ip[0]] = sum[ip[0]] * ip[1] >> 8; + } +} + +/* + This algorithm is officially called: + + "Interpolation using a Threshold-based variable number of gradients" + + described in http://scien.stanford.edu/class/psych221/projects/99/tingchen/algodep/vargra.html + + I've extended the basic idea to work with non-Bayer filter arrays. + Gradients are numbered clockwise from NW=0 to W=7. + */ +void CLASS vng_interpolate() +{ + static const signed char *cp, terms[] = { + -2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01, + -2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01, + -2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03, + -2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06, + -2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04, + -1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01, + -1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40, + -1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11, + -1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11, + -1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22, + -1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44, + -1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10, + -1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04, + +0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40, + +0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20, + +0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08, + +0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20, + +0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44, + +0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60, + +0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80, + +1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40, + +1,+0,+2,+1,0,0x10 + }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 }; + ushort (*brow[5])[4], *pix; + int prow=7, pcol=1, *ip, *code[16][16], gval[8], gmin, gmax, sum[4]; + int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag; + int g, diff, thold, num, c; + + lin_interpolate(); + if (verbose) fprintf (stderr,_("VNG interpolation...\n")); + + if (filters == 1) prow = pcol = 15; + ip = (int *) calloc ((prow+1)*(pcol+1), 1280); + merror (ip, "vng_interpolate()"); + for (row=0; row <= prow; row++) /* Precalculate for VNG */ + for (col=0; col <= pcol; col++) { + code[row][col] = ip; + for (cp=terms, t=0; t < 64; t++) { + y1 = *cp++; x1 = *cp++; + y2 = *cp++; x2 = *cp++; + weight = *cp++; + grads = *cp++; + color = fc(row+y1,col+x1); + if (fc(row+y2,col+x2) != color) continue; + diag = (fc(row,col+1) == color && fc(row+1,col) == color) ? 2:1; + if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue; + *ip++ = (y1*width + x1)*4 + color; + *ip++ = (y2*width + x2)*4 + color; + *ip++ = weight; + for (g=0; g < 8; g++) + if (grads & 1< gval[g]) gmin = gval[g]; + if (gmax < gval[g]) gmax = gval[g]; + } + if (gmax == 0) { + memcpy (brow[2][col], pix, sizeof *image); + continue; + } + thold = gmin + (gmax >> 1); + memset (sum, 0, sizeof sum); + color = fc(row,col); + for (num=g=0; g < 8; g++,ip+=2) { /* Average the neighbors */ + if (gval[g] <= thold) { + FORCC + if (c == color && ip[1]) + sum[c] += (pix[c] + pix[ip[1]]) >> 1; + else + sum[c] += pix[ip[0] + c]; + num++; + } + } + FORCC { /* Save to buffer */ + t = pix[color]; + if (c != color) + t += (sum[c] - sum[color]) / num; + brow[2][col][c] = CLIP(t); + } + } + if (row > 3) /* Write buffer to image */ + memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image); + for (g=0; g < 4; g++) + brow[(g-1) & 3] = brow[g]; + } + memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image); + memcpy (image[(row-1)*width+2], brow[1]+2, (width-4)*sizeof *image); + free (brow[4]); + free (code[0][0]); +} + +/* + Patterned Pixel Grouping Interpolation by Alain Desbiolles +*/ +void CLASS ppg_interpolate() +{ + int gr[4], dir[5] = { 1, width, -1, -width, 1 }; + int row, col, avg, diff[2], guess[2], c, d, i; + static const short sort[] = { 0,2,1,3,0,1,2,3 }; + ushort (*pix)[4]; + + border_interpolate(3); + if (verbose) fprintf (stderr,_("PPG interpolation...\n")); + +/* Fill in the green layer with gradients and pattern recognition: */ + for (row=3; row < height-3; row++) + for (col=3+(FC(row,3) & 1), c=FC(row,col); col < width-3; col+=2) { + pix = image + row*width+col; + for (avg=i=0; i < 4; i++) + avg += gr[i] = pix[dir[i]][1] << 2; + avg >>= 2; + for (i=0; i < 8; i+=2) + if (gr[sort[i]] > gr[sort[i+1]]) + SWAP(gr[sort[i]],gr[sort[i+1]]) + for (d=0; d < 4; d++) { + for (i=-2; i < 2; i++) + if (pix[i*dir[d] + (i+1)*dir[d+1]][1] <= avg) break; + if (i == 2) { + pix[0][1] = (gr[1]+gr[2]) >> 3; + goto next_pixel; + } + } + for (i=0; (d=dir[i]) > 0; i++) { + guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2 + - pix[-2*d][c] - pix[2*d][c]; + diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) + + ABS(pix[ 2*d][c] - pix[ 0][c]) + + ABS(pix[ -d][1] - pix[ d][1]) ) * 3 + + ( ABS(pix[ 3*d][1] - pix[ d][1]) + + ABS(pix[-3*d][1] - pix[-d][1]) ) * 2; + } + d = dir[i = diff[0] > diff[1]]; + pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]); +next_pixel: ; + } +/* Calculate red and blue for each green pixel: */ + for (row=1; row < height-1; row++) + for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) { + pix = image + row*width+col; + for (i=0; (d=dir[i]) > 0; c=2-c, i++) + pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2*pix[0][1] + - pix[-d][1] - pix[d][1]) >> 1); + } +/* Calculate blue for red pixels and vice versa: */ + for (row=1; row < height-1; row++) + for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) { + pix = image + row*width+col; + for (i=0; (d=dir[i]+dir[i+1]) > 0; i++) { + diff[i] = ABS(pix[-d][c] - pix[d][c]) + + ABS(pix[-d][1] - pix[0][1]) + + ABS(pix[ d][1] - pix[0][1]); + guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1] + - pix[-d][1] - pix[d][1]; + } + if (diff[0] != diff[1]) + pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1); + else + pix[0][c] = CLIP((guess[0]+guess[1]) >> 2); + } +} + +/* + Adaptive Homogeneity-Directed interpolation is based on + the work of Keigo Hirakawa, Thomas Parks, and Paul Lee. + */ +#define TS 256 /* Tile Size */ + +void CLASS ahd_interpolate() +{ + int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2]; + ushort (*pix)[4], (*rix)[3]; + static const int dir[4] = { -1, 1, -TS, TS }; + unsigned ldiff[2][4], abdiff[2][4], leps, abeps; + float r, cbrt[0x10000], xyz[3], xyz_cam[3][4]; + ushort (*rgb)[TS][TS][3]; + short (*lab)[TS][TS][3], (*lix)[3]; + char (*homo)[TS][TS], *buffer; + + if (verbose) fprintf (stderr,_("AHD interpolation...\n")); + + for (i=0; i < 0x10000; i++) { + r = i / 65535.0; + cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0; + } + for (i=0; i < 3; i++) + for (j=0; j < colors; j++) + for (xyz_cam[i][j] = k=0; k < 3; k++) + xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i]; + + border_interpolate(5); + buffer = (char *) malloc (26*TS*TS); /* 1664 kB */ + merror (buffer, "ahd_interpolate()"); + rgb = (ushort(*)[TS][TS][3]) buffer; + lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS); + homo = (char (*)[TS][TS]) (buffer + 24*TS*TS); + + for (top=2; top < height-5; top += TS-6) + for (left=2; left < width-5; left += TS-6) { + +/* Interpolate green horizontally and vertically: */ + for (row = top; row < top+TS && row < height-2; row++) { + col = left + (FC(row,left) & 1); + for (c = FC(row,col); col < left+TS && col < width-2; col+=2) { + pix = image + row*width+col; + val = ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2 + - pix[-2][c] - pix[2][c]) >> 2; + rgb[0][row-top][col-left][1] = ULIM(val,pix[-1][1],pix[1][1]); + val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2 + - pix[-2*width][c] - pix[2*width][c]) >> 2; + rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]); + } + } +/* Interpolate red and blue, and convert to CIELab: */ + for (d=0; d < 2; d++) + for (row=top+1; row < top+TS-1 && row < height-3; row++) + for (col=left+1; col < left+TS-1 && col < width-3; col++) { + pix = image + row*width+col; + rix = &rgb[d][row-top][col-left]; + lix = &lab[d][row-top][col-left]; + if ((c = 2 - FC(row,col)) == 1) { + c = FC(row+1,col); + val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c] + - rix[-1][1] - rix[1][1] ) >> 1); + rix[0][2-c] = CLIP(val); + val = pix[0][1] + (( pix[-width][c] + pix[width][c] + - rix[-TS][1] - rix[TS][1] ) >> 1); + } else + val = rix[0][1] + (( pix[-width-1][c] + pix[-width+1][c] + + pix[+width-1][c] + pix[+width+1][c] + - rix[-TS-1][1] - rix[-TS+1][1] + - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2); + rix[0][c] = CLIP(val); + c = FC(row,col); + rix[0][c] = pix[0][c]; + xyz[0] = xyz[1] = xyz[2] = 0.5; + FORCC { + xyz[0] += xyz_cam[0][c] * rix[0][c]; + xyz[1] += xyz_cam[1][c] * rix[0][c]; + xyz[2] += xyz_cam[2][c] * rix[0][c]; + } + xyz[0] = cbrt[CLIP((int) xyz[0])]; + xyz[1] = cbrt[CLIP((int) xyz[1])]; + xyz[2] = cbrt[CLIP((int) xyz[2])]; + lix[0][0] = 64 * (116 * xyz[1] - 16); + lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]); + lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]); + } +/* Build homogeneity maps from the CIELab images: */ + memset (homo, 0, 2*TS*TS); + for (row=top+2; row < top+TS-2 && row < height-4; row++) { + tr = row-top; + for (col=left+2; col < left+TS-2 && col < width-4; col++) { + tc = col-left; + for (d=0; d < 2; d++) { + lix = &lab[d][tr][tc]; + for (i=0; i < 4; i++) { + ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]); + abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1]) + + SQR(lix[0][2]-lix[dir[i]][2]); + } + } + leps = MIN(MAX(ldiff[0][0],ldiff[0][1]), + MAX(ldiff[1][2],ldiff[1][3])); + abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]), + MAX(abdiff[1][2],abdiff[1][3])); + for (d=0; d < 2; d++) + for (i=0; i < 4; i++) + if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps) + homo[d][tr][tc]++; + } + } +/* Combine the most homogenous pixels for the final result: */ + for (row=top+3; row < top+TS-3 && row < height-5; row++) { + tr = row-top; + for (col=left+3; col < left+TS-3 && col < width-5; col++) { + tc = col-left; + for (d=0; d < 2; d++) + for (hm[d]=0, i=tr-1; i <= tr+1; i++) + for (j=tc-1; j <= tc+1; j++) + hm[d] += homo[d][i][j]; + if (hm[0] != hm[1]) + FORC3 image[row*width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c]; + else + FORC3 image[row*width+col][c] = + (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1; + } + } + } + free (buffer); +} +#undef TS + +void CLASS median_filter () +{ + ushort (*pix)[4]; + int pass, c, i, j, k, med[9]; + static const uchar opt[] = /* Optimal 9-element median search */ + { 1,2, 4,5, 7,8, 0,1, 3,4, 6,7, 1,2, 4,5, 7,8, + 0,3, 5,8, 4,7, 3,6, 1,4, 2,5, 4,7, 4,2, 6,4, 4,2 }; + + for (pass=1; pass <= med_passes; pass++) { + if (verbose) + fprintf (stderr,_("Median filter pass %d...\n"), pass); + for (c=0; c < 3; c+=2) { + for (pix = image; pix < image+width*height; pix++) + pix[0][3] = pix[0][c]; + for (pix = image+width; pix < image+width*(height-1); pix++) { + if ((pix-image+1) % width < 2) continue; + for (k=0, i = -width; i <= width; i += width) + for (j = i-1; j <= i+1; j++) + med[k++] = pix[j][3] - pix[j][1]; + for (i=0; i < sizeof opt; i+=2) + if (med[opt[i]] > med[opt[i+1]]) + SWAP (med[opt[i]] , med[opt[i+1]]); + pix[0][c] = CLIP(med[4] + pix[0][1]); + } + } + } +} + +void CLASS blend_highlights() +{ + int clip=INT_MAX, row, col, c, i, j; + static const float trans[2][4][4] = + { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } }, + { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } }; + static const float itrans[2][4][4] = + { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } }, + { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } }; + float cam[2][4], lab[2][4], sum[2], chratio; + + if ((unsigned) (colors-3) > 1) return; + if (verbose) fprintf (stderr,_("Blending highlights...\n")); + FORCC if (clip > (i = 65535*pre_mul[c])) clip = i; + for (row=0; row < height; row++) + for (col=0; col < width; col++) { + FORCC if (image[row*width+col][c] > clip) break; + if (c == colors) continue; + FORCC { + cam[0][c] = image[row*width+col][c]; + cam[1][c] = MIN(cam[0][c],clip); + } + for (i=0; i < 2; i++) { + FORCC for (lab[i][c]=j=0; j < colors; j++) + lab[i][c] += trans[colors-3][c][j] * cam[i][j]; + for (sum[i]=0,c=1; c < colors; c++) + sum[i] += SQR(lab[i][c]); + } + chratio = sqrt(sum[1]/sum[0]); + for (c=1; c < colors; c++) + lab[0][c] *= chratio; + FORCC for (cam[0][c]=j=0; j < colors; j++) + cam[0][c] += itrans[colors-3][c][j] * lab[0][j]; + FORCC image[row*width+col][c] = cam[0][c] / colors; + } +} + +#define SCALE (4 >> shrink) +void CLASS recover_highlights() +{ + float *map, sum, wgt, grow; + int hsat[4], count, spread, change, val, i; + unsigned high, wide, mrow, mcol, row, col, kc, c, d, y, x; + ushort *pixel; + static const signed char dir[8][2] = + { {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1} }; + + if (verbose) fprintf (stderr,_("Rebuilding highlights...\n")); + + grow = pow (2, 4-highlight); + FORCC hsat[c] = 32000 * pre_mul[c]; + for (kc=0, c=1; c < colors; c++) + if (pre_mul[kc] < pre_mul[c]) kc = c; + high = height / SCALE; + wide = width / SCALE; + map = (float *) calloc (high*wide, sizeof *map); + merror (map, "recover_highlights()"); + FORCC if (c != kc) { + memset (map, 0, high*wide*sizeof *map); + for (mrow=0; mrow < high; mrow++) + for (mcol=0; mcol < wide; mcol++) { + sum = wgt = count = 0; + for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++) + for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) { + pixel = image[row*width+col]; + if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000) { + sum += pixel[c]; + wgt += pixel[kc]; + count++; + } + } + if (count == SCALE*SCALE) + map[mrow*wide+mcol] = sum / wgt; + } + for (spread = 32/grow; spread--; ) { + for (mrow=0; mrow < high; mrow++) + for (mcol=0; mcol < wide; mcol++) { + if (map[mrow*wide+mcol]) continue; + sum = count = 0; + for (d=0; d < 8; d++) { + y = mrow + dir[d][0]; + x = mcol + dir[d][1]; + if (y < high && x < wide && map[y*wide+x] > 0) { + sum += (1 + (d & 1)) * map[y*wide+x]; + count += 1 + (d & 1); + } + } + if (count > 3) + map[mrow*wide+mcol] = - (sum+grow) / (count+grow); + } + for (change=i=0; i < high*wide; i++) + if (map[i] < 0) { + map[i] = -map[i]; + change = 1; + } + if (!change) break; + } + for (i=0; i < high*wide; i++) + if (map[i] == 0) map[i] = 1; + for (mrow=0; mrow < high; mrow++) + for (mcol=0; mcol < wide; mcol++) { + for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++) + for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) { + pixel = image[row*width+col]; + if (pixel[c] / hsat[c] > 1) { + val = pixel[kc] * map[mrow*wide+mcol]; + if (pixel[c] < val) pixel[c] = CLIP(val); + } + } + } + } + free (map); +} +#undef SCALE + +void CLASS tiff_get (unsigned base, + unsigned *tag, unsigned *type, unsigned *len, unsigned *save) +{ + *tag = get2(); + *type = get2(); + *len = get4(); + *save = ftell(ifp) + 4; + if (*len * ("11124811248488"[*type < 14 ? *type:0]-'0') > 4) + fseek (ifp, get4()+base, SEEK_SET); +} + +void CLASS parse_thumb_note (int base, unsigned toff, unsigned tlen) +{ + unsigned entries, tag, type, len, save; + + entries = get2(); + while (entries--) { + tiff_get (base, &tag, &type, &len, &save); + if (tag == toff) thumb_offset = get4()+base; + if (tag == tlen) thumb_length = get4(); + fseek (ifp, save, SEEK_SET); + } +} + +int CLASS parse_tiff_ifd (int base); + +void CLASS parse_makernote (int base, int uptag) +{ + static const uchar xlat[2][256] = { + { 0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d, + 0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d, + 0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f, + 0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f, + 0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1, + 0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17, + 0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89, + 0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f, + 0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b, + 0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb, + 0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3, + 0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f, + 0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35, + 0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43, + 0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5, + 0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7 }, + { 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c, + 0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34, + 0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad, + 0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05, + 0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee, + 0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d, + 0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b, + 0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b, + 0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc, + 0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33, + 0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8, + 0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6, + 0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c, + 0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49, + 0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb, + 0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f } }; + unsigned offset=0, entries, tag, type, len, save, c; + unsigned ver97=0, serial=0, i, wbi=0, wb[4]={0,0,0,0}; + uchar buf97[324], ci, cj, ck; + short sorder=order; + char buf[10]; +/* + The MakerNote might have its own TIFF header (possibly with + its own byte-order!), or it might just be a table. + */ + fread (buf, 1, 10, ifp); + if (!strncmp (buf,"KDK" ,3) || /* these aren't TIFF tables */ + !strncmp (buf,"VER" ,3) || + !strncmp (buf,"IIII",4) || + !strncmp (buf,"MMMM",4)) return; + if (!strncmp (buf,"KC" ,2) || /* Konica KD-400Z, KD-510Z */ + !strncmp (buf,"MLY" ,3)) { /* Minolta DiMAGE G series */ + order = 0x4d4d; + while ((i=ftell(ifp)) < data_offset && i < 16384) { + wb[0] = wb[2]; wb[2] = wb[1]; wb[1] = wb[3]; + wb[3] = get2(); + if (wb[1] == 256 && wb[3] == 256 && + wb[0] > 256 && wb[0] < 640 && wb[2] > 256 && wb[2] < 640) + FORC4 cam_mul[c] = wb[c]; + } + goto quit; + } + if (!strcmp (buf,"Nikon")) { + base = ftell(ifp); + order = get2(); + if (get2() != 42) goto quit; + offset = get4(); + fseek (ifp, offset-8, SEEK_CUR); + } else if (!strcmp (buf,"OLYMPUS")) { + base = ftell(ifp)-10; + fseek (ifp, -2, SEEK_CUR); + order = get2(); get2(); + } else if (!strncmp (buf,"FUJIFILM",8) || + !strncmp (buf,"SONY",4) || + !strcmp (buf,"Panasonic")) { + order = 0x4949; + fseek (ifp, 2, SEEK_CUR); + } else if (!strcmp (buf,"OLYMP") || + !strcmp (buf,"LEICA") || + !strcmp (buf,"Ricoh") || + !strcmp (buf,"EPSON")) + fseek (ifp, -2, SEEK_CUR); + else if (!strcmp (buf,"AOC") || + !strcmp (buf,"QVC")) + fseek (ifp, -4, SEEK_CUR); + else fseek (ifp, -10, SEEK_CUR); + + entries = get2(); + if (entries > 1000) return; + while (entries--) { + tiff_get (base, &tag, &type, &len, &save); + tag |= uptag << 16; + if (tag == 2 && strstr(make,"NIKON")) + iso_speed = (get2(),get2()); + if (tag == 4 && len > 26 && len < 35) { + iso_speed = 50 * pow (2, (get4(),get2())/32.0 - 4); + if ((i=(get2(),get2())) != 0x7fff) + aperture = pow (2, i/64.0); + if ((i=get2()) != 0xffff) + shutter = pow (2, (short) i/-32.0); + wbi = (get2(),get2()); + shot_order = (get2(),get2()); + } + if (tag == 8 && type == 4) + shot_order = get4(); + if (tag == 9 && !strcmp(make,"Canon")) + fread (artist, 64, 1, ifp); + if (tag == 0xc && len == 4) { + cam_mul[0] = getrat(); + cam_mul[2] = getrat(); + } + if (tag == 0x10 && type == 4) + unique_id = get4(); + if (tag == 0x11 && is_raw && !strncmp(make,"NIKON",5)) { + fseek (ifp, get4()+base, SEEK_SET); + parse_tiff_ifd (base); + } + if (tag == 0x14 && len == 2560 && type == 7) { + fseek (ifp, 1248, SEEK_CUR); + goto get2_256; + } + if (tag == 0x15 && type == 2 && is_raw) + fread (model, 64, 1, ifp); + if (strstr(make,"PENTAX")) { + if (tag == 0x1b) tag = 0x1018; + if (tag == 0x1c) tag = 0x1017; + } + if (tag == 0x1d) + while ((c = fgetc(ifp)) && c != EOF) + serial = serial*10 + (isdigit(c) ? c - '0' : c % 10); + if (tag == 0x81 && type == 4) { + data_offset = get4(); + fseek (ifp, data_offset + 41, SEEK_SET); + raw_height = get2() * 2; + raw_width = get2(); + filters = 0x61616161; + } + if (tag == 0x29 && type == 1) { + c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0; + fseek (ifp, 8 + c*32, SEEK_CUR); + FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4(); + } + if ((tag == 0x81 && type == 7) || + (tag == 0x100 && type == 7) || + (tag == 0x280 && type == 1)) { + thumb_offset = ftell(ifp); + thumb_length = len; + } + if (tag == 0x88 && type == 4 && (thumb_offset = get4())) + thumb_offset += base; + if (tag == 0x89 && type == 4) + thumb_length = get4(); + if (tag == 0x8c || tag == 0x96) + meta_offset = ftell(ifp); + if (tag == 0x97) { + for (i=0; i < 4; i++) + ver97 = (ver97 << 4) + fgetc(ifp)-'0'; + switch (ver97) { + case 0x100: + fseek (ifp, 68, SEEK_CUR); + FORC4 cam_mul[(c >> 1) | ((c & 1) << 1)] = get2(); + break; + case 0x102: + fseek (ifp, 6, SEEK_CUR); + goto get2_rggb; + case 0x103: + fseek (ifp, 16, SEEK_CUR); + FORC4 cam_mul[c] = get2(); + } + if (ver97 >> 8 == 2) { + if (ver97 != 0x205) fseek (ifp, 280, SEEK_CUR); + fread (buf97, 324, 1, ifp); + } + } + if (tag == 0xa4 && type == 3) { + fseek (ifp, wbi*48, SEEK_CUR); + FORC3 cam_mul[c] = get2(); + } + if (tag == 0xa7 && ver97 >> 8 == 2) { + ci = xlat[0][serial & 0xff]; + cj = xlat[1][fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp)]; + ck = 0x60; + for (i=0; i < 324; i++) + buf97[i] ^= (cj += ci * ck++); + FORC4 cam_mul[c ^ (c >> 1)] = + sget2 (buf97 + (ver97 == 0x205 ? 14:6) + c*2); + if (ver97 == 0x209) + FORC4 cam_mul[c ^ (c >> 1) ^ 1] = + sget2 (buf97 + 10 + c*2); + } + if (tag == 0x200 && len == 3) + shot_order = (get4(),get4()); + if (tag == 0x200 && len == 4) + black = (get2()+get2()+get2()+get2())/4; + if (tag == 0x201 && len == 4) + goto get2_rggb; + if (tag == 0x401 && len == 4) { + black = (get4()+get4()+get4()+get4())/4; + } + if (tag == 0xe01) { /* Nikon Capture Note */ + type = order; + order = 0x4949; + fseek (ifp, 22, SEEK_CUR); + for (offset=22; offset+22 < len; offset += 22+i) { + tag = get4(); + fseek (ifp, 14, SEEK_CUR); + i = get4()-4; + if (tag == 0x76a43207) flip = get2(); + else fseek (ifp, i, SEEK_CUR); + } + order = type; + } + if (tag == 0xe80 && len == 256 && type == 7) { + fseek (ifp, 48, SEEK_CUR); + cam_mul[0] = get2() * 508 * 1.078 / 0x10000; + cam_mul[2] = get2() * 382 * 1.173 / 0x10000; + } + if (tag == 0xf00 && type == 7) { + if (len == 614) + fseek (ifp, 176, SEEK_CUR); + else if (len == 734 || len == 1502) + fseek (ifp, 148, SEEK_CUR); + else goto next; + goto get2_256; + } + if ((tag == 0x1011 && len == 9) || tag == 0x20400200) + for (i=0; i < 3; i++) + FORC3 cmatrix[i][c] = ((short) get2()) / 256.0; + if ((tag == 0x1012 || tag == 0x20400600) && len == 4) + for (black = i=0; i < 4; i++) + black += get2() << 2; + if (tag == 0x1017 || tag == 0x20400100) + cam_mul[0] = get2() / 256.0; + if (tag == 0x1018 || tag == 0x20400100) + cam_mul[2] = get2() / 256.0; + if (tag == 0x2011 && len == 2) { +get2_256: + order = 0x4d4d; + cam_mul[0] = get2() / 256.0; + cam_mul[2] = get2() / 256.0; + } + if (tag == 0x2020) + parse_thumb_note (base, 257, 258); + if (tag == 0x2040) + parse_makernote (base, 0x2040); + if (tag == 0xb028) { + fseek (ifp, get4(), SEEK_SET); + parse_thumb_note (base, 136, 137); + } + if (tag == 0x4001 && type == 3) { + i = len == 582 ? 50 : len == 653 ? 68 : 126; + fseek (ifp, i, SEEK_CUR); +get2_rggb: + FORC4 cam_mul[c ^ (c >> 1)] = get2(); + fseek (ifp, 22, SEEK_CUR); + FORC4 sraw_mul[c ^ (c >> 1)] = get2(); + } +next: + fseek (ifp, save, SEEK_SET); + } +quit: + order = sorder; +} + +/* + Since the TIFF DateTime string has no timezone information, + assume that the camera's clock was set to Universal Time. + */ +void CLASS get_timestamp (int reversed) +{ + struct tm t; + char str[20]; + int i; + + str[19] = 0; + if (reversed) + for (i=19; i--; ) str[i] = fgetc(ifp); + else + fread (str, 19, 1, ifp); + memset (&t, 0, sizeof t); + if (sscanf (str, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon, + &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6) + return; + t.tm_year -= 1900; + t.tm_mon -= 1; + if (mktime(&t) > 0) + timestamp = mktime(&t); +} + +void CLASS parse_exif (int base) +{ + unsigned kodak, entries, tag, type, len, save, c; + double expo; + + kodak = !strncmp(make,"EASTMAN",7); + entries = get2(); + while (entries--) { + tiff_get (base, &tag, &type, &len, &save); + switch (tag) { + case 33434: shutter = getrat(); break; + case 33437: aperture = getrat(); break; + case 34855: iso_speed = get2(); break; + case 36867: + case 36868: get_timestamp(0); break; + case 37377: if ((expo = -getrat()) < 128) + shutter = pow (2, expo); break; + case 37378: aperture = pow (2, getrat()/2); break; + case 37386: focal_len = getrat(); break; + case 37500: parse_makernote (base, 0); break; + case 40962: if (kodak) raw_width = get4(); break; + case 40963: if (kodak) raw_height = get4(); break; + case 41730: + if (get4() == 0x20002) + for (exif_cfa=c=0; c < 8; c+=2) + exif_cfa |= fgetc(ifp) * 0x01010101 << c; + } + fseek (ifp, save, SEEK_SET); + } +} + +void CLASS romm_coeff (float romm_cam[3][3]) +{ + static const float rgb_romm[3][3] = /* ROMM == Kodak ProPhoto */ + { { 2.034193, -0.727420, -0.306766 }, + { -0.228811, 1.231729, -0.002922 }, + { -0.008565, -0.153273, 1.161839 } }; + int i, j, k; + + for (i=0; i < 3; i++) + for (j=0; j < 3; j++) + for (cmatrix[i][j] = k=0; k < 3; k++) + cmatrix[i][j] += rgb_romm[i][k] * romm_cam[k][j]; +} + +void CLASS parse_mos (int offset) +{ + char data[40]; + int skip, from, i, c, neut[4], planes=0, frot=0; + static const char *mod[] = + { "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22", + "Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65", + "Aptus 54S","Aptus 65S","Aptus 75S" }; + float romm_cam[3][3]; + + fseek (ifp, offset, SEEK_SET); + while (1) { + if (get4() != 0x504b5453) break; + get4(); + fread (data, 1, 40, ifp); + skip = get4(); + from = ftell(ifp); + if (!strcmp(data,"JPEG_preview_data")) { + thumb_offset = from; + thumb_length = skip; + } + if (!strcmp(data,"icc_camera_profile")) { + profile_offset = from; + profile_length = skip; + } + if (!strcmp(data,"ShootObj_back_type")) { + fscanf (ifp, "%d", &i); + if ((unsigned) i < sizeof mod / sizeof (*mod)) + strcpy (model, mod[i]); + } + if (!strcmp(data,"icc_camera_to_tone_matrix")) { + for (i=0; i < 9; i++) + romm_cam[0][i] = int_to_float(get4()); + romm_coeff (romm_cam); + } + if (!strcmp(data,"CaptProf_color_matrix")) { + for (i=0; i < 9; i++) + fscanf (ifp, "%f", &romm_cam[0][i]); + romm_coeff (romm_cam); + } + if (!strcmp(data,"CaptProf_number_of_planes")) + fscanf (ifp, "%d", &planes); + if (!strcmp(data,"CaptProf_raw_data_rotation")) + fscanf (ifp, "%d", &flip); + if (!strcmp(data,"CaptProf_mosaic_pattern")) + FORC4 { + fscanf (ifp, "%d", &i); + if (i == 1) frot = c ^ (c >> 1); + } + if (!strcmp(data,"ImgProf_rotation_angle")) { + fscanf (ifp, "%d", &i); + flip = i - flip; + } + if (!strcmp(data,"NeutObj_neutrals") && !cam_mul[0]) { + FORC4 fscanf (ifp, "%d", neut+c); + FORC3 cam_mul[c] = (float) neut[0] / neut[c+1]; + } + parse_mos (from); + fseek (ifp, skip+from, SEEK_SET); + } + if (planes) + filters = (planes == 1) * 0x01010101 * + (uchar) "\x94\x61\x16\x49"[(flip/90 + frot) & 3]; +} + +void CLASS linear_table (unsigned len) +{ + int i; + if (len > 0x1000) len = 0x1000; + read_shorts (curve, len); + for (i=len; i < 0x1000; i++) + curve[i] = curve[i-1]; + maximum = curve[0xfff]; +} + +void CLASS parse_kodak_ifd (int base) +{ + unsigned entries, tag, type, len, save; + int i, c, wbi=-2, wbtemp=6500; + float mul[3], num; + + entries = get2(); + if (entries > 1024) return; + while (entries--) { + tiff_get (base, &tag, &type, &len, &save); + if (tag == 1020) wbi = getint(type); + if (tag == 1021 && len == 72) { /* WB set in software */ + fseek (ifp, 40, SEEK_CUR); + FORC3 cam_mul[c] = 2048.0 / get2(); + wbi = -2; + } + if (tag == 2118) wbtemp = getint(type); + if (tag == 2130 + wbi) + FORC3 mul[c] = getreal(type); + if (tag == 2140 + wbi && wbi >= 0) + FORC3 { + for (num=i=0; i < 4; i++) + num += getreal(type) * pow (wbtemp/100.0, i); + cam_mul[c] = 2048 / (num * mul[c]); + } + if (tag == 2317) linear_table (len); + if (tag == 6020) iso_speed = getint(type); + fseek (ifp, save, SEEK_SET); + } +} + +void CLASS parse_minolta (int base); + +int CLASS parse_tiff_ifd (int base) +{ + unsigned entries, tag, type, len, plen=16, save; + int ifd, use_cm=0, cfa, i, j, c, ima_len=0; + char software[64], *cbuf, *cp; + uchar cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256]; + double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num; + double ab[]={ 1,1,1,1 }, asn[] = { 0,0,0,0 }, xyz[] = { 1,1,1 }; + unsigned sony_curve[] = { 0,0,0,0,0,4095 }; + unsigned *buf, sony_offset=0, sony_length=0, sony_key=0; + struct jhead jh; + FILE *sfp; + + if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0]) + return 1; + ifd = tiff_nifds++; + for (j=0; j < 4; j++) + for (i=0; i < 4; i++) + cc[j][i] = i == j; + entries = get2(); + if (entries > 512) return 1; + while (entries--) { + tiff_get (base, &tag, &type, &len, &save); + switch (tag) { + case 17: case 18: + if (type == 3 && len == 1) + cam_mul[(tag-17)*2] = get2() / 256.0; + break; + case 23: + if (type == 3) iso_speed = get2(); + break; + case 36: case 37: case 38: + cam_mul[tag-0x24] = get2(); + break; + case 39: + if (len < 50 || cam_mul[0]) break; + fseek (ifp, 12, SEEK_CUR); + FORC3 cam_mul[c] = get2(); + break; + case 46: + if (type != 7 || fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) break; + thumb_offset = ftell(ifp) - 2; + thumb_length = len; + break; + case 2: case 256: /* ImageWidth */ + tiff_ifd[ifd].width = getint(type); + break; + case 3: case 257: /* ImageHeight */ + tiff_ifd[ifd].height = getint(type); + break; + case 258: /* BitsPerSample */ + tiff_ifd[ifd].samples = len & 7; + tiff_ifd[ifd].bps = get2(); + break; + case 259: /* Compression */ + tiff_ifd[ifd].comp = get2(); + break; + case 262: /* PhotometricInterpretation */ + tiff_ifd[ifd].phint = get2(); + break; + case 270: /* ImageDescription */ + fread (desc, 512, 1, ifp); + break; + case 271: /* Make */ + fgets (make, 64, ifp); + break; + case 272: /* Model */ + fgets (model, 64, ifp); + break; + case 273: /* StripOffset */ + case 513: + tiff_ifd[ifd].offset = get4()+base; + if (!tiff_ifd[ifd].bps) { + fseek (ifp, tiff_ifd[ifd].offset, SEEK_SET); + if (ljpeg_start (&jh, 1)) { + tiff_ifd[ifd].comp = 6; + tiff_ifd[ifd].width = jh.wide << (jh.clrs == 2); + tiff_ifd[ifd].height = jh.high; + tiff_ifd[ifd].bps = jh.bits; + tiff_ifd[ifd].samples = jh.clrs; + } + } + break; + case 274: /* Orientation */ + tiff_ifd[ifd].flip = "50132467"[get2() & 7]-'0'; + break; + case 277: /* SamplesPerPixel */ + tiff_ifd[ifd].samples = getint(type) & 7; + break; + case 279: /* StripByteCounts */ + case 514: + tiff_ifd[ifd].bytes = get4(); + break; + case 305: /* Software */ + fgets (software, 64, ifp); + if (!strncmp(software,"Adobe",5) || + !strncmp(software,"dcraw",5) || + !strncmp(software,"Bibble",6) || + !strncmp(software,"Nikon Scan",10) || + !strcmp (software,"Digital Photo Professional")) + is_raw = 0; + break; + case 306: /* DateTime */ + get_timestamp(0); + break; + case 315: /* Artist */ + fread (artist, 64, 1, ifp); + break; + case 322: /* TileWidth */ + tile_width = getint(type); + break; + case 323: /* TileLength */ + tile_length = getint(type); + break; + case 324: /* TileOffsets */ + tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4(); + if (len == 4) { + load_raw = &CLASS sinar_4shot_load_raw; + is_raw = 5; + } + break; + case 330: /* SubIFDs */ + if (!strcmp(model,"DSLR-A100") && tiff_ifd[ifd].width == 3872) { + data_offset = get4()+base; + ifd++; break; + } + while (len--) { + i = ftell(ifp); + fseek (ifp, get4()+base, SEEK_SET); + if (parse_tiff_ifd (base)) break; + fseek (ifp, i+4, SEEK_SET); + } + break; + case 400: + strcpy (make, "Sarnoff"); + maximum = 0xfff; + break; + case 28688: + FORC4 sony_curve[c+1] = get2() >> 2 & 0xfff; + for (i=0; i < 5; i++) + for (j = sony_curve[i]+1; j <= sony_curve[i+1]; j++) + curve[j] = curve[j-1] + (1 << i); + break; + case 29184: sony_offset = get4(); break; + case 29185: sony_length = get4(); break; + case 29217: sony_key = get4(); break; + case 29264: + parse_minolta (ftell(ifp)); + raw_width = 0; + break; + case 29443: + FORC4 cam_mul[c ^ (c < 2)] = get2(); + break; + case 33405: /* Model2 */ + fgets (model2, 64, ifp); + break; + case 33422: /* CFAPattern */ + case 64777: /* Kodak P-series */ + if ((plen=len) > 16) plen = 16; + fread (cfa_pat, 1, plen, ifp); + for (colors=cfa=i=0; i < plen; i++) { + colors += !(cfa & (1 << cfa_pat[i])); + cfa |= 1 << cfa_pat[i]; + } + if (cfa == 070) memcpy (cfa_pc,"\003\004\005",3); /* CMY */ + if (cfa == 072) memcpy (cfa_pc,"\005\003\004\001",4); /* GMCY */ + goto guess_cfa_pc; + case 33424: + fseek (ifp, get4()+base, SEEK_SET); + parse_kodak_ifd (base); + break; + case 33434: /* ExposureTime */ + shutter = getrat(); + break; + case 33437: /* FNumber */ + aperture = getrat(); + break; + case 34306: /* Leaf white balance */ + FORC4 cam_mul[c ^ 1] = 4096.0 / get2(); + break; + case 34307: /* Leaf CatchLight color matrix */ + fread (software, 1, 7, ifp); + if (strncmp(software,"MATRIX",6)) break; + colors = 4; + for (raw_color = i=0; i < 3; i++) { + FORC4 fscanf (ifp, "%f", &rgb_cam[i][c^1]); + if (!use_camera_wb) continue; + num = 0; + FORC4 num += rgb_cam[i][c]; + FORC4 rgb_cam[i][c] /= num; + } + break; + case 34310: /* Leaf metadata */ + parse_mos (ftell(ifp)); + case 34303: + strcpy (make, "Leaf"); + break; + case 34665: /* EXIF tag */ + fseek (ifp, get4()+base, SEEK_SET); + parse_exif (base); + break; + case 34675: /* InterColorProfile */ + case 50831: /* AsShotICCProfile */ + profile_offset = ftell(ifp); + profile_length = len; + break; + case 37122: /* CompressedBitsPerPixel */ + kodak_cbpp = get4(); + break; + case 37386: /* FocalLength */ + focal_len = getrat(); + break; + case 37393: /* ImageNumber */ + shot_order = getint(type); + break; + case 37400: /* old Kodak KDC tag */ + for (raw_color = i=0; i < 3; i++) { + getrat(); + FORC3 rgb_cam[i][c] = getrat(); + } + break; + case 46275: /* Imacon tags */ + strcpy (make, "Imacon"); + data_offset = ftell(ifp); + ima_len = len; + break; + case 46279: + fseek (ifp, 78, SEEK_CUR); + raw_width = get4(); + raw_height = get4(); + left_margin = get4() & 7; + width = raw_width - left_margin - (get4() & 7); + top_margin = get4() & 7; + height = raw_height - top_margin - (get4() & 7); + if (raw_width == 7262) { + height = 5444; + width = 7244; + left_margin = 7; + } + fseek (ifp, 52, SEEK_CUR); + FORC3 cam_mul[c] = getreal(11); + fseek (ifp, 114, SEEK_CUR); + flip = (get2() >> 7) * 90; + if (width * height * 6 == ima_len) { + if (flip % 180 == 90) SWAP(width,height); + filters = flip = 0; + } + sprintf (model, "Ixpress %d-Mp", height*width/1000000); + load_raw = &CLASS imacon_full_load_raw; + if (filters) { + if (left_margin & 1) filters = 0x61616161; + load_raw = &CLASS unpacked_load_raw; + } + maximum = 0xffff; + break; + case 50454: /* Sinar tag */ + case 50455: + if (!(cbuf = (char *) malloc(len))) break; + fread (cbuf, 1, len, ifp); + for (cp = cbuf-1; cp && cp < cbuf+len; cp = strchr(cp,'\n')) + if (!strncmp (++cp,"Neutral ",8)) + sscanf (cp+8, "%f %f %f", cam_mul, cam_mul+1, cam_mul+2); + free (cbuf); + break; + case 50459: /* Hasselblad tag */ + i = order; + j = ftell(ifp); + c = tiff_nifds; + order = get2(); + fseek (ifp, j+(get2(),get4()), SEEK_SET); + parse_tiff_ifd (j); + maximum = 0xffff; + tiff_nifds = c; + order = i; + break; + case 50706: /* DNGVersion */ + FORC4 dng_version = (dng_version << 8) + fgetc(ifp); + break; + case 50710: /* CFAPlaneColor */ + if (len > 4) len = 4; + colors = len; + fread (cfa_pc, 1, colors, ifp); +guess_cfa_pc: + FORCC tab[cfa_pc[c]] = c; + cdesc[c] = 0; + for (i=16; i--; ) + filters = filters << 2 | tab[cfa_pat[i % plen]]; + break; + case 50711: /* CFALayout */ + if (get2() == 2) { + fuji_width = 1; + filters = 0x49494949; + } + break; + case 291: + case 50712: /* LinearizationTable */ + linear_table (len); + break; + case 50714: /* BlackLevel */ + case 50715: /* BlackLevelDeltaH */ + case 50716: /* BlackLevelDeltaV */ + for (dblack=i=0; i < len; i++) + dblack += getreal(type); + black += dblack/len + 0.5; + break; + case 50717: /* WhiteLevel */ + maximum = getint(type); + break; + case 50718: /* DefaultScale */ + pixel_aspect = getrat(); + pixel_aspect /= getrat(); + break; + case 50721: /* ColorMatrix1 */ + case 50722: /* ColorMatrix2 */ + FORCC for (j=0; j < 3; j++) + cm[c][j] = getrat(); + use_cm = 1; + break; + case 50723: /* CameraCalibration1 */ + case 50724: /* CameraCalibration2 */ + for (i=0; i < colors; i++) + FORCC cc[i][c] = getrat(); + case 50727: /* AnalogBalance */ + FORCC ab[c] = getrat(); + break; + case 50728: /* AsShotNeutral */ + FORCC asn[c] = getreal(type); + break; + case 50729: /* AsShotWhiteXY */ + xyz[0] = getrat(); + xyz[1] = getrat(); + xyz[2] = 1 - xyz[0] - xyz[1]; + FORC3 xyz[c] /= d65_white[c]; + break; + case 50740: /* DNGPrivateData */ + if (dng_version) break; + parse_minolta (j = get4()+base); + fseek (ifp, j, SEEK_SET); + parse_tiff_ifd (base); + break; + case 50752: + read_shorts (cr2_slice, 3); + break; + case 50829: /* ActiveArea */ + top_margin = getint(type); + left_margin = getint(type); + height = getint(type) - top_margin; + width = getint(type) - left_margin; + break; + case 64772: /* Kodak P-series */ + fseek (ifp, 16, SEEK_CUR); + data_offset = get4(); + fseek (ifp, 28, SEEK_CUR); + data_offset += get4(); + load_raw = &CLASS packed_12_load_raw; + } + fseek (ifp, save, SEEK_SET); + } + if (sony_length && (buf = (unsigned *) malloc(sony_length))) { + fseek (ifp, sony_offset, SEEK_SET); + fread (buf, sony_length, 1, ifp); + sony_decrypt (buf, sony_length/4, 1, sony_key); + sfp = ifp; + if ((ifp = tmpfile())) { + fwrite (buf, sony_length, 1, ifp); + fseek (ifp, 0, SEEK_SET); + parse_tiff_ifd (-sony_offset); + fclose (ifp); + } + ifp = sfp; + free (buf); + } + for (i=0; i < colors; i++) + FORCC cc[i][c] *= ab[i]; + if (use_cm) { + FORCC for (i=0; i < 3; i++) + for (cam_xyz[c][i]=j=0; j < colors; j++) + cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i]; + cam_xyz_coeff (cam_xyz); + } + if (asn[0]) { + cam_mul[3] = 0; + FORCC cam_mul[c] = 1 / asn[c]; + } + if (!use_cm) + FORCC pre_mul[c] /= cc[c][c]; + return 0; +} + +void CLASS parse_tiff (int base) +{ + int doff, max_samp=0, raw=-1, thm=-1, i; + struct jhead jh; + + fseek (ifp, base, SEEK_SET); + order = get2(); + if (order != 0x4949 && order != 0x4d4d) return; + get2(); + memset (tiff_ifd, 0, sizeof tiff_ifd); + tiff_nifds = 0; + while ((doff = get4())) { + fseek (ifp, doff+base, SEEK_SET); + if (parse_tiff_ifd (base)) break; + } + thumb_misc = 16; + if (thumb_offset) { + fseek (ifp, thumb_offset, SEEK_SET); + if (ljpeg_start (&jh, 1)) { + thumb_misc = jh.bits; + thumb_width = jh.wide; + thumb_height = jh.high; + } + } + for (i=0; i < tiff_nifds; i++) { + if (max_samp < tiff_ifd[i].samples) + max_samp = tiff_ifd[i].samples; + if (max_samp > 3) max_samp = 3; + if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) && + tiff_ifd[i].width*tiff_ifd[i].height > raw_width*raw_height) { + raw_width = tiff_ifd[i].width; + raw_height = tiff_ifd[i].height; + tiff_bps = tiff_ifd[i].bps; + tiff_compress = tiff_ifd[i].comp; + data_offset = tiff_ifd[i].offset; + tiff_flip = tiff_ifd[i].flip; + tiff_samples = tiff_ifd[i].samples; + raw = i; + } + } + fuji_width *= (raw_width+1)/2; + if (tiff_ifd[0].flip) tiff_flip = tiff_ifd[0].flip; + if (raw >= 0 && !load_raw) + switch (tiff_compress) { + case 0: case 1: + switch (tiff_bps) { + case 8: load_raw = &CLASS eight_bit_load_raw; break; + case 12: load_raw = &CLASS packed_12_load_raw; + if (!strncmp(make,"NIKON",5)) + load_raw = &CLASS nikon_load_raw; + if (strncmp(make,"PENTAX",6)) break; + case 14: + case 16: load_raw = &CLASS unpacked_load_raw; break; + } + if (tiff_ifd[raw].bytes * 5 == raw_width * raw_height * 8) + load_raw = &CLASS olympus_e300_load_raw; + if (tiff_bps == 12 && tiff_ifd[raw].phint == 2) + load_raw = &CLASS olympus_cseries_load_raw; + break; + case 6: case 7: case 99: + load_raw = &CLASS lossless_jpeg_load_raw; break; + case 262: + load_raw = &CLASS kodak_262_load_raw; break; + case 32767: + load_raw = &CLASS sony_arw2_load_raw; break; + case 32769: + load_raw = &CLASS nikon_load_raw; break; + case 32773: + load_raw = &CLASS packed_12_load_raw; break; + case 34713: + load_raw = &CLASS nikon_compressed_load_raw; break; + case 65535: + load_raw = &CLASS pentax_k10_load_raw; break; + case 65000: + switch (tiff_ifd[raw].phint) { + case 2: load_raw = &CLASS kodak_rgb_load_raw; filters = 0; break; + case 6: load_raw = &CLASS kodak_ycbcr_load_raw; filters = 0; break; + case 32803: load_raw = &CLASS kodak_65000_load_raw; + } + case 32867: break; + default: is_raw = 0; + } + if (!dng_version && tiff_samples == 3) + if (tiff_ifd[raw].bytes && tiff_bps != 14 && tiff_bps != 2048) + is_raw = 0; + if (!dng_version && tiff_bps == 8 && tiff_compress == 1 && + tiff_ifd[raw].phint == 1) is_raw = 0; + for (i=0; i < tiff_nifds; i++) + if (i != raw && tiff_ifd[i].samples == max_samp && + tiff_ifd[i].width * tiff_ifd[i].height / SQR(tiff_ifd[i].bps+1) > + thumb_width * thumb_height / SQR(thumb_misc+1)) { + thumb_width = tiff_ifd[i].width; + thumb_height = tiff_ifd[i].height; + thumb_offset = tiff_ifd[i].offset; + thumb_length = tiff_ifd[i].bytes; + thumb_misc = tiff_ifd[i].bps; + thm = i; + } + if (thm >= 0) { + thumb_misc |= tiff_ifd[thm].samples << 5; + switch (tiff_ifd[thm].comp) { + case 0: + write_thumb = &CLASS layer_thumb; + break; + case 1: + if (tiff_ifd[thm].bps > 8) + thumb_load_raw = &CLASS kodak_thumb_load_raw; + else + write_thumb = &CLASS ppm_thumb; + break; + case 65000: + thumb_load_raw = tiff_ifd[thm].phint == 6 ? + &CLASS kodak_ycbcr_load_raw : &CLASS kodak_rgb_load_raw; + } + } +} + +void CLASS parse_minolta (int base) +{ + int save, tag, len, offset, high=0, wide=0, i, c; + short sorder=order; + + fseek (ifp, base, SEEK_SET); + if (fgetc(ifp) || fgetc(ifp)-'M' || fgetc(ifp)-'R') return; + order = fgetc(ifp) * 0x101; + offset = base + get4() + 8; + while ((save=ftell(ifp)) < offset) { + for (tag=i=0; i < 4; i++) + tag = tag << 8 | fgetc(ifp); + len = get4(); + switch (tag) { + case 0x505244: /* PRD */ + fseek (ifp, 8, SEEK_CUR); + high = get2(); + wide = get2(); + break; + case 0x574247: /* WBG */ + get4(); + i = strstr(model,"A200") ? 3:0; + FORC4 cam_mul[c ^ (c >> 1) ^ i] = get2(); + break; + case 0x545457: /* TTW */ + parse_tiff (ftell(ifp)); + data_offset = offset; + } + fseek (ifp, save+len+8, SEEK_SET); + } + raw_height = high; + raw_width = wide; + order = sorder; +} + +/* + Many cameras have a "debug mode" that writes JPEG and raw + at the same time. The raw file has no header, so try to + to open the matching JPEG file and read its metadata. + */ +void CLASS parse_external_jpeg() +{ + char *file, *ext, *jname, *jfile, *jext; + FILE *save=ifp; + + ext = strrchr (ifname, '.'); + file = strrchr (ifname, '/'); + if (!file) file = strrchr (ifname, '\\'); + if (!file) file = ifname-1; + file++; + if (!ext || strlen(ext) != 4 || ext-file != 8) return; + jname = (char *) malloc (strlen(ifname) + 1); + merror (jname, "parse_external()"); + strcpy (jname, ifname); + jfile = file - ifname + jname; + jext = ext - ifname + jname; + if (strcasecmp (ext, ".jpg")) { + strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg"); + memcpy (jfile, file+4, 4); + memcpy (jfile+4, file, 4); + } else + while (isdigit(*--jext)) { + if (*jext != '9') { + (*jext)++; + break; + } + *jext = '0'; + } + if (strcmp (jname, ifname)) { + if ((ifp = fopen (jname, "rb"))) { + if (verbose) + fprintf (stderr,_("Reading metadata from %s ...\n"), jname); + parse_tiff (12); + thumb_offset = 0; + is_raw = 1; + fclose (ifp); + } + } + if (!timestamp) + fprintf (stderr,_("Failed to read metadata from %s\n"), jname); + free (jname); + ifp = save; +} + +/* + CIFF block 0x1030 contains an 8x8 white sample. + Load this into white[][] for use in scale_colors(). + */ +void CLASS ciff_block_1030() +{ + static const ushort key[] = { 0x410, 0x45f3 }; + int i, bpp, row, col, vbits=0; + unsigned long bitbuf=0; + + if ((get2(),get4()) != 0x80008 || !get4()) return; + bpp = get2(); + if (bpp != 10 && bpp != 12) return; + for (i=row=0; row < 8; row++) + for (col=0; col < 8; col++) { + if (vbits < bpp) { + bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]); + vbits += 16; + } + white[row][col] = + bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp); + vbits -= bpp; + } +} + +/* + Parse a CIFF file, better known as Canon CRW format. + */ +void CLASS parse_ciff (int offset, int length) +{ + int tboff, nrecs, c, type, len, save, wbi=-1; + ushort key[] = { 0x410, 0x45f3 }; + + fseek (ifp, offset+length-4, SEEK_SET); + tboff = get4() + offset; + fseek (ifp, tboff, SEEK_SET); + nrecs = get2(); + if (nrecs > 100) return; + while (nrecs--) { + type = get2(); + len = get4(); + save = ftell(ifp) + 4; + fseek (ifp, offset+get4(), SEEK_SET); + if ((((type >> 8) + 8) | 8) == 0x38) + parse_ciff (ftell(ifp), len); /* Parse a sub-table */ + + if (type == 0x0810) + fread (artist, 64, 1, ifp); + if (type == 0x080a) { + fread (make, 64, 1, ifp); + fseek (ifp, strlen(make) - 63, SEEK_CUR); + fread (model, 64, 1, ifp); + } + if (type == 0x1810) { + fseek (ifp, 12, SEEK_CUR); + flip = get4(); + } + if (type == 0x1835) /* Get the decoder table */ + tiff_compress = get4(); + if (type == 0x2007) { + thumb_offset = ftell(ifp); + thumb_length = len; + } + if (type == 0x1818) { + shutter = pow (2, -int_to_float((get4(),get4()))); + aperture = pow (2, int_to_float(get4())/2); + } + if (type == 0x102a) { + iso_speed = pow (2, (get4(),get2())/32.0 - 4) * 50; + aperture = pow (2, (get2(),(short)get2())/64.0); + shutter = pow (2,-((short)get2())/32.0); + wbi = (get2(),get2()); + if (wbi > 17) wbi = 0; + fseek (ifp, 32, SEEK_CUR); + if (shutter > 1e6) shutter = get2()/10.0; + } + if (type == 0x102c) { + if (get2() > 512) { /* Pro90, G1 */ + fseek (ifp, 118, SEEK_CUR); + FORC4 cam_mul[c ^ 2] = get2(); + } else { /* G2, S30, S40 */ + fseek (ifp, 98, SEEK_CUR); + FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2(); + } + } + if (type == 0x0032) { + if (len == 768) { /* EOS D30 */ + fseek (ifp, 72, SEEK_CUR); + FORC4 cam_mul[c ^ (c >> 1)] = 1024.0 / get2(); + if (!wbi) cam_mul[0] = -1; /* use my auto white balance */ + } else if (!cam_mul[0]) { + if (get2() == key[0]) /* Pro1, G6, S60, S70 */ + c = (strstr(model,"Pro1") ? + "012346000000000000":"01345:000000006008")[wbi]-'0'+ 2; + else { /* G3, G5, S45, S50 */ + c = "023457000000006000"[wbi]-'0'; + key[0] = key[1] = 0; + } + fseek (ifp, 78 + c*8, SEEK_CUR); + FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2() ^ key[c & 1]; + if (!wbi) cam_mul[0] = -1; + } + } + if (type == 0x10a9) { /* D60, 10D, 300D, and clones */ + if (len > 66) wbi = "0134567028"[wbi]-'0'; + fseek (ifp, 2 + wbi*8, SEEK_CUR); + FORC4 cam_mul[c ^ (c >> 1)] = get2(); + } + if (type == 0x1030 && (0x18040 >> wbi & 1)) + ciff_block_1030(); /* all that don't have 0x10a9 */ + if (type == 0x1031) { + raw_width = (get2(),get2()); + raw_height = get2(); + } + if (type == 0x5029) { + focal_len = len >> 16; + if ((len & 0xffff) == 2) focal_len /= 32; + } + if (type == 0x5813) flash_used = int_to_float(len); + if (type == 0x5814) canon_ev = int_to_float(len); + if (type == 0x5817) shot_order = len; + if (type == 0x5834) unique_id = len; + if (type == 0x580e) timestamp = len; + if (type == 0x180e) timestamp = get4(); +#ifdef LOCALTIME + if ((type | 0x4000) == 0x580e) + timestamp = mktime (gmtime (×tamp)); +#endif + fseek (ifp, save, SEEK_SET); + } +} + +void CLASS parse_rollei() +{ + char line[128], *val; + struct tm t; + + fseek (ifp, 0, SEEK_SET); + memset (&t, 0, sizeof t); + do { + fgets (line, 128, ifp); + if ((val = strchr(line,'='))) + *val++ = 0; + else + val = line + strlen(line); + if (!strcmp(line,"DAT")) + sscanf (val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year); + if (!strcmp(line,"TIM")) + sscanf (val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec); + if (!strcmp(line,"HDR")) + thumb_offset = atoi(val); + if (!strcmp(line,"X ")) + raw_width = atoi(val); + if (!strcmp(line,"Y ")) + raw_height = atoi(val); + if (!strcmp(line,"TX ")) + thumb_width = atoi(val); + if (!strcmp(line,"TY ")) + thumb_height = atoi(val); + } while (strncmp(line,"EOHD",4)); + data_offset = thumb_offset + thumb_width * thumb_height * 2; + t.tm_year -= 1900; + t.tm_mon -= 1; + if (mktime(&t) > 0) + timestamp = mktime(&t); + strcpy (make, "Rollei"); + strcpy (model,"d530flex"); + write_thumb = &CLASS rollei_thumb; +} + +void CLASS parse_sinar_ia() +{ + int entries, off; + char str[8], *cp; + + order = 0x4949; + fseek (ifp, 4, SEEK_SET); + entries = get4(); + fseek (ifp, get4(), SEEK_SET); + while (entries--) { + off = get4(); get4(); + fread (str, 8, 1, ifp); + if (!strcmp(str,"META")) meta_offset = off; + if (!strcmp(str,"THUMB")) thumb_offset = off; + if (!strcmp(str,"RAW0")) data_offset = off; + } + fseek (ifp, meta_offset+20, SEEK_SET); + fread (make, 64, 1, ifp); + make[63] = 0; + if ((cp = strchr(make,' '))) { + strcpy (model, cp+1); + *cp = 0; + } + raw_width = get2(); + raw_height = get2(); + load_raw = &CLASS unpacked_load_raw; + thumb_width = (get4(),get2()); + thumb_height = get2(); + write_thumb = &CLASS ppm_thumb; + maximum = 0x3fff; +} + +void CLASS parse_phase_one (int base) +{ + unsigned entries, tag, type, len, data, save, i, c; + float romm_cam[3][3]; + char *cp; + + memset (&ph1, 0, sizeof ph1); + fseek (ifp, base, SEEK_SET); + order = get4() & 0xffff; + if (get4() >> 8 != 0x526177) return; /* "Raw" */ + fseek (ifp, base+get4(), SEEK_SET); + entries = get4(); + get4(); + while (entries--) { + tag = get4(); + type = get4(); + len = get4(); + data = get4(); + save = ftell(ifp); + fseek (ifp, base+data, SEEK_SET); + switch (tag) { + case 0x100: flip = "0653"[data & 3]-'0'; break; + case 0x106: + for (i=0; i < 9; i++) + romm_cam[0][i] = getreal(11); + romm_coeff (romm_cam); + break; + case 0x107: + FORC3 cam_mul[c] = getreal(11); + break; + case 0x108: raw_width = data; break; + case 0x109: raw_height = data; break; + case 0x10a: left_margin = data; break; + case 0x10b: top_margin = data; break; + case 0x10c: width = data; break; + case 0x10d: height = data; break; + case 0x10e: ph1.format = data; break; + case 0x10f: data_offset = data+base; break; + case 0x110: meta_offset = data+base; + meta_length = len; break; + case 0x112: ph1.key_off = save - 4; break; + case 0x210: ph1.tag_210 = int_to_float(data); break; + case 0x21a: ph1.tag_21a = data; break; + case 0x21c: strip_offset = data+base; break; + case 0x21d: ph1.black = data; break; + case 0x222: ph1.split_col = data - left_margin; break; + case 0x223: ph1.black_off = data+base; break; + case 0x301: + model[63] = 0; + fread (model, 1, 63, ifp); + if ((cp = strstr(model," camera"))) *cp = 0; + } + fseek (ifp, save, SEEK_SET); + } + load_raw = ph1.format < 3 ? + &CLASS phase_one_load_raw : &CLASS phase_one_load_raw_c; + maximum = 0xffff; + strcpy (make, "Phase One"); + if (model[0]) return; + switch (raw_height) { + case 2060: strcpy (model,"LightPhase"); break; + case 2682: strcpy (model,"H 10"); break; + case 4128: strcpy (model,"H 20"); break; + case 5488: strcpy (model,"H 25"); break; + } +} + +void CLASS parse_fuji (int offset) +{ + unsigned entries, tag, len, save, c; + + fseek (ifp, offset, SEEK_SET); + entries = get4(); + if (entries > 255) return; + while (entries--) { + tag = get2(); + len = get2(); + save = ftell(ifp); + if (tag == 0x100) { + raw_height = get2(); + raw_width = get2(); + } else if (tag == 0x121) { + height = get2(); + if ((width = get2()) == 4284) width += 3; + } else if (tag == 0x130) + fuji_layout = fgetc(ifp) >> 7; + if (tag == 0x2ff0) + FORC4 cam_mul[c ^ 1] = get2(); + fseek (ifp, save+len, SEEK_SET); + } + height <<= fuji_layout; + width >>= fuji_layout; +} + +int CLASS parse_jpeg (int offset) +{ + int len, save, hlen, mark; + + fseek (ifp, offset, SEEK_SET); + if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) return 0; + + while (fgetc(ifp) == 0xff && (mark = fgetc(ifp)) != 0xda) { + order = 0x4d4d; + len = get2() - 2; + save = ftell(ifp); + if (mark == 0xc0 || mark == 0xc3) { + fgetc(ifp); + raw_height = get2(); + raw_width = get2(); + } + order = get2(); + hlen = get4(); + if (get4() == 0x48454150) /* "HEAP" */ + parse_ciff (save+hlen, len-hlen); + parse_tiff (save+6); + fseek (ifp, save+len, SEEK_SET); + } + return 1; +} + +void CLASS parse_riff() +{ + unsigned i, size, end; + char tag[4], date[64], month[64]; + static const char mon[12][4] = + { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" }; + struct tm t; + + order = 0x4949; + fread (tag, 4, 1, ifp); + size = get4(); + if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) { + end = ftell(ifp) + size; + get4(); + while (ftell(ifp) < end) + parse_riff(); + } else if (!memcmp(tag,"IDIT",4) && size < 64) { + fread (date, 64, 1, ifp); + date[size] = 0; + memset (&t, 0, sizeof t); + if (sscanf (date, "%*s %s %d %d:%d:%d %d", month, &t.tm_mday, + &t.tm_hour, &t.tm_min, &t.tm_sec, &t.tm_year) == 6) { + for (i=0; i < 12 && strcmp(mon[i],month); i++); + t.tm_mon = i; + t.tm_year -= 1900; + if (mktime(&t) > 0) + timestamp = mktime(&t); + } + } else + fseek (ifp, size, SEEK_CUR); +} + +void CLASS parse_smal (int offset, int fsize) +{ + int ver; + + fseek (ifp, offset+2, SEEK_SET); + order = 0x4949; + ver = fgetc(ifp); + if (ver == 6) + fseek (ifp, 5, SEEK_CUR); + if (get4() != fsize) return; + if (ver > 6) data_offset = get4(); + raw_height = height = get2(); + raw_width = width = get2(); + strcpy (make, "SMaL"); + sprintf (model, "v%d %dx%d", ver, width, height); + if (ver == 6) load_raw = &CLASS smal_v6_load_raw; + if (ver == 9) load_raw = &CLASS smal_v9_load_raw; +} + +void CLASS parse_cine() +{ + unsigned off_head, off_setup, off_image, i; + + order = 0x4949; + fseek (ifp, 4, SEEK_SET); + is_raw = get2() == 2; + fseek (ifp, 14, SEEK_CUR); + is_raw *= get4(); + off_head = get4(); + off_setup = get4(); + off_image = get4(); + timestamp = get4(); + if ((i = get4())) timestamp = i; + fseek (ifp, off_head+4, SEEK_SET); + raw_width = get4(); + raw_height = get4(); + switch (get2(),get2()) { + case 8: load_raw = &CLASS eight_bit_load_raw; break; + case 16: load_raw = &CLASS unpacked_load_raw; + } + fseek (ifp, off_setup+792, SEEK_SET); + strcpy (make, "CINE"); + sprintf (model, "%d", get4()); + fseek (ifp, 12, SEEK_CUR); + switch ((i=get4()) & 0xffffff) { + case 3: filters = 0x94949494; break; + case 4: filters = 0x49494949; break; + default: is_raw = 0; + } + fseek (ifp, 72, SEEK_CUR); + switch ((get4()+3600) % 360) { + case 270: flip = 4; break; + case 180: flip = 1; break; + case 90: flip = 7; break; + case 0: flip = 2; + } + cam_mul[0] = getreal(11); + cam_mul[2] = getreal(11); + maximum = ~(-1 << get4()); + fseek (ifp, 668, SEEK_CUR); + shutter = get4()/1000000000.0; + fseek (ifp, off_image, SEEK_SET); + if (shot_select < is_raw) + fseek (ifp, shot_select*8, SEEK_CUR); + data_offset = (INT64) get4() + 8; + data_offset += (INT64) get4() << 32; +} + +char * CLASS foveon_gets (int offset, char *str, int len) +{ + int i; + fseek (ifp, offset, SEEK_SET); + for (i=0; i < len-1; i++) + if ((str[i] = get2()) == 0) break; + str[i] = 0; + return str; +} + +void CLASS parse_foveon() +{ + int entries, img=0, off, len, tag, save, i, wide, high, pent, poff[256][2]; + char name[64], value[64]; + + order = 0x4949; /* Little-endian */ + fseek (ifp, 36, SEEK_SET); + flip = get4(); + fseek (ifp, -4, SEEK_END); + fseek (ifp, get4(), SEEK_SET); + if (get4() != 0x64434553) return; /* SECd */ + entries = (get4(),get4()); + while (entries--) { + off = get4(); + len = get4(); + tag = get4(); + save = ftell(ifp); + fseek (ifp, off, SEEK_SET); + if (get4() != (0x20434553 | (tag << 24))) return; + switch (tag) { + case 0x47414d49: /* IMAG */ + case 0x32414d49: /* IMA2 */ + fseek (ifp, 12, SEEK_CUR); + wide = get4(); + high = get4(); + if (wide > raw_width && high > raw_height) { + raw_width = wide; + raw_height = high; + data_offset = off+24; + } + fseek (ifp, off+28, SEEK_SET); + if (fgetc(ifp) == 0xff && fgetc(ifp) == 0xd8) { + thumb_offset = off+28; + thumb_length = len-28; + write_thumb = &CLASS jpeg_thumb; + } + if (++img == 2 && !thumb_length) { + thumb_offset = off+24; + thumb_width = wide; + thumb_height = high; + write_thumb = &CLASS foveon_thumb; + } + break; + case 0x464d4143: /* CAMF */ + meta_offset = off+24; + meta_length = len-28; + if (meta_length > 0x20000) + meta_length = 0x20000; + break; + case 0x504f5250: /* PROP */ + pent = (get4(),get4()); + fseek (ifp, 12, SEEK_CUR); + off += pent*8 + 24; + if ((unsigned) pent > 256) pent=256; + for (i=0; i < pent*2; i++) + poff[0][i] = off + get4()*2; + for (i=0; i < pent; i++) { + foveon_gets (poff[i][0], name, 64); + foveon_gets (poff[i][1], value, 64); + if (!strcmp (name, "ISO")) + iso_speed = atoi(value); + if (!strcmp (name, "CAMMANUF")) + strcpy (make, value); + if (!strcmp (name, "CAMMODEL")) + strcpy (model, value); + if (!strcmp (name, "WB_DESC")) + strcpy (model2, value); + if (!strcmp (name, "TIME")) + timestamp = atoi(value); + if (!strcmp (name, "EXPTIME")) + shutter = atoi(value) / 1000000.0; + if (!strcmp (name, "APERTURE")) + aperture = atof(value); + if (!strcmp (name, "FLENGTH")) + focal_len = atof(value); + } +#ifdef LOCALTIME + timestamp = mktime (gmtime (×tamp)); +#endif + } + fseek (ifp, save, SEEK_SET); + } + is_foveon = 1; +} + +/* + Thanks to Adobe for providing these excellent CAM -> XYZ matrices! + */ +void CLASS adobe_coeff (char *make, char *model) +{ + static const struct { + const char *prefix; + short black, trans[12]; + } table[] = { + { "Apple QuickTake", 0, /* DJC */ + { 17576,-3191,-3318,5210,6733,-1942,9031,1280,-124 } }, + { "Canon EOS D2000", 0, + { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } }, + { "Canon EOS D6000", 0, + { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } }, + { "Canon EOS D30", 0, + { 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } }, + { "Canon EOS D60", 0, + { 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } }, + { "Canon EOS 5D", 0, + { 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } }, + { "Canon EOS 20Da", 0, + { 14155,-5065,-1382,-6550,14633,2039,-1623,1824,6561 } }, + { "Canon EOS 20D", 0, + { 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } }, + { "Canon EOS 30D", 0, + { 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 } }, + { "Canon EOS 40D", 0, + { 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } }, + { "Canon EOS 350D", 0, + { 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } }, + { "Canon EOS 400D", 0, + { 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } }, + { "Canon EOS-1Ds Mark II", 0, + { 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } }, + { "Canon EOS-1D Mark II N", 0, + { 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } }, + { "Canon EOS-1D Mark III", 0, + { 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } }, + { "Canon EOS-1D Mark II", 0, + { 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } }, + { "Canon EOS-1DS", 0, + { 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 } }, + { "Canon EOS-1D", 0, + { 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } }, + { "Canon EOS", 0, + { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, + { "Canon PowerShot A50", 0, + { -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } }, + { "Canon PowerShot A5", 0, + { -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } }, + { "Canon PowerShot G1", 0, + { -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557 } }, + { "Canon PowerShot G2", 0, + { 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 } }, + { "Canon PowerShot G3", 0, + { 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } }, + { "Canon PowerShot G5", 0, + { 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } }, + { "Canon PowerShot G6", 0, + { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } }, + { "Canon PowerShot G9", 0, + { 10823,-3042,-1842,-4562,13656,900,-1311,1670,3556 } }, + { "Canon PowerShot Pro1", 0, + { 10062,-3522,-999,-7643,15117,2730,-765,817,7323 } }, + { "Canon PowerShot Pro70", 34, + { -4155,9818,1529,3939,-25,4522,-5521,9870,6610,-2238,10873,1342 } }, + { "Canon PowerShot Pro90", 0, + { -4963,9896,2235,4642,-987,4294,-5162,10011,5859,-1770,11230,577 } }, + { "Canon PowerShot S30", 0, + { 10566,-3652,-1129,-6552,14662,2006,-2197,2581,7670 } }, + { "Canon PowerShot S40", 0, + { 8510,-2487,-940,-6869,14231,2900,-2318,2829,9013 } }, + { "Canon PowerShot S45", 0, + { 8163,-2333,-955,-6682,14174,2751,-2077,2597,8041 } }, + { "Canon PowerShot S50", 0, + { 8882,-2571,-863,-6348,14234,2288,-1516,2172,6569 } }, + { "Canon PowerShot S60", 0, + { 8795,-2482,-797,-7804,15403,2573,-1422,1996,7082 } }, + { "Canon PowerShot S70", 0, + { 9976,-3810,-832,-7115,14463,2906,-901,989,7889 } }, + { "Canon PowerShot A610", 0, /* DJC */ + { 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 } }, + { "Canon PowerShot A620", 0, /* DJC */ + { 15265,-6193,-1558,-4125,12116,2010,-888,1639,5220 } }, + { "Canon PowerShot A640", 0, /* DJC */ + { 13124,-5329,-1390,-3602,11658,1944,-1612,2863,4885 } }, + { "Canon PowerShot S3 IS", 0, /* DJC */ + { 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } }, + { "CINE 650", 0, + { 3390,480,-500,-800,3610,340,-550,2336,1192 } }, + { "CINE 660", 0, + { 3390,480,-500,-800,3610,340,-550,2336,1192 } }, + { "CINE", 0, + { 20183,-4295,-423,-3940,15330,3985,-280,4870,9800 } }, + { "Contax N Digital", 0, + { 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } }, + { "EPSON R-D1", 0, + { 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } }, + { "FUJIFILM FinePix E550", 0, + { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } }, + { "FUJIFILM FinePix E900", 0, + { 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 } }, + { "FUJIFILM FinePix F8", 0, + { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } }, + { "FUJIFILM FinePix F7", 0, + { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } }, + { "FUJIFILM FinePix S20Pro", 0, + { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } }, + { "FUJIFILM FinePix S2Pro", 128, + { 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } }, + { "FUJIFILM FinePix S3Pro", 0, + { 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } }, + { "FUJIFILM FinePix S5Pro", 0, + { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } }, + { "FUJIFILM FinePix S5000", 0, + { 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } }, + { "FUJIFILM FinePix S5100", 0, + { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } }, + { "FUJIFILM FinePix S5500", 0, + { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } }, + { "FUJIFILM FinePix S5200", 0, + { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } }, + { "FUJIFILM FinePix S5600", 0, + { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } }, + { "FUJIFILM FinePix S6", 0, + { 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 } }, + { "FUJIFILM FinePix S7000", 0, + { 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } }, + { "FUJIFILM FinePix S9000", 0, + { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } }, + { "FUJIFILM FinePix S9500", 0, + { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } }, + { "FUJIFILM FinePix S9100", 0, + { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } }, + { "FUJIFILM FinePix S9600", 0, + { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } }, + { "Imacon Ixpress", 0, /* DJC */ + { 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 } }, + { "KODAK NC2000", 0, /* DJC */ + { 16475,-6903,-1218,-851,10375,477,2505,-7,1020 } }, + { "Kodak DCS315C", 8, + { 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } }, + { "Kodak DCS330C", 8, + { 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } }, + { "KODAK DCS420", 0, + { 10868,-1852,-644,-1537,11083,484,2343,628,2216 } }, + { "KODAK DCS460", 0, + { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } }, + { "KODAK EOSDCS1", 0, + { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } }, + { "KODAK EOSDCS3B", 0, + { 9898,-2700,-940,-2478,12219,206,1985,634,1031 } }, + { "Kodak DCS520C", 180, + { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } }, + { "Kodak DCS560C", 188, + { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } }, + { "Kodak DCS620C", 180, + { 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } }, + { "Kodak DCS620X", 185, + { 13095,-6231,154,12221,-21,-2137,895,4602,2258 } }, + { "Kodak DCS660C", 214, + { 18244,-6351,-2739,-791,11193,-521,3711,-129,2802 } }, + { "Kodak DCS720X", 0, + { 11775,-5884,950,9556,1846,-1286,-1019,6221,2728 } }, + { "Kodak DCS760C", 0, + { 16623,-6309,-1411,-4344,13923,323,2285,274,2926 } }, + { "Kodak DCS Pro SLR", 0, + { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } }, + { "Kodak DCS Pro 14nx", 0, + { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } }, + { "Kodak DCS Pro 14", 0, + { 7791,3128,-776,-8588,16458,2039,-2455,4006,6198 } }, + { "Kodak ProBack645", 0, + { 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } }, + { "Kodak ProBack", 0, + { 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } }, + { "KODAK P712", 0, + { 9658,-3314,-823,-5163,12695,2768,-1342,1843,6044 } }, + { "KODAK P850", 0, + { 10511,-3836,-1102,-6946,14587,2558,-1481,1792,6246 } }, + { "KODAK P880", 0, + { 12805,-4662,-1376,-7480,15267,2360,-1626,2194,7904 } }, + { "Leaf CMost", 0, + { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } }, + { "Leaf Valeo 6", 0, + { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } }, + { "Leaf Aptus 54S", 0, + { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } }, + { "Leaf Aptus 65", 0, + { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } }, + { "Leaf Aptus 75", 0, + { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } }, + { "Leaf", 0, + { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } }, + { "Mamiya ZD", 0, + { 7645,2579,-1363,-8689,16717,2015,-3712,5941,5961 } }, + { "Micron 2010", 110, /* DJC */ + { 16695,-3761,-2151,155,9682,163,3433,951,4904 } }, + { "Minolta DiMAGE 5", 0, + { 8983,-2942,-963,-6556,14476,2237,-2426,2887,8014 } }, + { "Minolta DiMAGE 7Hi", 0, + { 11368,-3894,-1242,-6521,14358,2339,-2475,3056,7285 } }, + { "Minolta DiMAGE 7", 0, + { 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 } }, + { "Minolta DiMAGE A1", 0, + { 9274,-2547,-1167,-8220,16323,1943,-2273,2720,8340 } }, + { "MINOLTA DiMAGE A200", 0, + { 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 } }, + { "Minolta DiMAGE A2", 0, + { 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 } }, + { "Minolta DiMAGE Z2", 0, /* DJC */ + { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } }, + { "MINOLTA DYNAX 5", 0, + { 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } }, + { "MINOLTA DYNAX 7", 0, + { 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } }, + { "NIKON D100", 0, + { 5902,-933,-782,-8983,16719,2354,-1402,1455,6464 } }, + { "NIKON D1H", 0, + { 7577,-2166,-926,-7454,15592,1934,-2377,2808,8606 } }, + { "NIKON D1X", 0, + { 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } }, + { "NIKON D1", 0, /* multiplied by 2.218750, 1.0, 1.148438 */ + { 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 } }, + { "NIKON D2H", 0, + { 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } }, + { "NIKON D2X", 0, + { 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } }, + { "NIKON D40X", 0, + { 8819,-2543,-911,-9025,16928,2151,-1329,1213,8449 } }, + { "NIKON D40", 0, + { 6992,-1668,-806,-8138,15748,2543,-874,850,7897 } }, + { "NIKON D50", 0, + { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, + { "NIKON D70", 0, + { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, + { "NIKON D80", 0, + { 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 } }, + { "NIKON D200", 0, + { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } }, + { "NIKON D300", 0, + { 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } }, + { "NIKON D3", 0, + { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } }, + { "NIKON E950", 0, /* DJC */ + { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } }, + { "NIKON E995", 0, /* copied from E5000 */ + { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, + { "NIKON E2500", 0, + { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, + { "NIKON E4300", 0, /* copied from Minolta DiMAGE Z2 */ + { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } }, + { "NIKON E4500", 0, + { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, + { "NIKON E5000", 0, + { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, + { "NIKON E5400", 0, + { 9349,-2987,-1001,-7919,15766,2266,-2098,2680,6839 } }, + { "NIKON E5700", 0, + { -5368,11478,2368,5537,-113,3148,-4969,10021,5782,778,9028,211 } }, + { "NIKON E8400", 0, + { 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 } }, + { "NIKON E8700", 0, + { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } }, + { "NIKON E8800", 0, + { 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } }, + { "OLYMPUS C5050", 0, + { 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 } }, + { "OLYMPUS C5060", 0, + { 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 } }, + { "OLYMPUS C7070", 0, + { 10252,-3531,-1095,-7114,14850,2436,-1451,1723,6365 } }, + { "OLYMPUS C70", 0, + { 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 } }, + { "OLYMPUS C80", 0, + { 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 } }, + { "OLYMPUS E-10", 0, + { 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } }, + { "OLYMPUS E-1", 0, + { 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } }, + { "OLYMPUS E-20", 0, + { 13173,-4732,-1499,-5807,14036,1895,-2045,2452,7142 } }, + { "OLYMPUS E-300", 0, + { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } }, + { "OLYMPUS E-330", 0, + { 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } }, + { "OLYMPUS E-3", 0, + { 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } }, + { "OLYMPUS E-400", 0, + { 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 } }, + { "OLYMPUS E-410", 0, + { 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } }, + { "OLYMPUS E-500", 0, + { 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } }, + { "OLYMPUS E-510", 0, + { 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } }, + { "OLYMPUS SP350", 0, + { 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } }, + { "OLYMPUS SP3", 0, + { 11766,-4445,-1067,-6901,14421,2707,-1029,1217,7572 } }, + { "OLYMPUS SP500UZ", 0, + { 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 } }, + { "OLYMPUS SP510UZ", 0, + { 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 } }, + { "OLYMPUS SP550UZ", 0, + { 11597,-4006,-1049,-5432,12799,2957,-1029,1750,6516 } }, + { "PENTAX *ist DL2", 0, + { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, + { "PENTAX *ist DL", 0, + { 10829,-2838,-1115,-8339,15817,2696,-837,680,11939 } }, + { "PENTAX *ist DS2", 0, + { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, + { "PENTAX *ist DS", 0, + { 10371,-2333,-1206,-8688,16231,2602,-1230,1116,11282 } }, + { "PENTAX *ist D", 0, + { 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } }, + { "PENTAX K10D", 0, + { 9566,-2863,-803,-7170,15172,2112,-818,803,9705 } }, + { "PENTAX K1", 0, + { 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } }, + { "Panasonic DMC-FZ8", 0, + { 8986,-2755,-802,-6341,13575,3077,-1476,2144,6379 } }, + { "Panasonic DMC-FZ18", 0, + { 9932,-3060,-935,-5809,13331,2753,-1267,2155,5575 } }, + { "Panasonic DMC-FZ30", 0, + { 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } }, + { "Panasonic DMC-FZ50", 0, /* aka "LEICA V-LUX1" */ + { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } }, + { "Panasonic DMC-L1", 0, /* aka "LEICA DIGILUX 3" */ + { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } }, + { "Panasonic DMC-LC1", 0, /* aka "LEICA DIGILUX 2" */ + { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } }, + { "Panasonic DMC-LX1", 0, /* aka "LEICA D-LUX2" */ + { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } }, + { "Panasonic DMC-LX2", 0, /* aka "LEICA D-LUX3" */ + { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } }, + { "Phase One H 20", 0, /* DJC */ + { 1313,1855,-109,-6715,15908,808,-327,1840,6020 } }, + { "Phase One P 2", 0, + { 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } }, + { "Phase One P 30", 0, + { 4516,-245,-37,-7020,14976,2173,-3206,4671,7087 } }, + { "Phase One P 45", 0, + { 5053,-24,-117,-5684,14076,1702,-2619,4492,5849 } }, + { "SAMSUNG GX-1", 0, + { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, + { "Sinar", 0, /* DJC */ + { 16442,-2956,-2422,-2877,12128,750,-1136,6066,4559 } }, + { "SONY DSC-F828", 491, + { 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 } }, + { "SONY DSC-R1", 512, + { 8512,-2641,-694,-8042,15670,2526,-1821,2117,7414 } }, + { "SONY DSC-V3", 0, + { 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } }, + { "SONY DSLR-A100", 0, + { 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } }, + { "SONY DSLR-A700", 254, + { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } } + }; + double cam_xyz[4][3]; + char name[130]; + int i, j; + + sprintf (name, "%s %s", make, model); + for (i=0; i < sizeof table / sizeof *table; i++) + if (!strncmp (name, table[i].prefix, strlen(table[i].prefix))) { + if (table[i].black) + black = table[i].black; + for (j=0; j < 12; j++) + cam_xyz[0][j] = table[i].trans[j] / 10000.0; + cam_xyz_coeff (cam_xyz); + break; + } +} + +void CLASS simple_coeff (int index) +{ + static const float table[][12] = { + /* index 0 -- all Foveon cameras */ + { 1.4032,-0.2231,-0.1016,-0.5263,1.4816,0.017,-0.0112,0.0183,0.9113 }, + /* index 1 -- Kodak DC20 and DC25 */ + { 2.25,0.75,-1.75,-0.25,-0.25,0.75,0.75,-0.25,-0.25,-1.75,0.75,2.25 }, + /* index 2 -- Logitech Fotoman Pixtura */ + { 1.893,-0.418,-0.476,-0.495,1.773,-0.278,-1.017,-0.655,2.672 }, + /* index 3 -- Nikon E880, E900, and E990 */ + { -1.936280, 1.800443, -1.448486, 2.584324, + 1.405365, -0.524955, -0.289090, 0.408680, + -1.204965, 1.082304, 2.941367, -1.818705 } + }; + int i, c; + + for (raw_color = i=0; i < 3; i++) + FORCC rgb_cam[i][c] = table[index][i*colors+c]; +} + +short CLASS guess_byte_order (int words) +{ + uchar test[4][2]; + int t=2, msb; + double diff, sum[2] = {0,0}; + + fread (test[0], 2, 2, ifp); + for (words-=2; words--; ) { + fread (test[t], 2, 1, ifp); + for (msb=0; msb < 2; msb++) { + diff = (test[t^2][msb] << 8 | test[t^2][!msb]) + - (test[t ][msb] << 8 | test[t ][!msb]); + sum[msb] += diff*diff; + } + t = (t+1) & 3; + } + return sum[0] < sum[1] ? 0x4d4d : 0x4949; +} + +/* + Identify which camera created this file, and set global variables + accordingly. + */ +void CLASS identify() +{ + char head[32], *cp; + unsigned hlen, fsize, i, c, is_canon; + struct jhead jh; + static const struct { + int fsize; + char make[12], model[19], withjpeg; + } table[] = { + { 62464, "Kodak", "DC20" ,0 }, + { 124928, "Kodak", "DC20" ,0 }, + { 1652736, "Kodak", "DCS200" ,0 }, + { 4159302, "Kodak", "C330" ,0 }, + { 4162462, "Kodak", "C330" ,0 }, + { 311696, "ST Micro", "STV680 VGA" ,0 }, /* SPYz */ + { 614400, "Kodak", "KAI-0340" ,0 }, + { 787456, "Creative", "PC-CAM 600" ,0 }, + { 1138688, "Minolta", "RD175" ,0 }, + { 3840000, "Foculus", "531C" ,0 }, + { 786432, "AVT", "F-080C" ,0 }, + { 1447680, "AVT", "F-145C" ,0 }, + { 1920000, "AVT", "F-201C" ,0 }, + { 5067304, "AVT", "F-510C" ,0 }, + { 10134608, "AVT", "F-510C" ,0 }, + { 16157136, "AVT", "F-810C" ,0 }, + { 1409024, "Sony", "XCD-SX910CR",0 }, + { 2818048, "Sony", "XCD-SX910CR",0 }, + { 3884928, "Micron", "2010" ,0 }, + { 6624000, "Pixelink", "A782" ,0 }, + { 13248000, "Pixelink", "A782" ,0 }, + { 6291456, "RoverShot","3320AF" ,0 }, + { 6573120, "Canon", "PowerShot A610",0 }, + { 9219600, "Canon", "PowerShot A620",0 }, + { 10383120, "Canon", "PowerShot A630",0 }, + { 12945240, "Canon", "PowerShot A640",0 }, + { 7710960, "Canon", "PowerShot S3 IS",0 }, + { 5939200, "OLYMPUS", "C770UZ" ,0 }, + { 1581060, "NIKON", "E900" ,1 }, /* or E900s,E910 */ + { 2465792, "NIKON", "E950" ,1 }, /* or E800,E700 */ + { 2940928, "NIKON", "E2100" ,1 }, /* or E2500 */ + { 4771840, "NIKON", "E990" ,1 }, /* or E995, Oly C3030Z */ + { 4775936, "NIKON", "E3700" ,1 }, /* or Optio 33WR */ + { 5869568, "NIKON", "E4300" ,1 }, /* or DiMAGE Z2 */ + { 5865472, "NIKON", "E4500" ,1 }, + { 7438336, "NIKON", "E5000" ,1 }, /* or E5700 */ + { 8998912, "NIKON", "COOLPIX S6" ,1 }, + { 1976352, "CASIO", "QV-2000UX" ,1 }, + { 3217760, "CASIO", "QV-3*00EX" ,1 }, + { 6218368, "CASIO", "QV-5700" ,1 }, + { 6054400, "CASIO", "QV-R41" ,1 }, + { 7530816, "CASIO", "QV-R51" ,1 }, + { 7684000, "CASIO", "QV-4000" ,1 }, + { 4948608, "CASIO", "EX-S100" ,1 }, + { 7542528, "CASIO", "EX-Z50" ,1 }, + { 7753344, "CASIO", "EX-Z55" ,1 }, + { 7426656, "CASIO", "EX-P505" ,1 }, + { 9313536, "CASIO", "EX-P600" ,1 }, + { 10979200, "CASIO", "EX-P700" ,1 }, + { 3178560, "PENTAX", "Optio S" ,1 }, + { 4841984, "PENTAX", "Optio S" ,1 }, + { 6114240, "PENTAX", "Optio S4" ,1 }, /* or S4i, CASIO EX-Z4 */ + { 10702848, "PENTAX", "Optio 750Z" ,1 }, + { 12582980, "Sinar", "" ,0 }, + { 33292868, "Sinar", "" ,0 }, + { 44390468, "Sinar", "" ,0 } }; + static const char *corp[] = + { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX", + "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One", + "SAMSUNG", "Mamiya" }; + + tiff_flip = flip = filters = -1; /* 0 is valid, so -1 is unknown */ + raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0; + maximum = height = width = top_margin = left_margin = 0; + cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0; + iso_speed = shutter = aperture = focal_len = unique_id = 0; + memset (white, 0, sizeof white); + thumb_offset = thumb_length = thumb_width = thumb_height = 0; + load_raw = thumb_load_raw = 0; + write_thumb = &CLASS jpeg_thumb; + data_offset = meta_length = tiff_bps = tiff_compress = 0; + kodak_cbpp = zero_after_ff = dng_version = 0; + timestamp = shot_order = tiff_samples = black = is_foveon = 0; + mix_green = profile_length = data_error = zero_is_bad = 0; + pixel_aspect = is_raw = raw_color = use_gamma = 1; + tile_width = tile_length = INT_MAX; + for (i=0; i < 4; i++) { + cam_mul[i] = i == 1; + pre_mul[i] = i < 3; + FORC3 cmatrix[c][i] = 0; + FORC3 rgb_cam[c][i] = c == i; + } + colors = 3; + tiff_bps = 12; + for (i=0; i < 0x4000; i++) curve[i] = i; + + order = get2(); + hlen = get4(); + fseek (ifp, 0, SEEK_SET); + fread (head, 1, 32, ifp); + fseek (ifp, 0, SEEK_END); + fsize = ftell(ifp); + if ((cp = (char *) memmem (head, 32, "MMMM", 4)) || + (cp = (char *) memmem (head, 32, "IIII", 4))) { + parse_phase_one (cp-head); + if (cp-head) parse_tiff(0); + } else if (order == 0x4949 || order == 0x4d4d) { + if (!memcmp (head+6,"HEAPCCDR",8)) { + data_offset = hlen; + parse_ciff (hlen, fsize - hlen); + } else { + parse_tiff(0); + } + } else if (!memcmp (head,"\xff\xd8\xff\xe1",4) && + !memcmp (head+6,"Exif",4)) { + fseek (ifp, 4, SEEK_SET); + data_offset = 4 + get2(); + fseek (ifp, data_offset, SEEK_SET); + if (fgetc(ifp) != 0xff) + parse_tiff(12); + thumb_offset = 0; + } else if (!memcmp (head+25,"ARECOYK",7)) { + strcpy (make, "Contax"); + strcpy (model,"N Digital"); + fseek (ifp, 33, SEEK_SET); + get_timestamp(1); + fseek (ifp, 60, SEEK_SET); + FORC4 cam_mul[c ^ (c >> 1)] = get4(); + } else if (!strcmp (head, "PXN")) { + strcpy (make, "Logitech"); + strcpy (model,"Fotoman Pixtura"); + } else if (!strcmp (head, "qktk")) { + strcpy (make, "Apple"); + strcpy (model,"QuickTake 100"); + } else if (!strcmp (head, "qktn")) { + strcpy (make, "Apple"); + strcpy (model,"QuickTake 150"); + } else if (!memcmp (head,"FUJIFILM",8)) { + fseek (ifp, 84, SEEK_SET); + thumb_offset = get4(); + thumb_length = get4(); + fseek (ifp, 92, SEEK_SET); + parse_fuji (get4()); + if (thumb_offset > 120) { + fseek (ifp, 120, SEEK_SET); + is_raw += (i = get4()) && 1; + if (is_raw == 2 && shot_select) + parse_fuji (i); + } + fseek (ifp, 100, SEEK_SET); + data_offset = get4(); + parse_tiff (thumb_offset+12); + } else if (!memcmp (head,"RIFF",4)) { + fseek (ifp, 0, SEEK_SET); + parse_riff(); + } else if (!memcmp (head,"DSC-Image",9)) + parse_rollei(); + else if (!memcmp (head,"PWAD",4)) + parse_sinar_ia(); + else if (!memcmp (head,"\0MRM",4)) + parse_minolta(0); + else if (!memcmp (head,"FOVb",4)) + parse_foveon(); + else if (!memcmp (head,"CI",2)) + parse_cine(); + else + for (i=0; i < sizeof table / sizeof *table; i++) + if (fsize == table[i].fsize) { + strcpy (make, table[i].make ); + strcpy (model, table[i].model); + if (table[i].withjpeg) + parse_external_jpeg(); + } + if (make[0] == 0) parse_smal (0, fsize); + if (make[0] == 0) parse_jpeg (is_raw = 0); + + for (i=0; i < sizeof corp / sizeof *corp; i++) + if (strstr (make, corp[i])) /* Simplify company names */ + strcpy (make, corp[i]); + if (!strncmp (make,"KODAK",5)) + make[16] = model[16] = 0; + cp = make + strlen(make); /* Remove trailing spaces */ + while (*--cp == ' ') *cp = 0; + cp = model + strlen(model); + while (*--cp == ' ') *cp = 0; + i = strlen(make); /* Remove make from model */ + if (!strncasecmp (model, make, i) && model[i++] == ' ') + memmove (model, model+i, 64-i); + if (!strncmp (model,"Digital Camera ",15)) + strcpy (model, model+15); + desc[511] = artist[63] = make[63] = model[63] = model2[63] = 0; + if (!is_raw) goto notraw; + + if (!maximum) maximum = (1 << tiff_bps) - 1; + if (!height) height = raw_height; + if (!width) width = raw_width; + if (fuji_width) { + width = height + fuji_width; + height = width - 1; + pixel_aspect = 1; + } + if (height == 2624 && width == 3936) { /* Pentax K10D and Samsung GX10 */ + height = 2616; + width = 3896; + } + if (dng_version) { + if (filters == UINT_MAX) filters = 0; + if (filters) is_raw = tiff_samples; + else colors = tiff_samples; + if (tiff_compress == 1) + load_raw = &CLASS adobe_dng_load_raw_nc; + if (tiff_compress == 7) + load_raw = &CLASS adobe_dng_load_raw_lj; + goto dng_skip; + } + if ((is_canon = !strcmp(make,"Canon"))) { + load_raw = memcmp (head+6,"HEAPCCDR",8) ? + &CLASS lossless_jpeg_load_raw : &CLASS canon_compressed_load_raw; + maximum = 0xfff; + } + if (!strcmp(make,"NIKON") && !load_raw) + load_raw = &CLASS nikon_load_raw; + +/* Set parameters based on camera name (for non-DNG files). */ + + if (is_foveon) { + if (height*2 < width) pixel_aspect = 0.5; + if (height > width) pixel_aspect = 2; + filters = 0; + load_raw = &CLASS foveon_load_raw; + simple_coeff(0); + } else if (is_canon && tiff_samples == 4) { + filters = 0; + load_raw = &CLASS canon_sraw_load_raw; + } else if (!strcmp(model,"PowerShot 600")) { + height = 613; + width = 854; + raw_width = 896; + pixel_aspect = 607/628.0; + colors = 4; + filters = 0xe1e4e1e4; + load_raw = &CLASS canon_600_load_raw; + } else if (!strcmp(model,"PowerShot A5") || + !strcmp(model,"PowerShot A5 Zoom")) { + height = 773; + width = 960; + raw_width = 992; + pixel_aspect = 256/235.0; + colors = 4; + filters = 0x1e4e1e4e; + load_raw = &CLASS canon_a5_load_raw; + } else if (!strcmp(model,"PowerShot A50")) { + height = 968; + width = 1290; + raw_width = 1320; + colors = 4; + filters = 0x1b4e4b1e; + load_raw = &CLASS canon_a5_load_raw; + } else if (!strcmp(model,"PowerShot Pro70")) { + height = 1024; + width = 1552; + colors = 4; + filters = 0x1e4b4e1b; + load_raw = &CLASS canon_a5_load_raw; + } else if (!strcmp(model,"PowerShot A610")) { + if (canon_s2is()) strcpy (model+10, "S2 IS"); + height = 1960; + width = 2616; + raw_height = 1968; + raw_width = 2672; + top_margin = 8; + left_margin = 12; + load_raw = &CLASS canon_a5_load_raw; + } else if (!strcmp(model,"PowerShot A620")) { + height = 2328; + width = 3112; + raw_height = 2340; + raw_width = 3152; + top_margin = 12; + left_margin = 36; + load_raw = &CLASS canon_a5_load_raw; + } else if (!strcmp(model,"PowerShot A630")) { + height = 2472; + width = 3288; + raw_height = 2484; + raw_width = 3344; + top_margin = 6; + left_margin = 12; + load_raw = &CLASS canon_a5_load_raw; + } else if (!strcmp(model,"PowerShot A640")) { + height = 2760; + width = 3672; + raw_height = 2772; + raw_width = 3736; + top_margin = 6; + left_margin = 12; + load_raw = &CLASS canon_a5_load_raw; + } else if (!strcmp(model,"PowerShot S3 IS")) { + height = 2128; + width = 2840; + raw_height = 2136; + raw_width = 2888; + top_margin = 8; + left_margin = 44; + load_raw = &CLASS canon_a5_load_raw; + } else if (!strcmp(model,"PowerShot Pro90 IS")) { + width = 1896; + colors = 4; + filters = 0xb4b4b4b4; + } else if (is_canon && raw_width == 2144) { + height = 1550; + width = 2088; + top_margin = 8; + left_margin = 4; + if (!strcmp(model,"PowerShot G1")) { + colors = 4; + filters = 0xb4b4b4b4; + } + } else if (is_canon && raw_width == 2224) { + height = 1448; + width = 2176; + top_margin = 6; + left_margin = 48; + } else if (is_canon && raw_width == 2376) { + height = 1720; + width = 2312; + top_margin = 6; + left_margin = 12; + } else if (is_canon && raw_width == 2672) { + height = 1960; + width = 2616; + top_margin = 6; + left_margin = 12; + } else if (is_canon && raw_width == 3152) { + height = 2056; + width = 3088; + top_margin = 12; + left_margin = 64; + if (unique_id == 0x80000170) + adobe_coeff ("Canon","EOS 300D"); + maximum = 0xfa0; + } else if (is_canon && raw_width == 3160) { + height = 2328; + width = 3112; + top_margin = 12; + left_margin = 44; + } else if (is_canon && raw_width == 3344) { + height = 2472; + width = 3288; + top_margin = 6; + left_margin = 4; + } else if (!strcmp(model,"EOS D2000C")) { + filters = 0x61616161; + black = curve[200]; + } else if (is_canon && raw_width == 3516) { + top_margin = 14; + left_margin = 42; + if (unique_id == 0x80000189) + adobe_coeff ("Canon","EOS 350D"); + goto canon_cr2; + } else if (is_canon && raw_width == 3596) { + top_margin = 12; + left_margin = 74; + goto canon_cr2; + } else if (is_canon && raw_width == 3944) { + height = 2602; + width = 3908; + top_margin = 18; + left_margin = 30; + maximum = 0x3f60; + } else if (is_canon && raw_width == 3948) { + top_margin = 18; + left_margin = 42; + height -= 2; + if (unique_id == 0x80000236) + adobe_coeff ("Canon","EOS 400D"); + goto canon_cr2; + } else if (is_canon && raw_width == 3984) { + top_margin = 20; + left_margin = 76; + height -= 2; + maximum = 0x3bb0; + goto canon_cr2; + } else if (is_canon && raw_width == 4104) { + height = 3024; + width = 4032; + top_margin = 12; + left_margin = 48; + } else if (is_canon && raw_width == 4476) { + top_margin = 34; + left_margin = 90; + maximum = 0xe6c; + goto canon_cr2; + } else if (is_canon && raw_width == 5108) { + top_margin = 13; + left_margin = 98; + maximum = 0xe80; +canon_cr2: + height -= top_margin; + width -= left_margin; + } else if (is_canon && raw_width == 5712) { + height = 3752; + width = 5640; + top_margin = 20; + left_margin = 62; + maximum = 0x3bb0; + } else if (!strcmp(model,"D1")) { + cam_mul[0] *= 256/527.0; + cam_mul[2] *= 256/317.0; + } else if (!strcmp(model,"D1X")) { + width -= 4; + pixel_aspect = 0.5; + } else if (!strncmp(model,"D40",3) || + !strncmp(model,"D50",3) || + !strncmp(model,"D70",3)) { + width--; + } else if (!strcmp(model,"D80")) { + height -= 3; + width -= 4; + } else if (!strcmp(model,"D100")) { + if (tiff_compress == 34713 && !nikon_is_compressed()) { + load_raw = &CLASS nikon_load_raw; + raw_width = (width += 3) + 3; + } + maximum = 0xf44; + } else if (!strcmp(model,"D200")) { + left_margin = 1; + width -= 4; + maximum = 0xfbc; + filters = 0x94949494; + } else if (!strncmp(model,"D2H",3)) { + left_margin = 6; + width -= 14; + } else if (!strcmp(model,"D2X")) { + width -= 8; + maximum = 0xf35; + } else if (!strcmp(model,"D300")) { + width -= 32; + } else if (fsize == 1581060) { + height = 963; + width = 1287; + raw_width = 1632; + load_raw = &CLASS nikon_e900_load_raw; + maximum = 0x3f4; + colors = 4; + filters = 0x1e1e1e1e; + simple_coeff(3); + pre_mul[0] = 1.2085; + pre_mul[1] = 1.0943; + pre_mul[3] = 1.1103; + } else if (fsize == 2465792) { + height = 1203; + width = 1616; + raw_width = 2048; + load_raw = &CLASS nikon_e900_load_raw; + maximum = 0x3dd; + colors = 4; + filters = 0x4b4b4b4b; + adobe_coeff ("NIKON","E950"); + } else if (fsize == 4771840) { + height = 1540; + width = 2064; + colors = 4; + filters = 0xe1e1e1e1; + load_raw = &CLASS nikon_load_raw; + if (!timestamp && nikon_e995()) + strcpy (model, "E995"); + if (strcmp(model,"E995")) { + filters = 0xb4b4b4b4; + simple_coeff(3); + pre_mul[0] = 1.196; + pre_mul[1] = 1.246; + pre_mul[2] = 1.018; + } + } else if (!strcmp(model,"E2100")) { + if (!timestamp && !nikon_e2100()) goto cp_e2500; + height = 1206; + width = 1616; + load_raw = &CLASS nikon_e2100_load_raw; + pre_mul[0] = 1.945; + pre_mul[2] = 1.040; + } else if (!strcmp(model,"E2500")) { +cp_e2500: + strcpy (model, "E2500"); + height = 1204; + width = 1616; + colors = 4; + filters = 0x4b4b4b4b; + } else if (fsize == 4775936) { + height = 1542; + width = 2064; + load_raw = &CLASS nikon_e2100_load_raw; + pre_mul[0] = 1.818; + pre_mul[2] = 1.618; + if (!timestamp) nikon_3700(); + if (model[0] == 'E' && atoi(model+1) < 3700) + filters = 0x49494949; + if (!strcmp(model,"Optio 33WR")) { + flip = 1; + filters = 0x16161616; + pre_mul[0] = 1.331; + pre_mul[2] = 1.820; + } + } else if (fsize == 5869568) { + height = 1710; + width = 2288; + filters = 0x16161616; + if (!timestamp && minolta_z2()) { + strcpy (make, "Minolta"); + strcpy (model,"DiMAGE Z2"); + } + if (make[0] == 'M') + load_raw = &CLASS nikon_e2100_load_raw; + } else if (!strcmp(model,"E4500")) { + height = 1708; + width = 2288; + colors = 4; + filters = 0xb4b4b4b4; + } else if (fsize == 7438336) { + height = 1924; + width = 2576; + colors = 4; + filters = 0xb4b4b4b4; + } else if (fsize == 8998912) { + height = 2118; + width = 2832; + maximum = 0xf83; + load_raw = &CLASS nikon_e2100_load_raw; + } else if (!strcmp(model,"FinePix S5100") || + !strcmp(model,"FinePix S5500")) { + load_raw = &CLASS unpacked_load_raw; + maximum = 0x3e00; + } else if (!strncmp(model,"FinePix",7)) { + if (!strcmp(model+7,"S2Pro")) { + strcpy (model+7," S2Pro"); + height = 2144; + width = 2880; + flip = 6; + } else + maximum = 0x3e00; + if (is_raw == 2 && shot_select) + maximum = 0x2f00; + top_margin = (raw_height - height)/2; + left_margin = (raw_width - width )/2; + if (is_raw == 2) + data_offset += (shot_select > 0) * ( fuji_layout ? + (raw_width *= 2) : raw_height*raw_width*2 ); + fuji_width = width >> !fuji_layout; + width = (height >> fuji_layout) + fuji_width; + raw_height = height; + height = width - 1; + load_raw = &CLASS fuji_load_raw; + if (!(fuji_width & 1)) filters = 0x49494949; + } else if (!strcmp(model,"RD175")) { + height = 986; + width = 1534; + data_offset = 513; + filters = 0x61616161; + load_raw = &CLASS minolta_rd175_load_raw; + } else if (!strcmp(model,"KD-400Z")) { + height = 1712; + width = 2312; + raw_width = 2336; + goto konica_400z; + } else if (!strcmp(model,"KD-510Z")) { + goto konica_510z; + } else if (!strcasecmp(make,"MINOLTA")) { + load_raw = &CLASS unpacked_load_raw; + maximum = 0xf7d; + if (!strncmp(model,"DiMAGE A",8)) { + if (!strcmp(model,"DiMAGE A200")) + filters = 0x49494949; + load_raw = &CLASS packed_12_load_raw; + maximum = model[8] == '1' ? 0xf8b : 0xfff; + } else if (!strncmp(model,"ALPHA",5) || + !strncmp(model,"DYNAX",5) || + !strncmp(model,"MAXXUM",6)) { + sprintf (model+20, "DYNAX %-10s", model+6+(model[0]=='M')); + adobe_coeff (make, model+20); + load_raw = &CLASS packed_12_load_raw; + maximum = 0xffb; + } else if (!strncmp(model,"DiMAGE G",8)) { + if (model[8] == '4') { + height = 1716; + width = 2304; + } else if (model[8] == '5') { +konica_510z: + height = 1956; + width = 2607; + raw_width = 2624; + } else if (model[8] == '6') { + height = 2136; + width = 2848; + } + data_offset += 14; + filters = 0x61616161; +konica_400z: + load_raw = &CLASS unpacked_load_raw; + maximum = 0x3df; + order = 0x4d4d; + } + } else if (!strcmp(model,"*ist DS")) { + height -= 2; + } else if (!strcmp(model,"Optio S")) { + if (fsize == 3178560) { + height = 1540; + width = 2064; + load_raw = &CLASS eight_bit_load_raw; + cam_mul[0] *= 4; + cam_mul[2] *= 4; + pre_mul[0] = 1.391; + pre_mul[2] = 1.188; + } else { + height = 1544; + width = 2068; + raw_width = 3136; + load_raw = &CLASS packed_12_load_raw; + maximum = 0xf7c; + pre_mul[0] = 1.137; + pre_mul[2] = 1.453; + } + } else if (fsize == 6114240) { + height = 1737; + width = 2324; + raw_width = 3520; + load_raw = &CLASS packed_12_load_raw; + maximum = 0xf7a; + pre_mul[0] = 1.980; + pre_mul[2] = 1.570; + } else if (!strcmp(model,"Optio 750Z")) { + height = 2302; + width = 3072; + load_raw = &CLASS nikon_e2100_load_raw; + } else if (!strcmp(model,"STV680 VGA")) { + height = 484; + width = 644; + load_raw = &CLASS eight_bit_load_raw; + flip = 2; + filters = 0x16161616; + black = 16; + pre_mul[0] = 1.097; + pre_mul[2] = 1.128; + } else if (!strcmp(model,"KAI-0340")) { + height = 477; + width = 640; + order = 0x4949; + data_offset = 3840; + load_raw = &CLASS unpacked_load_raw; + pre_mul[0] = 1.561; + pre_mul[2] = 2.454; + } else if (!strcmp(model,"531C")) { + height = 1200; + width = 1600; + load_raw = &CLASS unpacked_load_raw; + filters = 0x49494949; + pre_mul[1] = 1.218; + } else if (!strcmp(model,"F-080C")) { + height = 768; + width = 1024; + load_raw = &CLASS eight_bit_load_raw; + } else if (!strcmp(model,"F-145C")) { + height = 1040; + width = 1392; + load_raw = &CLASS eight_bit_load_raw; + } else if (!strcmp(model,"F-201C")) { + height = 1200; + width = 1600; + load_raw = &CLASS eight_bit_load_raw; + } else if (!strcmp(model,"F-510C")) { + height = 1958; + width = 2588; + load_raw = fsize < 7500000 ? + &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw; + maximum = 0xfff0; + } else if (!strcmp(model,"F-810C")) { + height = 2469; + width = 3272; + load_raw = &CLASS unpacked_load_raw; + maximum = 0xfff0; + } else if (!strcmp(model,"XCD-SX910CR")) { + height = 1024; + width = 1375; + raw_width = 1376; + filters = 0x49494949; + maximum = 0x3ff; + load_raw = fsize < 2000000 ? + &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw; + } else if (!strcmp(model,"2010")) { + height = 1207; + width = 1608; + order = 0x4949; + filters = 0x16161616; + data_offset = 3212; + maximum = 0x3ff; + load_raw = &CLASS unpacked_load_raw; + } else if (!strcmp(model,"A782")) { + height = 3000; + width = 2208; + filters = 0x61616161; + load_raw = fsize < 10000000 ? + &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw; + maximum = 0xffc0; + } else if (!strcmp(model,"3320AF")) { + height = 1536; + raw_width = width = 2048; + filters = 0x61616161; + load_raw = &CLASS unpacked_load_raw; + maximum = 0x3ff; + pre_mul[0] = 1.717; + pre_mul[2] = 1.138; + fseek (ifp, 0x300000, SEEK_SET); + if ((order = guess_byte_order(0x10000)) == 0x4d4d) { + height -= (top_margin = 16); + width -= (left_margin = 28); + maximum = 0xf5c0; + strcpy (make, "ISG"); + model[0] = 0; + } + } else if (!strcmp(make,"Hasselblad")) { + if (load_raw == lossless_jpeg_load_raw) + load_raw = hasselblad_load_raw; + } else if (!strcmp(make,"Sinar")) { + if (!memcmp(head,"8BPS",4)) { + fseek (ifp, 14, SEEK_SET); + height = get4(); + width = get4(); + filters = 0x61616161; + data_offset = 68; + } + if (!load_raw) load_raw = &CLASS unpacked_load_raw; + maximum = 0x3fff; + } else if (!strcmp(make,"Leaf")) { + maximum = 0x3fff; + if (tiff_samples > 1) filters = 0; + if (tiff_samples > 1 || tile_length < raw_height) + load_raw = &CLASS leaf_hdr_load_raw; + if ((width | height) == 2048) { + if (tiff_samples == 1) { + filters = 1; + strcpy (cdesc, "RBTG"); + strcpy (model, "CatchLight"); + top_margin = 8; left_margin = 18; height = 2032; width = 2016; + } else { + strcpy (model, "DCB2"); + top_margin = 10; left_margin = 16; height = 2028; width = 2022; + } + } else if (width+height == 3144+2060) { + if (!model[0]) strcpy (model, "Cantare"); + if (width > height) { + top_margin = 6; left_margin = 32; height = 2048; width = 3072; + filters = 0x61616161; + } else { + left_margin = 6; top_margin = 32; width = 2048; height = 3072; + filters = 0x16161616; + } + if (!cam_mul[0] || model[0] == 'V') filters = 0; + else is_raw = tiff_samples; + } else if (width == 2116) { + strcpy (model, "Valeo 6"); + height -= 2 * (top_margin = 30); + width -= 2 * (left_margin = 55); + filters = 0x49494949; + } else if (width == 3171) { + strcpy (model, "Valeo 6"); + height -= 2 * (top_margin = 24); + width -= 2 * (left_margin = 24); + filters = 0x16161616; + } + } else if (!strcmp(make,"LEICA") || !strcmp(make,"Panasonic")) { + maximum = 0xfff0; + if (!load_raw) load_raw = &CLASS unpacked_load_raw; + switch (width) { + case 2568: + adobe_coeff ("Panasonic","DMC-LC1"); break; + case 3130: + left_margin = -14; + case 3170: + left_margin += 18; + width = 3096; + if (height > 2326) { + height = 2326; + top_margin = 13; + filters = 0x49494949; + } + maximum = 0xf7f0; + zero_is_bad = 1; + adobe_coeff ("Panasonic","DMC-FZ8"); break; + case 3177: + width -= 10; + filters = 0x49494949; + maximum = 0xf7fc; + zero_is_bad = 1; + adobe_coeff ("Panasonic","DMC-L1"); break; + case 3304: + width -= 16; + maximum = 0xf94c; + zero_is_bad = 1; + adobe_coeff ("Panasonic","DMC-FZ30"); break; + case 3330: + width = 3291; + left_margin = 9; + maximum = 0xf7f0; + goto fz18; + case 3370: + width = 3288; + left_margin = 15; +fz18: if (height > 2480) + height = 2480 - (top_margin = 10); + filters = 0x49494949; + zero_is_bad = 1; + break; + case 3690: + height += 36; + left_margin = -14; + filters = 0x49494949; + maximum = 0xf7f0; + case 3770: + width = 3672; + if ((height -= 39) == 2760) + top_margin = 15; + left_margin += 17; + zero_is_bad = 1; + adobe_coeff ("Panasonic","DMC-FZ50"); break; + case 3880: + width -= 22; + left_margin = 6; + maximum = 0xf7f0; + zero_is_bad = 1; + adobe_coeff ("Panasonic","DMC-LX1"); break; + case 4290: + height += 38; + left_margin = -14; + filters = 0x49494949; + case 4330: + width = 4248; + if ((height -= 39) == 2400) + top_margin = 15; + left_margin += 17; + adobe_coeff ("Panasonic","DMC-LX2"); break; + } + } else if (!strcmp(model,"C770UZ")) { + height = 1718; + width = 2304; + filters = 0x16161616; + load_raw = &CLASS nikon_e2100_load_raw; + } else if (!strcmp(make,"OLYMPUS")) { + height += height & 1; + filters = exif_cfa; + if (!strcmp(model,"E-1") || + !strcmp(model,"E-400")) { + maximum = 0xfff0; + } else if (!strcmp(model,"E-10") || + !strncmp(model,"E-20",4)) { + maximum = 0xffc0; + black <<= 2; + } else if (!strcmp(model,"E-300") || + !strcmp(model,"E-500")) { + width -= 20; + if (load_raw == &CLASS unpacked_load_raw) { + maximum = 0xfc30; + black = 0; + } + } else if (!strcmp(model,"E-330")) { + width -= 30; + if (load_raw == &CLASS unpacked_load_raw) + maximum = 0xf790; + } else if (!strcmp(model,"E-3")) { + maximum = 0xf99; + goto e410; + } else if (!strcmp(model,"E-410") || + !strcmp(model,"E-510")) { + maximum = 0xf6a; +e410: load_raw = &CLASS olympus_e410_load_raw; + black >>= 4; + } else if (!strcmp(model,"SP550UZ")) { + thumb_length = fsize - (thumb_offset = 0xa39800); + thumb_height = 480; + thumb_width = 640; + } + } else if (!strcmp(model,"N Digital")) { + height = 2047; + width = 3072; + filters = 0x61616161; + data_offset = 0x1a00; + load_raw = &CLASS packed_12_load_raw; + maximum = 0xf1e; + } else if (!strcmp(model,"DSC-F828")) { + width = 3288; + left_margin = 5; + data_offset = 862144; + load_raw = &CLASS sony_load_raw; + filters = 0x9c9c9c9c; + colors = 4; + strcpy (cdesc, "RGBE"); + } else if (!strcmp(model,"DSC-V3")) { + width = 3109; + left_margin = 59; + data_offset = 787392; + load_raw = &CLASS sony_load_raw; + } else if (!strcmp(make,"SONY") && raw_width == 3984) { + adobe_coeff ("SONY","DSC-R1"); + width = 3925; + order = 0x4d4d; + } else if (!strcmp(model,"DSLR-A100")) { + height--; + load_raw = &CLASS sony_arw_load_raw; + maximum = 0xfeb; + } else if (!strncmp(model,"P850",4)) { + maximum = 0xf7c; + } else if (!strcmp(model,"C330")) { + height = 1744; + width = 2336; + raw_height = 1779; + raw_width = 2338; + top_margin = 33; + left_margin = 1; + order = 0x4949; + if ((data_offset = fsize - raw_height*raw_width)) { + fseek (ifp, 168, SEEK_SET); + read_shorts (curve, 256); + } else use_gamma = 0; + load_raw = &CLASS eight_bit_load_raw; + } else if (!strcasecmp(make,"KODAK")) { + if (filters == UINT_MAX) filters = 0x61616161; + if (!strncmp(model,"NC2000",6)) { + width -= 4; + left_margin = 2; + } else if (!strcmp(model,"EOSDCS3B")) { + width -= 4; + left_margin = 2; + } else if (!strcmp(model,"EOSDCS1")) { + width -= 4; + left_margin = 2; + } else if (!strcmp(model,"DCS420")) { + width -= 4; + left_margin = 2; + } else if (!strcmp(model,"DCS460")) { + width -= 4; + left_margin = 2; + } else if (!strcmp(model,"DCS460A")) { + width -= 4; + left_margin = 2; + colors = 1; + filters = 0; + } else if (!strcmp(model,"DCS660M")) { + black = 214; + colors = 1; + filters = 0; + } else if (!strcmp(model,"DCS760M")) { + colors = 1; + filters = 0; + } + if (strstr(model,"DC25")) { + strcpy (model, "DC25"); + data_offset = 15424; + } + if (!strncmp(model,"DC2",3)) { + height = 242; + if (fsize < 100000) { + raw_width = 256; width = 249; + pixel_aspect = (4.0*height) / (3.0*width); + } else { + raw_width = 512; width = 501; + pixel_aspect = (493.0*height) / (373.0*width); + } + data_offset += raw_width + 1; + colors = 4; + filters = 0x8d8d8d8d; + simple_coeff(1); + pre_mul[1] = 1.179; + pre_mul[2] = 1.209; + pre_mul[3] = 1.036; + load_raw = &CLASS eight_bit_load_raw; + } else if (!strcmp(model,"40")) { + strcpy (model, "DC40"); + height = 512; + width = 768; + data_offset = 1152; + load_raw = &CLASS kodak_radc_load_raw; + } else if (strstr(model,"DC50")) { + strcpy (model, "DC50"); + height = 512; + width = 768; + data_offset = 19712; + load_raw = &CLASS kodak_radc_load_raw; + } else if (strstr(model,"DC120")) { + strcpy (model, "DC120"); + height = 976; + width = 848; + pixel_aspect = height/0.75/width; + load_raw = tiff_compress == 7 ? + &CLASS kodak_jpeg_load_raw : &CLASS kodak_dc120_load_raw; + } else if (!strcmp(model,"DCS200")) { + thumb_height = 128; + thumb_width = 192; + thumb_offset = 6144; + thumb_misc = 360; + write_thumb = &CLASS layer_thumb; + height = 1024; + width = 1536; + data_offset = 79872; + load_raw = &CLASS eight_bit_load_raw; + black = 17; + } + } else if (!strcmp(model,"Fotoman Pixtura")) { + height = 512; + width = 768; + data_offset = 3632; + load_raw = &CLASS kodak_radc_load_raw; + filters = 0x61616161; + simple_coeff(2); + } else if (!strcmp(model,"QuickTake 100")) { + data_offset = 736; + load_raw = &CLASS quicktake_100_load_raw; + goto qt_common; + } else if (!strcmp(model,"QuickTake 150")) { + data_offset = 738; + load_raw = &CLASS kodak_radc_load_raw; +qt_common: + height = 480; + width = 640; + filters = 0x61616161; + } else if (!strcmp(make,"Rollei") && !load_raw) { + switch (raw_width) { + case 1316: + height = 1030; + width = 1300; + top_margin = 1; + left_margin = 6; + break; + case 2568: + height = 1960; + width = 2560; + top_margin = 2; + left_margin = 8; + } + filters = 0x16161616; + load_raw = &CLASS rollei_load_raw; + pre_mul[0] = 1.8; + pre_mul[2] = 1.3; + } else if (!strcmp(model,"PC-CAM 600")) { + height = 768; + data_offset = width = 1024; + filters = 0x49494949; + load_raw = &CLASS eight_bit_load_raw; + pre_mul[0] = 1.14; + pre_mul[2] = 2.73; + } else if (!strcmp(model,"QV-2000UX")) { + height = 1208; + width = 1632; + data_offset = width * 2; + load_raw = &CLASS eight_bit_load_raw; + } else if (fsize == 3217760) { + height = 1546; + width = 2070; + raw_width = 2080; + load_raw = &CLASS eight_bit_load_raw; + } else if (!strcmp(model,"QV-4000")) { + height = 1700; + width = 2260; + load_raw = &CLASS unpacked_load_raw; + maximum = 0xffff; + } else if (!strcmp(model,"QV-5700")) { + height = 1924; + width = 2576; + load_raw = &CLASS casio_qv5700_load_raw; + } else if (!strcmp(model,"QV-R41")) { + height = 1720; + width = 2312; + raw_width = 3520; + left_margin = 2; + load_raw = &CLASS packed_12_load_raw; + maximum = 0xf7f; + } else if (!strcmp(model,"QV-R51")) { + height = 1926; + width = 2580; + raw_width = 3904; + load_raw = &CLASS packed_12_load_raw; + maximum = 0xf7f; + pre_mul[0] = 1.340; + pre_mul[2] = 1.672; + } else if (!strcmp(model,"EX-S100")) { + height = 1544; + width = 2058; + raw_width = 3136; + load_raw = &CLASS packed_12_load_raw; + pre_mul[0] = 1.631; + pre_mul[2] = 1.106; + } else if (!strcmp(model,"EX-Z50")) { + height = 1931; + width = 2570; + raw_width = 3904; + load_raw = &CLASS packed_12_load_raw; + maximum = 0xf7f; + pre_mul[0] = 2.529; + pre_mul[2] = 1.185; + } else if (!strcmp(model,"EX-Z55")) { + height = 1960; + width = 2570; + raw_width = 3904; + load_raw = &CLASS packed_12_load_raw; + maximum = 0xf7f; + pre_mul[0] = 1.520; + pre_mul[2] = 1.316; + } else if (!strcmp(model,"EX-P505")) { + height = 1928; + width = 2568; + raw_width = 3852; + load_raw = &CLASS packed_12_load_raw; + pre_mul[0] = 2.07; + pre_mul[2] = 1.88; + } else if (fsize == 9313536) { /* EX-P600 or QV-R61 */ + height = 2142; + width = 2844; + raw_width = 4288; + load_raw = &CLASS packed_12_load_raw; + maximum = 0xf7f; + pre_mul[0] = 1.797; + pre_mul[2] = 1.219; + } else if (!strcmp(model,"EX-P700")) { + height = 2318; + width = 3082; + raw_width = 4672; + load_raw = &CLASS packed_12_load_raw; + maximum = 0xf7f; + pre_mul[0] = 1.758; + pre_mul[2] = 1.504; + } + if (!model[0]) + sprintf (model, "%dx%d", width, height); + if (filters == UINT_MAX) filters = 0x94949494; + if (raw_color) adobe_coeff (make, model); + if (thumb_offset && !thumb_height) { + fseek (ifp, thumb_offset, SEEK_SET); + if (ljpeg_start (&jh, 1)) { + thumb_width = jh.wide; + thumb_height = jh.high; + } + } +dng_skip: + if (!load_raw || height < 22) is_raw = 0; +#ifdef NO_JPEG + if (load_raw == kodak_jpeg_load_raw) { + fprintf (stderr,_("%s: You must link dcraw with libjpeg!!\n"), ifname); + is_raw = 0; + } +#endif + if (!cdesc[0]) + strcpy (cdesc, colors == 3 ? "RGB":"GMCY"); + if (!raw_height) raw_height = height; + if (!raw_width ) raw_width = width; + if (filters && colors == 3) + for (i=0; i < 32; i+=4) { + if ((filters >> i & 15) == 9) + filters |= 2 << i; + if ((filters >> i & 15) == 6) + filters |= 8 << i; + } +notraw: + if (flip == -1) flip = tiff_flip; + if (flip == -1) flip = 0; +} + +#ifndef NO_LCMS +void CLASS apply_profile (char *input, char *output) +{ + char *prof; + cmsHPROFILE hInProfile=0, hOutProfile=0; + cmsHTRANSFORM hTransform; + FILE *fp; + unsigned size; + + cmsErrorAction (LCMS_ERROR_SHOW); + if (strcmp (input, "embed")) + hInProfile = cmsOpenProfileFromFile (input, "r"); + else if (profile_length) { + prof = (char *) malloc (profile_length); + merror (prof, "apply_profile()"); + fseek (ifp, profile_offset, SEEK_SET); + fread (prof, 1, profile_length, ifp); + hInProfile = cmsOpenProfileFromMem (prof, profile_length); + free (prof); + } else + fprintf (stderr,_("%s has no embedded profile.\n"), ifname); + if (!hInProfile) return; + if (!output) + hOutProfile = cmsCreate_sRGBProfile(); + else if ((fp = fopen (output, "rb"))) { + fread (&size, 4, 1, fp); + fseek (fp, 0, SEEK_SET); + oprof = (unsigned *) malloc (size = ntohl(size)); + merror (oprof, "apply_profile()"); + fread (oprof, 1, size, fp); + fclose (fp); + if (!(hOutProfile = cmsOpenProfileFromMem (oprof, size))) { + free (oprof); + oprof = 0; + } + } else + fprintf (stderr,_("Cannot open file %s!\n"), output); + if (!hOutProfile) goto quit; + if (verbose) + fprintf (stderr,_("Applying color profile...\n")); + hTransform = cmsCreateTransform (hInProfile, TYPE_RGBA_16, + hOutProfile, TYPE_RGBA_16, INTENT_PERCEPTUAL, 0); + cmsDoTransform (hTransform, image, image, width*height); + raw_color = 1; /* Don't use rgb_cam with a profile */ + cmsDeleteTransform (hTransform); + cmsCloseProfile (hOutProfile); +quit: + cmsCloseProfile (hInProfile); +} +#endif + +void CLASS convert_to_rgb() +{ + int row, col, c, i, j, k; + ushort *img; + float out[3], out_cam[3][4]; + double num, inverse[3][3]; + static const double xyzd50_srgb[3][3] = + { { 0.436083, 0.385083, 0.143055 }, + { 0.222507, 0.716888, 0.060608 }, + { 0.013930, 0.097097, 0.714022 } }; + static const double rgb_rgb[3][3] = + { { 1,0,0 }, { 0,1,0 }, { 0,0,1 } }; + static const double adobe_rgb[3][3] = + { { 0.715146, 0.284856, 0.000000 }, + { 0.000000, 1.000000, 0.000000 }, + { 0.000000, 0.041166, 0.958839 } }; + static const double wide_rgb[3][3] = + { { 0.593087, 0.404710, 0.002206 }, + { 0.095413, 0.843149, 0.061439 }, + { 0.011621, 0.069091, 0.919288 } }; + static const double prophoto_rgb[3][3] = + { { 0.529317, 0.330092, 0.140588 }, + { 0.098368, 0.873465, 0.028169 }, + { 0.016879, 0.117663, 0.865457 } }; + static const double (*out_rgb[])[3] = + { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb }; + static const char *name[] = + { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ" }; + static const unsigned phead[] = + { 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0, + 0x61637370, 0, 0, 0x6e6f6e65, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d }; + unsigned pbody[] = + { 10, 0x63707274, 0, 36, /* cprt */ + 0x64657363, 0, 40, /* desc */ + 0x77747074, 0, 20, /* wtpt */ + 0x626b7074, 0, 20, /* bkpt */ + 0x72545243, 0, 14, /* rTRC */ + 0x67545243, 0, 14, /* gTRC */ + 0x62545243, 0, 14, /* bTRC */ + 0x7258595a, 0, 20, /* rXYZ */ + 0x6758595a, 0, 20, /* gXYZ */ + 0x6258595a, 0, 20 }; /* bXYZ */ + static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc }; + unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 }; + + memcpy (out_cam, rgb_cam, sizeof out_cam); + raw_color |= colors == 1 || document_mode || + output_color < 1 || output_color > 5; + if (!raw_color) { + oprof = (unsigned *) calloc (phead[0], 1); + merror (oprof, "convert_to_rgb()"); + memcpy (oprof, phead, sizeof phead); + if (output_color == 5) oprof[4] = oprof[5]; + oprof[0] = 132 + 12*pbody[0]; + for (i=0; i < pbody[0]; i++) { + oprof[oprof[0]/4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874; + pbody[i*3+2] = oprof[0]; + oprof[0] += (pbody[i*3+3] + 3) & -4; + } + memcpy (oprof+32, pbody, sizeof pbody); + oprof[pbody[5]/4+2] = strlen(name[output_color-1]) + 1; + memcpy ((char *)oprof+pbody[8]+8, pwhite, sizeof pwhite); + if (output_bps == 8) +#ifdef SRGB_GAMMA + pcurve[3] = 0x2330000; +#else + pcurve[3] = 0x1f00000; +#endif + for (i=4; i < 7; i++) + memcpy ((char *)oprof+pbody[i*3+2], pcurve, sizeof pcurve); + pseudoinverse ((double (*)[3]) out_rgb[output_color-1], inverse, 3); + for (i=0; i < 3; i++) + for (j=0; j < 3; j++) { + for (num = k=0; k < 3; k++) + num += xyzd50_srgb[i][k] * inverse[j][k]; + oprof[pbody[j*3+23]/4+i+2] = num * 0x10000 + 0.5; + } + for (i=0; i < phead[0]/4; i++) + oprof[i] = htonl(oprof[i]); + strcpy ((char *)oprof+pbody[2]+8, "auto-generated by dcraw"); + strcpy ((char *)oprof+pbody[5]+12, name[output_color-1]); + for (i=0; i < 3; i++) + for (j=0; j < colors; j++) + for (out_cam[i][j] = k=0; k < 3; k++) + out_cam[i][j] += out_rgb[output_color-1][i][k] * rgb_cam[k][j]; + } + if (verbose) + fprintf (stderr, raw_color ? _("Building histograms...\n") : + _("Converting to %s colorspace...\n"), name[output_color-1]); + + memset (histogram, 0, sizeof histogram); + for (img=image[0], row=0; row < height; row++) + for (col=0; col < width; col++, img+=4) { + if (!raw_color) { + out[0] = out[1] = out[2] = 0; + FORCC { + out[0] += out_cam[0][c] * img[c]; + out[1] += out_cam[1][c] * img[c]; + out[2] += out_cam[2][c] * img[c]; + } + FORC3 img[c] = CLIP((int) out[c]); + } + else if (document_mode) + img[0] = img[FC(row,col)]; + FORCC histogram[c][img[c] >> 3]++; + } + if (colors == 4 && output_color) colors = 3; + if (document_mode && filters) colors = 1; +} + +void CLASS fuji_rotate() +{ + int i, row, col; + double step; + float r, c, fr, fc; + unsigned ur, uc; + ushort wide, high, (*img)[4], (*pix)[4]; + + if (!fuji_width) return; + if (verbose) + fprintf (stderr,_("Rotating image 45 degrees...\n")); + fuji_width = (fuji_width - 1 + shrink) >> shrink; + step = sqrt(0.5); + wide = fuji_width / step; + high = (height - fuji_width) / step; + img = (ushort (*)[4]) calloc (wide*high, sizeof *img); + merror (img, "fuji_rotate()"); + + for (row=0; row < high; row++) + for (col=0; col < wide; col++) { + ur = r = fuji_width + (row-col)*step; + uc = c = (row+col)*step; + if (ur > height-2 || uc > width-2) continue; + fr = r - ur; + fc = c - uc; + pix = image + ur*width + uc; + for (i=0; i < colors; i++) + img[row*wide+col][i] = + (pix[ 0][i]*(1-fc) + pix[ 1][i]*fc) * (1-fr) + + (pix[width][i]*(1-fc) + pix[width+1][i]*fc) * fr; + } + free (image); + width = wide; + height = high; + image = img; + fuji_width = 0; +} + +void CLASS stretch() +{ + ushort newdim, (*img)[4], *pix0, *pix1; + int row, col, c; + double rc, frac; + + if (pixel_aspect == 1) return; + if (verbose) fprintf (stderr,_("Stretching the image...\n")); + if (pixel_aspect < 1) { + newdim = height / pixel_aspect + 0.5; + img = (ushort (*)[4]) calloc (width*newdim, sizeof *img); + merror (img, "stretch()"); + for (rc=row=0; row < newdim; row++, rc+=pixel_aspect) { + frac = rc - (c = rc); + pix0 = pix1 = image[c*width]; + if (c+1 < height) pix1 += width*4; + for (col=0; col < width; col++, pix0+=4, pix1+=4) + FORCC img[row*width+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5; + } + height = newdim; + } else { + newdim = width * pixel_aspect + 0.5; + img = (ushort (*)[4]) calloc (height*newdim, sizeof *img); + merror (img, "stretch()"); + for (rc=col=0; col < newdim; col++, rc+=1/pixel_aspect) { + frac = rc - (c = rc); + pix0 = pix1 = image[c]; + if (c+1 < width) pix1 += 4; + for (row=0; row < height; row++, pix0+=width*4, pix1+=width*4) + FORCC img[row*newdim+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5; + } + width = newdim; + } + free (image); + image = img; +} + +int CLASS flip_index (int row, int col) +{ + if (flip & 4) SWAP(row,col); + if (flip & 2) row = iheight - 1 - row; + if (flip & 1) col = iwidth - 1 - col; + return row * iwidth + col; +} + +void CLASS gamma_lut (uchar lut[0x10000]) +{ + int perc, c, val, total, i; + float white=0, r; + + perc = width * height * 0.01; /* 99th percentile white point */ + if (fuji_width) perc /= 2; + if (highlight && highlight != 2) perc = -1; + FORCC { + for (val=0x2000, total=0; --val > 32; ) + if ((total += histogram[c][val]) > perc) break; + if (white < val) white = val; + } + white *= 8 / bright; + for (i=0; i < 0x10000; i++) { + r = i / white; + val = 256 * ( !use_gamma ? r : +#ifdef SRGB_GAMMA + r <= 0.00304 ? r*12.92 : pow(r,2.5/6)*1.055-0.055 ); +#else + r <= 0.018 ? r*4.5 : pow(r,0.45)*1.099-0.099 ); +#endif + if (val > 255) val = 255; + lut[i] = val; + } +} + +struct tiff_tag { + ushort tag, type; + int count; + union { short s0, s1; int i0; } val; +}; + +struct tiff_hdr { + ushort order, magic; + int ifd; + ushort pad, ntag; + struct tiff_tag tag[22]; + int nextifd; + ushort pad2, nexif; + struct tiff_tag exif[4]; + short bps[4]; + int rat[10]; + char desc[512], make[64], model[64], soft[32], date[20], artist[64]; +}; + +void CLASS tiff_set (ushort *ntag, + ushort tag, ushort type, int count, int val) +{ + struct tiff_tag *tt; + + tt = (struct tiff_tag *)(ntag+1) + (*ntag)++; + tt->tag = tag; + tt->type = type; + tt->count = count; + if (type == 3 && count == 1) + tt->val.s0 = val; + else tt->val.i0 = val; +} + +#define TOFF(ptr) ((char *)(&(ptr)) - (char *)th) + +void CLASS tiff_head (struct tiff_hdr *th, int full) +{ + int c, psize=0; + struct tm *t; + + memset (th, 0, sizeof *th); + th->order = htonl(0x4d4d4949) >> 16; + th->magic = 42; + th->ifd = 10; + if (full) { + tiff_set (&th->ntag, 254, 4, 1, 0); + tiff_set (&th->ntag, 256, 4, 1, width); + tiff_set (&th->ntag, 257, 4, 1, height); + tiff_set (&th->ntag, 258, 3, colors, output_bps); + if (colors > 2) + th->tag[th->ntag-1].val.i0 = TOFF(th->bps); + FORC4 th->bps[c] = output_bps; + tiff_set (&th->ntag, 259, 3, 1, 1); + tiff_set (&th->ntag, 262, 3, 1, 1 + (colors > 1)); + } + tiff_set (&th->ntag, 270, 2, 512, TOFF(th->desc)); + tiff_set (&th->ntag, 271, 2, 64, TOFF(th->make)); + tiff_set (&th->ntag, 272, 2, 64, TOFF(th->model)); + if (full) { + if (oprof) psize = ntohl(oprof[0]); + tiff_set (&th->ntag, 273, 4, 1, sizeof *th + psize); + tiff_set (&th->ntag, 277, 3, 1, colors); + tiff_set (&th->ntag, 278, 4, 1, height); + tiff_set (&th->ntag, 279, 4, 1, height*width*colors*output_bps/8); + } else + tiff_set (&th->ntag, 274, 3, 1, "12435867"[flip]-'0'); + tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[6])); + tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[8])); + tiff_set (&th->ntag, 284, 3, 1, 1); + tiff_set (&th->ntag, 296, 3, 1, 2); + tiff_set (&th->ntag, 305, 2, 32, TOFF(th->soft)); + tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date)); + tiff_set (&th->ntag, 315, 2, 64, TOFF(th->artist)); + tiff_set (&th->ntag, 34665, 4, 1, TOFF(th->nexif)); + if (psize) tiff_set (&th->ntag, 34675, 7, psize, sizeof *th); + tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[0])); + tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[2])); + tiff_set (&th->nexif, 34855, 3, 1, iso_speed); + tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[4])); + for (c=0; c < 6; c++) th->rat[c] = 1000000; + th->rat[0] *= shutter; + th->rat[2] *= aperture; + th->rat[4] *= focal_len; + th->rat[6] = th->rat[8] = 300; + th->rat[7] = th->rat[9] = 1; + strncpy (th->desc, desc, 512); + strncpy (th->make, make, 64); + strncpy (th->model, model, 64); + strcpy (th->soft, "dcraw v"VERSION); + t = gmtime (×tamp); + sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d", + t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec); + strncpy (th->artist, artist, 64); +} + +void CLASS jpeg_thumb (FILE *tfp) +{ + char *thumb; + ushort exif[5]; + struct tiff_hdr th; + + thumb = (char *) malloc (thumb_length); + merror (thumb, "jpeg_thumb()"); + fread (thumb, 1, thumb_length, ifp); + fputc (0xff, tfp); + fputc (0xd8, tfp); + if (strcmp (thumb+6, "Exif")) { + memcpy (exif, "\xff\xe1 Exif\0\0", 10); + exif[1] = htons (8 + sizeof th); + fwrite (exif, 1, sizeof exif, tfp); + tiff_head (&th, 0); + fwrite (&th, 1, sizeof th, tfp); + } + fwrite (thumb+2, 1, thumb_length-2, tfp); + free (thumb); +} + +void CLASS write_ppm_tiff (FILE *ofp) +{ + struct tiff_hdr th; + uchar *ppm, lut[0x10000]; + ushort *ppm2; + int c, row, col, soff, rstep, cstep; + + iheight = height; + iwidth = width; + if (flip & 4) SWAP(height,width); + ppm = (uchar *) calloc (width, colors*output_bps/8); + ppm2 = (ushort *) ppm; + merror (ppm, "write_ppm_tiff()"); + if (output_tiff) { + tiff_head (&th, 1); + fwrite (&th, sizeof th, 1, ofp); + if (oprof) + fwrite (oprof, ntohl(oprof[0]), 1, ofp); + } else if (colors > 3) + fprintf (ofp, + "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n", + width, height, colors, (1 << output_bps)-1, cdesc); + else + fprintf (ofp, "P%d\n%d %d\n%d\n", + colors/2+5, width, height, (1 << output_bps)-1); + + if (output_bps == 8) gamma_lut (lut); + soff = flip_index (0, 0); + cstep = flip_index (0, 1) - soff; + rstep = flip_index (1, 0) - flip_index (0, width); + for (row=0; row < height; row++, soff += rstep) { + for (col=0; col < width; col++, soff += cstep) + if (output_bps == 8) + FORCC ppm [col*colors+c] = lut[image[soff][c]]; + else FORCC ppm2[col*colors+c] = image[soff][c]; + if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa) + swab (ppm2, ppm2, width*colors*2); + fwrite (ppm, colors*output_bps/8, width, ofp); + } + free (ppm); +} + +int CLASS main (int argc, char **argv) +{ + int arg, status=0, user_flip=-1, user_black=-1, user_qual=-1; + int timestamp_only=0, thumbnail_only=0, identify_only=0; + int use_fuji_rotate=1, write_to_stdout=0, quality, i, c; + char opm, opt, *ofname, *sp, *cp, *dark_frame=0; + const char *write_ext; + struct utimbuf ut; + FILE *ofp; +#ifndef NO_LCMS + char *cam_profile=0, *out_profile=0; +#endif + +#ifndef LOCALTIME + putenv ("TZ=UTC"); +#endif +#ifdef LOCALEDIR + setlocale (LC_CTYPE, ""); + setlocale (LC_MESSAGES, ""); + bindtextdomain ("dcraw", LOCALEDIR); + textdomain ("dcraw"); +#endif + + if (argc == 1) { + printf(_("\nRaw photo decoder \"dcraw\" v%s"), VERSION); + printf(_("\nby Dave Coffin, dcoffin a cybercom o net\n")); + printf(_("\nUsage: %s [OPTION]... [FILE]...\n\n"), argv[0]); + puts(_("-v Print verbose messages")); + puts(_("-c Write image data to standard output")); + puts(_("-e Extract embedded thumbnail image")); + puts(_("-i Identify files without decoding them")); + puts(_("-i -v Identify files and show metadata")); + puts(_("-z Change file dates to camera timestamp")); + puts(_("-w Use camera white balance, if possible")); + puts(_("-a Average the whole image for white balance")); + puts(_("-A Average a grey box for white balance")); + puts(_("-r Set custom white balance")); + puts(_("+M/-M Use/don't use an embedded color matrix")); + puts(_("-C Correct chromatic aberration")); + puts(_("-b Adjust brightness (default = 1.0)")); + puts(_("-n Set threshold for wavelet denoising")); + puts(_("-k Set black point")); + puts(_("-K Subtract dark frame (16-bit raw PGM)")); + puts(_("-H [0-9] Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)")); + puts(_("-t [0-7] Flip image (0=none, 3=180, 5=90CCW, 6=90CW)")); + puts(_("-o [0-5] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ)")); +#ifndef NO_LCMS + puts(_("-o Apply output ICC profile from file")); + puts(_("-p Apply camera ICC profile from file or \"embed\"")); +#endif + puts(_("-d Document mode (no color, no interpolation)")); + puts(_("-D Document mode without scaling (totally raw)")); + puts(_("-j Don't stretch or rotate raw pixels")); + puts(_("-q [0-3] Set the interpolation quality")); + puts(_("-h Half-size color image (twice as fast as \"-q 0\")")); + puts(_("-f Interpolate RGGB as four colors")); + puts(_("-m Apply a 3x3 median filter to R-G and B-G")); + puts(_("-s [0..N-1] Select one raw image or \"all\" from each file")); + puts(_("-4 Write 16-bit linear instead of 8-bit with gamma")); + puts(_("-T Write TIFF instead of PPM")); + puts(""); + return 1; + } + argv[argc] = ""; + for (arg=1; (((opm = argv[arg][0]) - 2) | 2) == '+'; ) { + opt = argv[arg++][1]; + if ((cp = strchr (sp="nbrktqmHAC", opt))) + for (i=0; i < "1141111142"[cp-sp]-'0'; i++) + if (!isdigit(argv[arg+i][0])) { + fprintf (stderr,_("Non-numeric argument to \"-%c\"\n"), opt); + return 1; + } + switch (opt) { + case 'n': threshold = atof(argv[arg++]); break; + case 'b': bright = atof(argv[arg++]); break; + case 'r': + FORC4 user_mul[c] = atof(argv[arg++]); break; + case 'C': aber[0] = 1 / atof(argv[arg++]); + aber[2] = 1 / atof(argv[arg++]); break; + case 'k': user_black = atoi(argv[arg++]); break; + case 't': user_flip = atoi(argv[arg++]); break; + case 'q': user_qual = atoi(argv[arg++]); break; + case 'm': med_passes = atoi(argv[arg++]); break; + case 'H': highlight = atoi(argv[arg++]); break; + case 's': + shot_select = abs(atoi(argv[arg])); + multi_out = !strcmp(argv[arg++],"all"); + break; + case 'o': + if (isdigit(argv[arg][0]) && !argv[arg][1]) + output_color = atoi(argv[arg++]); +#ifndef NO_LCMS + else out_profile = argv[arg++]; + break; + case 'p': cam_profile = argv[arg++]; +#endif + break; + case 'K': dark_frame = argv[arg++]; + break; + case 'z': timestamp_only = 1; break; + case 'e': thumbnail_only = 1; break; + case 'i': identify_only = 1; break; + case 'c': write_to_stdout = 1; break; + case 'v': verbose = 1; break; + case 'h': half_size = 1; /* "-h" implies "-f" */ + case 'f': four_color_rgb = 1; break; + case 'A': FORC4 greybox[c] = atoi(argv[arg++]); + case 'a': use_auto_wb = 1; break; + case 'w': use_camera_wb = 1; break; + case 'M': use_camera_matrix = (opm == '+'); break; + case 'D': + case 'd': document_mode = 1 + (opt == 'D'); + case 'j': use_fuji_rotate = 0; break; + case 'T': output_tiff = 1; break; + case '4': output_bps = 16; break; + default: + fprintf (stderr,_("Unknown option \"-%c\".\n"), opt); + return 1; + } + } + if (use_camera_matrix < 0) + use_camera_matrix = use_camera_wb; + if (arg == argc) { + fprintf (stderr,_("No files to process.\n")); + return 1; + } + if (write_to_stdout) { + if (isatty(1)) { + fprintf (stderr,_("Will not write an image to the terminal!\n")); + return 1; + } +#if defined(WIN32) || defined(DJGPP) || defined(__CYGWIN__) + if (setmode(1,O_BINARY) < 0) { + perror ("setmode()"); + return 1; + } +#endif + } + for ( ; arg < argc; arg++) { + status = 1; + image = 0; + oprof = 0; + meta_data = ofname = 0; + ofp = stdout; + if (setjmp (failure)) { + if (fileno(ifp) > 2) fclose(ifp); + if (fileno(ofp) > 2) fclose(ofp); + status = 1; + goto cleanup; + } + ifname = argv[arg]; + if (!(ifp = fopen (ifname, "rb"))) { + perror (ifname); + continue; + } + status = (identify(),!is_raw); + if (user_flip >= 0) + flip = user_flip; + switch ((flip+3600) % 360) { + case 270: flip = 5; break; + case 180: flip = 3; break; + case 90: flip = 6; + } + if (timestamp_only) { + if ((status = !timestamp)) + fprintf (stderr,_("%s has no timestamp.\n"), ifname); + else if (identify_only) + printf ("%10ld%10d %s\n", (long) timestamp, shot_order, ifname); + else { + if (verbose) + fprintf (stderr,_("%s time set to %d.\n"), ifname, (int) timestamp); + ut.actime = ut.modtime = timestamp; + utime (ifname, &ut); + } + goto next; + } + write_fun = &CLASS write_ppm_tiff; + if (thumbnail_only) { + if ((status = !thumb_offset)) { + fprintf (stderr,_("%s has no thumbnail.\n"), ifname); + goto next; + } else if (thumb_load_raw) { + load_raw = thumb_load_raw; + data_offset = thumb_offset; + height = thumb_height; + width = thumb_width; + filters = 0; + } else { + fseek (ifp, thumb_offset, SEEK_SET); + write_fun = write_thumb; + goto thumbnail; + } + } + if (load_raw == &CLASS kodak_ycbcr_load_raw) { + height += height & 1; + width += width & 1; + } + if (identify_only && verbose && make[0]) { + printf (_("\nFilename: %s\n"), ifname); + printf (_("Timestamp: %s"), ctime(×tamp)); + printf (_("Camera: %s %s\n"), make, model); + if (artist[0]) + printf (_("Owner: %s\n"), artist); + if (dng_version) { + printf (_("DNG Version: ")); + for (i=24; i >= 0; i -= 8) + printf ("%d%c", dng_version >> i & 255, i ? '.':'\n'); + } + printf (_("ISO speed: %d\n"), (int) iso_speed); + printf (_("Shutter: ")); + if (shutter > 0 && shutter < 1) + shutter = (printf ("1/"), 1 / shutter); + printf (_("%0.1f sec\n"), shutter); + printf (_("Aperture: f/%0.1f\n"), aperture); + printf (_("Focal length: %0.1f mm\n"), focal_len); + printf (_("Embedded ICC profile: %s\n"), profile_length ? _("yes"):_("no")); + printf (_("Number of raw images: %d\n"), is_raw); + if (pixel_aspect != 1) + printf (_("Pixel Aspect Ratio: %0.6f\n"), pixel_aspect); + if (thumb_offset) + printf (_("Thumb size: %4d x %d\n"), thumb_width, thumb_height); + printf (_("Full size: %4d x %d\n"), raw_width, raw_height); + } else if (!is_raw) + fprintf (stderr,_("Cannot decode file %s\n"), ifname); + if (!is_raw) goto next; + shrink = filters && + (half_size || threshold || aber[0] != 1 || aber[2] != 1); + iheight = (height + shrink) >> shrink; + iwidth = (width + shrink) >> shrink; + if (identify_only) { + if (verbose) { + if (use_fuji_rotate) { + if (fuji_width) { + fuji_width = (fuji_width - 1 + shrink) >> shrink; + iwidth = fuji_width / sqrt(0.5); + iheight = (iheight - fuji_width) / sqrt(0.5); + } else { + if (pixel_aspect < 1) iheight = iheight / pixel_aspect + 0.5; + if (pixel_aspect > 1) iwidth = iwidth * pixel_aspect + 0.5; + } + } + if (flip & 4) + SWAP(iheight,iwidth); + printf (_("Image size: %4d x %d\n"), width, height); + printf (_("Output size: %4d x %d\n"), iwidth, iheight); + printf (_("Raw colors: %d"), colors); + if (filters) { + printf (_("\nFilter pattern: ")); + if (!cdesc[3]) cdesc[3] = 'G'; + for (i=0; i < 16; i++) + putchar (cdesc[fc(i >> 1,i & 1)]); + } + printf (_("\nDaylight multipliers:")); + FORCC printf (" %f", pre_mul[c]); + if (cam_mul[0] > 0) { + printf (_("\nCamera multipliers:")); + FORC4 printf (" %f", cam_mul[c]); + } + putchar ('\n'); + } else + printf (_("%s is a %s %s image.\n"), ifname, make, model); +next: + fclose(ifp); + continue; + } + if (use_camera_matrix && cmatrix[0][0] > 0.25) { + memcpy (rgb_cam, cmatrix, sizeof cmatrix); + raw_color = 0; + } + image = (ushort (*)[4]) calloc (iheight*iwidth, sizeof *image); + merror (image, "main()"); + if (meta_length) { + meta_data = (char *) malloc (meta_length); + merror (meta_data, "main()"); + } + if (verbose) + fprintf (stderr,_("Loading %s %s image from %s ...\n"), + make, model, ifname); + if (shot_select >= is_raw) + fprintf (stderr,_("%s: \"-s %d\" requests a nonexistent image!\n"), + ifname, shot_select); + fseeko (ifp, data_offset, SEEK_SET); + (*load_raw)(); + if (zero_is_bad) remove_zeroes(); + bad_pixels(); + if (dark_frame) subtract (dark_frame); + quality = 2 + !fuji_width; + if (user_qual >= 0) quality = user_qual; + if (user_black >= 0) black = user_black; +#ifdef COLORCHECK + colorcheck(); +#endif + if (is_foveon && !document_mode) foveon_interpolate(); + if (!is_foveon && document_mode < 2) scale_colors(); + pre_interpolate(); + if (filters && !document_mode) { + if (quality == 0) + lin_interpolate(); + else if (quality == 1 || colors > 3) + vng_interpolate(); + else if (quality == 2) + ppg_interpolate(); + else ahd_interpolate(); + } + if (mix_green) + for (colors=3, i=0; i < height*width; i++) + image[i][1] = (image[i][1] + image[i][3]) >> 1; + if (!is_foveon && colors == 3) median_filter(); + if (!is_foveon && highlight == 2) blend_highlights(); + if (!is_foveon && highlight > 2) recover_highlights(); + if (use_fuji_rotate) fuji_rotate(); +#ifndef NO_LCMS + if (cam_profile) apply_profile (cam_profile, out_profile); +#endif + convert_to_rgb(); + if (use_fuji_rotate) stretch(); +thumbnail: + if (write_fun == &CLASS jpeg_thumb) + write_ext = ".jpg"; + else if (output_tiff && write_fun == &CLASS write_ppm_tiff) + write_ext = ".tiff"; + else + write_ext = ".pgm\0.ppm\0.ppm\0.pam" + colors*5-5; + ofname = (char *) malloc (strlen(ifname) + 64); + merror (ofname, "main()"); + if (write_to_stdout) + strcpy (ofname,_("standard output")); + else { + strcpy (ofname, ifname); + if ((cp = strrchr (ofname, '.'))) *cp = 0; + if (multi_out) + sprintf (ofname+strlen(ofname), "_%0*d", + snprintf(0,0,"%d",is_raw-1), shot_select); + if (thumbnail_only) + strcat (ofname, ".thumb"); + strcat (ofname, write_ext); + ofp = fopen (ofname, "wb"); + if (!ofp) { + status = 1; + perror (ofname); + goto cleanup; + } + } + if (verbose) + fprintf (stderr,_("Writing data to %s ...\n"), ofname); + (*write_fun)(ofp); + fclose(ifp); + if (ofp != stdout) fclose(ofp); +cleanup: + if (meta_data) free (meta_data); + if (ofname) free (ofname); + if (oprof) free (oprof); + if (image) free (image); + if (multi_out) { + if (++shot_select < is_raw) arg--; + else shot_select = 0; + } + } + return status; +} diff --git a/kernel/kls_camera/fmt_codec_pnm.cpp b/kernel/kls_camera/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_camera/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_camera/fmt_codec_pnm_defs.h b/kernel/kls_camera/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_camera/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_camera/ksquirrel-libs-camera2ppm.in b/kernel/kls_camera/ksquirrel-libs-camera2ppm.in new file mode 100644 index 0000000..5ee4063 --- /dev/null +++ b/kernel/kls_camera/ksquirrel-libs-camera2ppm.in @@ -0,0 +1,20 @@ +#!/bin/sh + +kls_camera_i="" +kls_camera_o="" +kls_camera_bin="" +kls_camera_params="" + +while [ "$1" ] ; do + + case "$1" in + "--input") kls_camera_i="$2" shift ;; + "--output") kls_camera_o="$2" shift ;; + "--binary") kls_camera_bin="$2" shift ;; + *) kls_camera_params="$kls_camera_params $1" ;; + esac + +shift +done + +$kls_camera_bin $kls_camera_params "$kls_camera_i" > "$kls_camera_o" \ No newline at end of file diff --git a/kernel/kls_camera/libkls_camera.so.ui b/kernel/kls_camera/libkls_camera.so.ui new file mode 100644 index 0000000..645f30b --- /dev/null +++ b/kernel/kls_camera/libkls_camera.so.ui @@ -0,0 +1,1023 @@ + +Form1 + + + Form1 + + + + 0 + 0 + 635 + 551 + + + + Form1 + + + + unnamed + + + 0 + + + + camera_white + + + Use camera white balance, if possible + + + + + interpolate_rggb + + + Interpolate RGGB as four colors + + + + + dontstretch + + + Don't stretch or rotate raw pixels + + + + + camera_date + + + Change file dates to camera timestamp + + + + + icc_cam + + + Try to use the ICC profile embedded in the photo + + + + + half_size + + + Half-size color image + + + + + automatic_white + + + Use automatic white balance + + + + + document_mode + + + Document mode (no color, no interpolation) + + + + + layout7 + + + + unnamed + + + + line1_4 + + + HLine + + + Sunken + + + Horizontal + + + + + no_black + + + no + + + 255 + + + -1 + + + -1 + + + + + textLabel2_5 + + + <b>Set black point</b> + + + AlignVCenter + + + + + black + + + -1 + + + 255 + + + -1 + + + Horizontal + + + Below + + + 10 + + + + + + + layout6 + + + + unnamed + + + + brightness + + + 255 + + + 1 + + + 1 + + + + + no_brightness + + + 1 + + + 255 + + + 1 + + + Horizontal + + + Below + + + 10 + + + + + line1_2 + + + HLine + + + Sunken + + + Horizontal + + + + + textLabel2_2 + + + <b>Adjust brightness</b> + + + AlignVCenter + + + + + + + layout5 + + + + unnamed + + + + no_different + + + # + + + 99 + + + 0 + + + 0 + + + + + line1_3 + + + HLine + + + Sunken + + + Horizontal + + + + + different + + + 0 + + + 99 + + + 0 + + + Horizontal + + + Below + + + 5 + + + + + textLabel2_4 + + + <b>Select a different raw image from the same file</b> + + + AlignVCenter + + + + + + + layout4 + + + + unnamed + + + + threshold + + + 99 + + + 1000 + + + 99 + + + Horizontal + + + Below + + + 75 + + + + + no_threshold + + + no + + + 1000 + + + 99 + + + + + textLabel2_2_2 + + + <b>Threshold for wavelet denoising</b> + + + AlignVCenter + + + + + line1_2_2 + + + HLine + + + Sunken + + + Horizontal + + + + + + + layout3 + + + + unnamed + + + + highlights + + + 0 + + + 9 + + + 0 + + + Horizontal + + + Below + + + 1 + + + + + no_highlights + + + 9 + + + 0 + + + 0 + + + + + line1_2_2_2 + + + HLine + + + Sunken + + + Horizontal + + + + + no_widgetStack + + + + 5 + 0 + 0 + 0 + + + + + WStackPage + + + 0 + + + + unnamed + + + 0 + + + + textLabel1 + + + Clip all highlights to solid white + + + AlignVCenter + + + + + + + WStackPage + + + 1 + + + + unnamed + + + 0 + + + + textLabel2 + + + Leave highlights unclipped in various shades of pink + + + AlignVCenter + + + + + + + WStackPage + + + 2 + + + + unnamed + + + 0 + + + + textLabel3 + + + Reconstruct highlights: <b>favor whites 1</b> + + + AlignVCenter|AlignLeft + + + + + + + WStackPage + + + 3 + + + + unnamed + + + 0 + + + + textLabel3_2 + + + Reconstruct highlights: <b><font color="magenta">favor whites 2</font></b> + + + AlignVCenter|AlignLeft + + + + + + + WStackPage + + + 4 + + + + unnamed + + + 0 + + + + textLabel3_3 + + + Reconstruct highlights: <b><font color="red">favor whites 3</font></b> + + + AlignVCenter|AlignLeft + + + + + + + WStackPage + + + 5 + + + + unnamed + + + 0 + + + + textLabel3_4 + + + <b>compromise</b> + + + WordBreak|AlignCenter + + + + + + + WStackPage + + + 6 + + + + unnamed + + + 0 + + + + textLabel4 + + + Reconstruct highlights: <b>favor colors 1</b> + + + AlignVCenter|AlignRight + + + + + + + WStackPage + + + 7 + + + + unnamed + + + 0 + + + + textLabel4_2 + + + Reconstruct highlights: <b><font color="green">favor colors 2</font></b> + + + AlignVCenter|AlignRight + + + + + + + WStackPage + + + 8 + + + + unnamed + + + 0 + + + + textLabel4_3 + + + Reconstruct highlights: <b><font color="magenta">favor colors 3</font></b> + + + AlignVCenter|AlignRight + + + + + + + WStackPage + + + 9 + + + + unnamed + + + 0 + + + + textLabel4_4 + + + Reconstruct highlights: <b><font color="red">favor colors 4</font></b> + + + AlignVCenter|AlignRight + + + + + + + + textLabel2_2_2_2 + + + <b>Highlights</b> + + + AlignVCenter + + + + + + + quick + + + Interpolation + + + + unnamed + + + 9 + + + 1 + + + + radioButton1 + + + No interpolation + + + + + radioButton2 + + + Low-quality bilinear interpolation + + + 1 + + + + + radioButton3 + + + Variable Number of Gradients interpolation + + + + + radioButton4 + + + Adaptive Homogeneity-Directed interpolation + + + + + + + layout10 + + + + unnamed + + + 0 + + + + textLabel2_3_2 + + + <b>Apply camera ICC profile from file</b> + + + AlignVCenter + + + + + icc_file + + + *.icc *.icm + + + + + + + flipping + + + Flipping + + + + unnamed + + + 9 + + + 1 + + + + radioButton7 + + + 90CCW + + + 5 + + + + + radioButton6 + + + 180 + + + 3 + + + + + radioButton5 + + + None + + + 1 + + + + + radioButton9 + + + Camera settings + + + 0 + + + + + radioButton8 + + + 90CW + + + 6 + + + + + + + embedded_cm + + + Use an embedded color matrix + + + + + spacer5 + + + Vertical + + + Expanding + + + + 16 + 110 + + + + + + + + + + no_brightness + valueChanged(int) + brightness + setValue(int) + + + brightness + valueChanged(int) + no_brightness + setValue(int) + + + different + valueChanged(int) + no_different + setValue(int) + + + no_different + valueChanged(int) + different + setValue(int) + + + black + valueChanged(int) + no_black + setValue(int) + + + no_black + valueChanged(int) + black + setValue(int) + + + threshold + valueChanged(int) + no_threshold + setValue(int) + + + no_threshold + valueChanged(int) + threshold + setValue(int) + + + highlights + valueChanged(int) + no_highlights + setValue(int) + + + no_highlights + valueChanged(int) + highlights + setValue(int) + + + highlights + valueChanged(int) + no_widgetStack + raiseWidget(int) + + + icc_cam + toggled(bool) + icc_file + setDisabled(bool) + + + + automatic_white + camera_white + document_mode + half_size + interpolate_rggb + camera_date + dontstretch + black + no_black + threshold + no_brightness + brightness + different + no_different + + + + kurlrequester.h + klineedit.h + kpushbutton.h + + diff --git a/kernel/kls_cut/Makefile.am b/kernel/kls_cut/Makefile.am new file mode 100644 index 0000000..1137f5a --- /dev/null +++ b/kernel/kls_cut/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_cut.la + +libkls_cut_la_SOURCES = fmt_codec_cut.cpp fmt_codec_cut_defs.h + +libkls_cut_la_LDFLAGS = ${SQ_RELEASE} + +libkls_cut_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_cut/fmt_codec_cut.cpp b/kernel/kls_cut/fmt_codec_cut.cpp new file mode 100644 index 0000000..803c4e4 --- /dev/null +++ b/kernel/kls_cut/fmt_codec_cut.cpp @@ -0,0 +1,173 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_cut_defs.h" +#include "fmt_codec_cut.h" + +#include "../xpm/codec_cut.xpm" + +/* + * + * The Dr. Halo file format is a device-independent interchange format used for + * transporting image data from one hardware environment or operating system to + * another. This format is associated with the HALO Image File Format + * Library. + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{ + for(s32 i = 0;i < 256;i++) + memset(pal+i, i, sizeof(RGB)); +} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.1.1"; + o->name = "Dr. Halo CUT"; + o->filter = "*.cut "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-cut"; + o->pixmap = codec_cut; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + s16 width, height; + s32 dummy; + + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + if(!frs.readK(&width, sizeof(s16))) return SQE_R_BADFILE; + if(!frs.readK(&height, sizeof(s16))) return SQE_R_BADFILE; + if(!frs.readK(&dummy, sizeof(s32))) return SQE_R_BADFILE; + + image.w = width; + image.h = height; + image.bpp = 8; + + image.compression = "RLE"; + image.colorspace = "Color indexed"; + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + s32 i = 0, j; + u8 count, run, c; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + while(i < im->w) + { + if(!frs.readK(&count, 1)) return SQE_R_BADFILE; + + if(count == 0) + { + frs.readK(&c, 1); + + if(!frs.readK(&c, 1)) return SQE_R_BADFILE; + + continue; // ugly hack + } + else if(count & 0x80) + { + count &= ~(0x80); + + if(!frs.readK(&run, 1)) return SQE_R_BADFILE; + + for(j = 0;j < count;j++) + { + memcpy(scan+i, pal+run, sizeof(RGB)); + i++; + } + } + else + { + for(j = 0;j < count;j++) + { + if(!frs.readK(&run, 1)) return SQE_R_BADFILE; + + memcpy(scan+i, pal+run, sizeof(RGB)); + + i++; + } + } + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_cut/fmt_codec_cut_defs.h b/kernel/kls_cut/fmt_codec_cut_defs.h new file mode 100644 index 0000000..3caac6e --- /dev/null +++ b/kernel/kls_cut/fmt_codec_cut_defs.h @@ -0,0 +1,25 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_cut +#define KSQUIRREL_READ_IMAGE_cut + +#endif diff --git a/kernel/kls_dds/Makefile.am b/kernel/kls_dds/Makefile.am new file mode 100644 index 0000000..753dfb6 --- /dev/null +++ b/kernel/kls_dds/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_dds.la + +libkls_dds_la_SOURCES = fmt_codec_dds.cpp fmt_codec_dds_defs.h dds.cpp + +libkls_dds_la_LDFLAGS = ${SQ_RELEASE} + +libkls_dds_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_dds/dds.cpp b/kernel/kls_dds/dds.cpp new file mode 100644 index 0000000..c5551f0 --- /dev/null +++ b/kernel/kls_dds/dds.cpp @@ -0,0 +1,1066 @@ +/* + * (C) 2007 Dmitry Baryshev, KSquirrel project + */ + +/* This file is part of the KDE project + Copyright (C) 2003 Ignacio Casta�o + + This program is free software; you can redistribute it and/or + modify it under the terms of the Lesser GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + Almost all this code is based on nVidia's DDS-loading example + and the DevIl's source code by Denton Woods. +*/ + +/* this code supports: + * reading: + * rgb and dxt dds files + * cubemap dds files + * volume dds files -- TODO + * writing: + * rgb dds files only -- TODO + */ + +#include // sqrtf +#include +#include +#include +#include + +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fmt_defs.h" + +#include "dds.h" + +#ifndef __USE_ISOC99 +#define sqrtf(x) ((float)sqrt(x)) +#endif + +typedef u32 uint; +typedef u16 ushort; +typedef u8 uchar; + +typedef RGBA* RGBAP; + +namespace { // Private. + +static bool MALLOC_ROWS(RGBAP **A, const int RB, const int H) +{ + *A = (RGBAP *)malloc(H * sizeof(RGBA*)); + + if(!*A) + return false; + + for(s32 row = 0; row < H; row++) + (*A)[row] = 0; + + for(s32 row = 0; row < (s32)H; row++) + { + (*A)[row] = (RGBA *)malloc(RB); + + if(!(*A)[row]) + return false; + + memset((*A)[row], 0, RB); + } + + return true; +} +/* +static void FREE_ROWS(RGBAP **A, const int H) +{ + if(*A) + { + for(s32 i = 0;i < H;i++) + { + if((*A)[i]) + free((*A)[i]); + } + + free(*A); + *A = 0; + } +} +*/ +#if !defined(MAKEFOURCC) +# define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + (uint(uchar(ch0)) | (uint(uchar(ch1)) << 8) | \ + (uint(uchar(ch2)) << 16) | (uint(uchar(ch3)) << 24 )) +#endif + +//#ifdef max +#undef max +#define max(a,b) ((a)>(b)?(a):(b)) +//#endif + +#define HORIZONTAL 1 +#define VERTICAL 2 +#define CUBE_LAYOUT HORIZONTAL + + struct Color8888 + { + uchar r, g, b, a; + }; + + union Color565 + { + struct { + ushort b : 5; + ushort g : 6; + ushort r : 5; + } c; + ushort u; + }; + + union Color1555 { + struct { + ushort b : 5; + ushort g : 5; + ushort r : 5; + ushort a : 1; + } c; + ushort u; + }; + + union Color4444 { + struct { + ushort b : 4; + ushort g : 4; + ushort r : 4; + ushort a : 4; + } c; + ushort u; + }; + + + static const uint FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' '); + static const uint FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1'); + static const uint FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2'); + static const uint FOURCC_DXT3 = MAKEFOURCC('D', 'X', 'T', '3'); + static const uint FOURCC_DXT4 = MAKEFOURCC('D', 'X', 'T', '4'); + static const uint FOURCC_DXT5 = MAKEFOURCC('D', 'X', 'T', '5'); + static const uint FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B'); + static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2'); + + static const uint DDSD_CAPS = 0x00000001l; + static const uint DDSD_PIXELFORMAT = 0x00001000l; + static const uint DDSD_WIDTH = 0x00000004l; + static const uint DDSD_HEIGHT = 0x00000002l; + static const uint DDSD_PITCH = 0x00000008l; + + static const uint DDSCAPS_TEXTURE = 0x00001000l; + static const uint DDSCAPS2_VOLUME = 0x00200000l; + static const uint DDSCAPS2_CUBEMAP = 0x00000200l; + + static const uint DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400l; + static const uint DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800l; + static const uint DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000l; + static const uint DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000l; + static const uint DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000l; + static const uint DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000l; + + static const uint DDPF_RGB = 0x00000040l; + static const uint DDPF_FOURCC = 0x00000004l; + static const uint DDPF_ALPHAPIXELS = 0x00000001l; + + enum DDSType { + DDS_A8R8G8B8 = 0, + DDS_A1R5G5B5 = 1, + DDS_A4R4G4B4 = 2, + DDS_R8G8B8 = 3, + DDS_R5G6B5 = 4, + DDS_DXT1 = 5, + DDS_DXT2 = 6, + DDS_DXT3 = 7, + DDS_DXT4 = 8, + DDS_DXT5 = 9, + DDS_RXGB = 10, + DDS_ATI2 = 11, + DDS_UNKNOWN + }; + + + struct DDSPixelFormat { + uint size; + uint flags; + uint fourcc; + uint bitcount; + uint rmask; + uint gmask; + uint bmask; + uint amask; + }; + + static ifstreamK & operator>> ( ifstreamK & s, DDSPixelFormat & pf ) + { + s.readK(&pf.size, sizeof(pf.size)); + s.readK(&pf.flags, sizeof(pf.flags)); + s.readK(&pf.fourcc, sizeof(pf.fourcc)); + s.readK(&pf.bitcount, sizeof(pf.bitcount)); + s.readK(&pf.rmask, sizeof(pf.rmask)); + s.readK(&pf.gmask, sizeof(pf.gmask)); + s.readK(&pf.bmask, sizeof(pf.bmask)); + s.readK(&pf.amask, sizeof(pf.amask)); + + return s; + } + + struct DDSCaps { + uint caps1; + uint caps2; + uint caps3; + uint caps4; + }; + + static ifstreamK & operator>> ( ifstreamK & s, DDSCaps & caps ) + { + s.readK(&caps.caps1, sizeof(caps.caps1)); + s.readK(&caps.caps2, sizeof(caps.caps2)); + s.readK(&caps.caps3, sizeof(caps.caps3)); + s.readK(&caps.caps4, sizeof(caps.caps4)); + + return s; + } + + struct DDSHeader { + uint size; + uint flags; + uint height; + uint width; + uint pitch; + uint depth; + uint mipmapcount; + uint reserved[11]; + DDSPixelFormat pf; + DDSCaps caps; + uint notused; + }; + + static ifstreamK & operator>> ( ifstreamK & s, DDSHeader & header ) + { + s.readK(&header.size, sizeof(header.size)); + s.readK(&header.flags, sizeof(header.flags)); + s.readK(&header.height, sizeof(header.height)); + s.readK(&header.width, sizeof(header.width)); + s.readK(&header.pitch, sizeof(header.pitch)); + s.readK(&header.depth, sizeof(header.depth)); + s.readK(&header.mipmapcount, sizeof(header.mipmapcount)); + + for( int i = 0; i < 11; i++ ) + { + s.readK(&header.reserved[i], sizeof(header.reserved[i])); + } + + s >> header.pf; + s >> header.caps; + + s.readK(&header.notused, sizeof(header.notused)); + + return s; + } + + static bool IsValid( const DDSHeader & header ) + { + if( header.size != 124 || !header.width || !header.height) { + return false; + } + + const uint required = (DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT); + + if( (header.flags & required) != required ) { + return false; + } + if( header.pf.size != 32 ) { + return false; + } + if( !(header.caps.caps1 & DDSCAPS_TEXTURE) ) { + return false; + } + return true; + } + + // Get supported type. We currently support 10 different types. + static DDSType GetType( const DDSHeader & header ) + { + if( header.pf.flags & DDPF_RGB ) { + if( header.pf.flags & DDPF_ALPHAPIXELS ) { + switch( header.pf.bitcount ) { + case 16: + return (header.pf.amask == 0x7000) ? DDS_A1R5G5B5 : DDS_A4R4G4B4; + case 32: + return DDS_A8R8G8B8; + } + } + else { + switch( header.pf.bitcount ) { + case 16: + return DDS_R5G6B5; + case 24: + return DDS_R8G8B8; + } + } + } + else if( header.pf.flags & DDPF_FOURCC ) { + switch( header.pf.fourcc ) { + case FOURCC_DXT1: + return DDS_DXT1; + case FOURCC_DXT2: + return DDS_DXT2; + case FOURCC_DXT3: + return DDS_DXT3; + case FOURCC_DXT4: + return DDS_DXT4; + case FOURCC_DXT5: + return DDS_DXT5; + case FOURCC_RXGB: + return DDS_RXGB; + case FOURCC_ATI2: + return DDS_ATI2; + } + } + return DDS_UNKNOWN; + } + + static bool IsCubeMap( const DDSHeader & header ) + { + return header.caps.caps2 & DDSCAPS2_CUBEMAP; + } + + static bool IsSupported( const DDSHeader & header ) + { + if( header.caps.caps2 & DDSCAPS2_VOLUME ) { + return false; + } + if( GetType(header) == DDS_UNKNOWN ) { + return false; + } + return true; + } + + static bool LoadA8R8G8B8( ifstreamK & s, const DDSHeader & header, RGBA **img) + { + const uint w = header.width; + const uint h = header.height; + + for( uint y = 0; y < h; y++ ) { + RGBA *scanline = img[y]; + for( uint x = 0; x < w; x++ ) { + uchar r, g, b, a; + + s.readK(&b, sizeof(b)); + s.readK(&g, sizeof(g)); + s.readK(&r, sizeof(r)); + s.readK(&a, sizeof(a)); + + scanline[x] = RGBA(r, g, b, a); + } + } + + return true; + } + + static bool LoadR8G8B8( ifstreamK & s, const DDSHeader & header, RGBA **img) + { + const uint w = header.width; + const uint h = header.height; + + for( uint y = 0; y < h; y++ ) { + RGBA * scanline = img[y]; + for( uint x = 0; x < w; x++ ) + { + uchar r, g, b; + + s.readK(&b, sizeof(b)); + s.readK(&g, sizeof(g)); + s.readK(&r, sizeof(r)); + + scanline[x] = RGBA(r, g, b, 255); + } + } + + return true; + } + + static bool LoadA1R5G5B5( ifstreamK & s, const DDSHeader & header, RGBA **img ) + { + const uint w = header.width; + const uint h = header.height; + + for( uint y = 0; y < h; y++ ) { + RGBA * scanline = img[y]; + for( uint x = 0; x < w; x++ ) { + Color1555 color; + s.readK(&color.u, sizeof(color.u)); + uchar a = (color.c.a != 0) ? 0xFF : 0; + uchar r = (color.c.r << 3) | (color.c.r >> 2); + uchar g = (color.c.g << 3) | (color.c.g >> 2); + uchar b = (color.c.b << 3) | (color.c.b >> 2); + scanline[x] = RGBA(r, g, b, a); + } + } + + return true; + } + + static bool LoadA4R4G4B4( ifstreamK & s, const DDSHeader & header, RGBA **img) + { + const uint w = header.width; + const uint h = header.height; + + for( uint y = 0; y < h; y++ ) { + RGBA * scanline = img[y]; + for( uint x = 0; x < w; x++ ) { + Color4444 color; + s.readK(&color.u, sizeof(color.u)); + uchar a = (color.c.a << 4) | color.c.a; + uchar r = (color.c.r << 4) | color.c.r; + uchar g = (color.c.g << 4) | color.c.g; + uchar b = (color.c.b << 4) | color.c.b; + scanline[x] = RGBA(r, g, b, a); + } + } + + return true; + } + + static bool LoadR5G6B5( ifstreamK & s, const DDSHeader & header, RGBA **img) + { + const uint w = header.width; + const uint h = header.height; + + for( uint y = 0; y < h; y++ ) { + RGBA * scanline = img[y]; + for( uint x = 0; x < w; x++ ) { + Color565 color; + s.readK(&color.u, sizeof(color.u)); + uchar r = (color.c.r << 3) | (color.c.r >> 2); + uchar g = (color.c.g << 2) | (color.c.g >> 4); + uchar b = (color.c.b << 3) | (color.c.b >> 2); + scanline[x] = RGBA(r, g, b, 255); + } + } + + return true; + } + + static ifstreamK & operator>> ( ifstreamK & s, Color565 & c ) + { + s.readK(&c.u, sizeof(c.u)); + + return s; + } + + struct BlockDXT + { + Color565 col0; + Color565 col1; + uchar row[4]; + + void GetColors( Color8888 color_array[4] ) + { + color_array[0].r = (col0.c.r << 3) | (col0.c.r >> 2); + color_array[0].g = (col0.c.g << 2) | (col0.c.g >> 4); + color_array[0].b = (col0.c.b << 3) | (col0.c.b >> 2); + color_array[0].a = 0xFF; + + color_array[1].r = (col1.c.r << 3) | (col1.c.r >> 2); + color_array[1].g = (col1.c.g << 2) | (col1.c.g >> 4); + color_array[1].b = (col1.c.b << 3) | (col1.c.b >> 2); + color_array[1].a = 0xFF; + + if( col0.u > col1.u ) { + // Four-color block: derive the other two colors. + color_array[2].r = (2 * color_array[0].r + color_array[1].r) / 3; + color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3; + color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3; + color_array[2].a = 0xFF; + + color_array[3].r = (2 * color_array[1].r + color_array[0].r) / 3; + color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3; + color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3; + color_array[3].a = 0xFF; + } + else { + // Three-color block: derive the other color. + color_array[2].r = (color_array[0].r + color_array[1].r) / 2; + color_array[2].g = (color_array[0].g + color_array[1].g) / 2; + color_array[2].b = (color_array[0].b + color_array[1].b) / 2; + color_array[2].a = 0xFF; + + // Set all components to 0 to match DXT specs. + color_array[3].r = 0x00; // color_array[2].r; + color_array[3].g = 0x00; // color_array[2].g; + color_array[3].b = 0x00; // color_array[2].b; + color_array[3].a = 0x00; + } + } + }; + + static ifstreamK & operator>> ( ifstreamK & s, BlockDXT & c ) + { + s >> c.col0 >> c.col1; + + s.readK(&c.row[0], sizeof(uchar)); + s.readK(&c.row[1], sizeof(uchar)); + s.readK(&c.row[2], sizeof(uchar)); + s.readK(&c.row[3], sizeof(uchar)); + + return s; + } + + struct BlockDXTAlphaExplicit { + ushort row[4]; + }; + + static ifstreamK & operator>> ( ifstreamK & s, BlockDXTAlphaExplicit & c ) + { + s.readK(&c.row[0], sizeof(ushort)); + s.readK(&c.row[1], sizeof(ushort)); + s.readK(&c.row[2], sizeof(ushort)); + s.readK(&c.row[3], sizeof(ushort)); + + return s; + } + + struct BlockDXTAlphaLinear { + uchar alpha0; + uchar alpha1; + uchar bits[6]; + + void GetAlphas( uchar alpha_array[8] ) + { + alpha_array[0] = alpha0; + alpha_array[1] = alpha1; + + // 8-alpha or 6-alpha block? + if( alpha_array[0] > alpha_array[1] ) + { + // 8-alpha block: derive the other 6 alphas. + // 000 = alpha_0, 001 = alpha_1, others are interpolated + + alpha_array[2] = ( 6 * alpha0 + alpha1) / 7; // bit code 010 + alpha_array[3] = ( 5 * alpha0 + 2 * alpha1) / 7; // Bit code 011 + alpha_array[4] = ( 4 * alpha0 + 3 * alpha1) / 7; // Bit code 100 + alpha_array[5] = ( 3 * alpha0 + 4 * alpha1) / 7; // Bit code 101 + alpha_array[6] = ( 2 * alpha0 + 5 * alpha1) / 7; // Bit code 110 + alpha_array[7] = ( alpha0 + 6 * alpha1) / 7; // Bit code 111 + } + else + { + // 6-alpha block: derive the other alphas. + // 000 = alpha_0, 001 = alpha_1, others are interpolated + + alpha_array[2] = (4 * alpha0 + alpha1) / 5; // Bit code 010 + alpha_array[3] = (3 * alpha0 + 2 * alpha1) / 5; // Bit code 011 + alpha_array[4] = (2 * alpha0 + 3 * alpha1) / 5; // Bit code 100 + alpha_array[5] = ( alpha0 + 4 * alpha1) / 5; // Bit code 101 + alpha_array[6] = 0x00; // Bit code 110 + alpha_array[7] = 0xFF; // Bit code 111 + } + } + + void GetBits( uchar bit_array[16] ) + { + uint b = (uint &) bits[0]; + bit_array[0] = uchar(b & 0x07); b >>= 3; + bit_array[1] = uchar(b & 0x07); b >>= 3; + bit_array[2] = uchar(b & 0x07); b >>= 3; + bit_array[3] = uchar(b & 0x07); b >>= 3; + bit_array[4] = uchar(b & 0x07); b >>= 3; + bit_array[5] = uchar(b & 0x07); b >>= 3; + bit_array[6] = uchar(b & 0x07); b >>= 3; + bit_array[7] = uchar(b & 0x07); b >>= 3; + + b = (uint &) bits[3]; + bit_array[8] = uchar(b & 0x07); b >>= 3; + bit_array[9] = uchar(b & 0x07); b >>= 3; + bit_array[10] = uchar(b & 0x07); b >>= 3; + bit_array[11] = uchar(b & 0x07); b >>= 3; + bit_array[12] = uchar(b & 0x07); b >>= 3; + bit_array[13] = uchar(b & 0x07); b >>= 3; + bit_array[14] = uchar(b & 0x07); b >>= 3; + bit_array[15] = uchar(b & 0x07); b >>= 3; + } + }; + + static ifstreamK & operator>> ( ifstreamK & s, BlockDXTAlphaLinear & c ) + { + s.readK(&c.alpha0, sizeof(c.alpha0)); + s.readK(&c.alpha1, sizeof(c.alpha1)); + + s.readK(&c.bits[0], sizeof(uchar)); + s.readK(&c.bits[1], sizeof(uchar)); + s.readK(&c.bits[2], sizeof(uchar)); + s.readK(&c.bits[3], sizeof(uchar)); + s.readK(&c.bits[4], sizeof(uchar)); + s.readK(&c.bits[5], sizeof(uchar)); + + return s; + } + + static bool LoadDXT1( ifstreamK & s, const DDSHeader & header, RGBA **img) + { + const uint w = header.width; + const uint h = header.height; + + BlockDXT block; + RGBA * scanline[4]; + + for( uint y = 0; y < h; y += 4 ) { + for( uint j = 0; j < 4; j++ ) { + scanline[j] = img[y + j]; + } + + for( uint x = 0; x < w; x += 4 ) { + + // Read 64bit color block. + s >> block; + + // Decode color block. + Color8888 color_array[4]; + block.GetColors(color_array); + + // bit masks = 00000011, 00001100, 00110000, 11000000 + const uint masks[4] = { 3, 3<<2, 3<<4, 3<<6 }; + const int shift[4] = { 0, 2, 4, 6 }; + + // Write color block. + for( uint j = 0; j < 4; j++ ) { + for( uint i = 0; i < 4; i++ ) { + /*if( img.valid( x+i, y+j ) ) */{ + + uint idx = (block.row[j] & masks[i]) >> shift[i]; + scanline[j][x+i] = RGBA(color_array[idx].r, color_array[idx].g, color_array[idx].b, color_array[idx].a); + } + } + } + } + } + + return true; + } + + static bool LoadDXT3( ifstreamK & s, const DDSHeader & header, RGBA **img) + { + const uint w = header.width; + const uint h = header.height; + + BlockDXT block; + BlockDXTAlphaExplicit alpha; + RGBA * scanline[4]; + + for( uint y = 0; y < h; y += 4 ) { + for( uint j = 0; j < 4; j++ ) { + scanline[j] = img[y + j]; + } + for( uint x = 0; x < w; x += 4 ) { + + // Read 128bit color block. + s >> alpha; + s >> block; + + // Decode color block. + Color8888 color_array[4]; + block.GetColors(color_array); + + // bit masks = 00000011, 00001100, 00110000, 11000000 + const uint masks[4] = { 3, 3<<2, 3<<4, 3<<6 }; + const int shift[4] = { 0, 2, 4, 6 }; + + // Write color block. + for( uint j = 0; j < 4; j++ ) { + ushort a = alpha.row[j]; + for( uint i = 0; i < 4; i++ ) { + /*if( img.valid( x+i, y+j ) ) */{ + uint idx = (block.row[j] & masks[i]) >> shift[i]; + color_array[idx].a = a & 0x0f; + color_array[idx].a = color_array[idx].a | (color_array[idx].a << 4); + scanline[j][x+i] = RGBA(color_array[idx].r, color_array[idx].g, color_array[idx].b, color_array[idx].a); + } + a >>= 4; + } + } + } + } + return true; + } + + static bool LoadDXT2( ifstreamK & s, const DDSHeader & header, RGBA **img) + { + if( !LoadDXT3(s, header, img) ) return false; + //UndoPremultiplyAlpha(img); + return true; + } + + static bool LoadDXT5( ifstreamK & s, const DDSHeader & header, RGBA **img) + { + const uint w = header.width; + const uint h = header.height; + + BlockDXT block; + BlockDXTAlphaLinear alpha; + RGBA * scanline[4]; + + for( uint y = 0; y < h; y += 4 ) { + for( uint j = 0; j < 4; j++ ) { + scanline[j] = img[y + j]; + } + for( uint x = 0; x < w; x += 4 ) { + + // Read 128bit color block. + s >> alpha; + s >> block; + + // Decode color block. + Color8888 color_array[4]; + block.GetColors(color_array); + + uchar alpha_array[8]; + alpha.GetAlphas(alpha_array); + + uchar bit_array[16]; + alpha.GetBits(bit_array); + + // bit masks = 00000011, 00001100, 00110000, 11000000 + const uint masks[4] = { 3, 3<<2, 3<<4, 3<<6 }; + const int shift[4] = { 0, 2, 4, 6 }; + + // Write color block. + for( uint j = 0; j < 4; j++ ) { + for( uint i = 0; i < 4; i++ ) { + /*if( img.valid( x+i, y+j ) ) */{ + uint idx = (block.row[j] & masks[i]) >> shift[i]; + color_array[idx].a = alpha_array[bit_array[j*4+i]]; + scanline[j][x+i] = RGBA(color_array[idx].r, color_array[idx].g, color_array[idx].b, color_array[idx].a); + } + } + } + } + } + + return true; + } + static bool LoadDXT4( ifstreamK & s, const DDSHeader & header, RGBA **img) + { + if( !LoadDXT5(s, header, img) ) return false; + //UndoPremultiplyAlpha(img); + return true; + } + + static bool LoadRXGB( ifstreamK & s, const DDSHeader & header, RGBA **img) + { + const uint w = header.width; + const uint h = header.height; + + BlockDXT block; + BlockDXTAlphaLinear alpha; + RGBA * scanline[4]; + + for( uint y = 0; y < h; y += 4 ) { + for( uint j = 0; j < 4; j++ ) { + scanline[j] = img[y + j]; + } + for( uint x = 0; x < w; x += 4 ) { + + // Read 128bit color block. + s >> alpha; + s >> block; + + // Decode color block. + Color8888 color_array[4]; + block.GetColors(color_array); + + uchar alpha_array[8]; + alpha.GetAlphas(alpha_array); + + uchar bit_array[16]; + alpha.GetBits(bit_array); + + // bit masks = 00000011, 00001100, 00110000, 11000000 + const uint masks[4] = { 3, 3<<2, 3<<4, 3<<6 }; + const int shift[4] = { 0, 2, 4, 6 }; + + // Write color block. + for( uint j = 0; j < 4; j++ ) { + for( uint i = 0; i < 4; i++ ) { + /*if( img.valid( x+i, y+j ) ) */{ + uint idx = (block.row[j] & masks[i]) >> shift[i]; + color_array[idx].a = alpha_array[bit_array[j*4+i]]; + scanline[j][x+i] = RGBA(color_array[idx].a, color_array[idx].g, color_array[idx].b, 255); + } + } + } + } + } + + return true; + } + + static bool LoadATI2( ifstreamK & s, const DDSHeader & header, RGBA **img) + { + const uint w = header.width; + const uint h = header.height; + + BlockDXTAlphaLinear xblock; + BlockDXTAlphaLinear yblock; + RGBA * scanline[4]; + + for( uint y = 0; y < h; y += 4 ) { + for( uint j = 0; j < 4; j++ ) { + scanline[j] = img[y + j]; + } + for( uint x = 0; x < w; x += 4 ) { + + // Read 128bit color block. + s >> xblock; + s >> yblock; + + // Decode color block. + uchar xblock_array[8]; + xblock.GetAlphas(xblock_array); + + uchar xbit_array[16]; + xblock.GetBits(xbit_array); + + uchar yblock_array[8]; + yblock.GetAlphas(yblock_array); + + uchar ybit_array[16]; + yblock.GetBits(ybit_array); + + // Write color block. + for( uint j = 0; j < 4; j++ ) { + for( uint i = 0; i < 4; i++ ) { + /*if( img.valid( x+i, y+j ) ) */{ + const uchar nx = xblock_array[xbit_array[j*4+i]]; + const uchar ny = yblock_array[ybit_array[j*4+i]]; + + const float fx = float(nx) / 127.5f - 1.0f; + const float fy = float(ny) / 127.5f - 1.0f; + const float fz = sqrtf(1.0f - fx*fx - fy*fy); + const uchar nz = uchar((fz + 1.0f) * 127.5f); + + scanline[j][x+i] = RGBA(nx, ny, nz, 255); + } + } + } + } + } + + return true; + } + + typedef bool (* TextureLoader)( ifstreamK & s, const DDSHeader & header, RGBA **); + + // Get an appropiate texture loader for the given type. + static TextureLoader GetTextureLoader( DDSType type ) { + switch( type ) { + case DDS_A8R8G8B8: + return LoadA8R8G8B8; + case DDS_A1R5G5B5: + return LoadA1R5G5B5; + case DDS_A4R4G4B4: + return LoadA4R4G4B4; + case DDS_R8G8B8: + return LoadR8G8B8; + case DDS_R5G6B5: + return LoadR5G6B5; + case DDS_DXT1: + return LoadDXT1; + case DDS_DXT2: + return LoadDXT2; + case DDS_DXT3: + return LoadDXT3; + case DDS_DXT4: + return LoadDXT4; + case DDS_DXT5: + return LoadDXT5; + case DDS_RXGB: + return LoadRXGB; + case DDS_ATI2: + return LoadATI2; + default: + return NULL; + }; + } + + + // Load a 2d texture. + static bool LoadTexture( ifstreamK & s, const DDSHeader & header, RGBA ***img) + { + if(!MALLOC_ROWS(img, header.width * sizeof(RGBA), header.height)) + return false; + + // Read image. + DDSType type = GetType( header ); + + TextureLoader loader = GetTextureLoader( type ); + if( loader == NULL ) { + return false; + } + + return loader( s, header, *img ); + } + + + static int FaceOffset( const DDSHeader & header ) { + + DDSType type = GetType( header ); + + int mipmap = max(header.mipmapcount, 1); + int size = 0; + int w = header.width; + int h = header.height; + + if( type >= DDS_DXT1 ) { + int multiplier = (type == DDS_DXT1) ? 8 : 16; + do { + int face_size = max(w/4,1) * max(h/4,1) * multiplier; + size += face_size; + w >>= 1; + h >>= 1; + } while( --mipmap ); + } + else { + int multiplier = header.pf.bitcount / 8; + do { + int face_size = w * h * multiplier; + size += face_size; + w = max( w>>1, 1 ); + h = max( h>>1, 1 ); + } while( --mipmap ); + } + + return size; + } + +#if CUBE_LAYOUT == HORIZONTAL + static int face_offset[6][2] = { {2, 1}, {0, 1}, {1, 0}, {1, 2}, {1, 1}, {3, 1} }; +#elif CUBE_LAYOUT == VERTICAL + static int face_offset[6][2] = { {2, 1}, {0, 1}, {1, 0}, {1, 2}, {1, 1}, {1, 3} }; +#endif + static int face_flags[6] = { + DDSCAPS2_CUBEMAP_POSITIVEX, + DDSCAPS2_CUBEMAP_NEGATIVEX, + DDSCAPS2_CUBEMAP_POSITIVEY, + DDSCAPS2_CUBEMAP_NEGATIVEY, + DDSCAPS2_CUBEMAP_POSITIVEZ, + DDSCAPS2_CUBEMAP_NEGATIVEZ + }; + + // Load unwrapped cube map. + static bool LoadCubeMap( ifstreamK & s, const DDSHeader & header, RGBA ***img) + { + int dimw = 0, dimh = 0; +#if CUBE_LAYOUT == HORIZONTAL + dimw = 4 * header.width; + dimh = 3 * header.height; +#elif CUBE_LAYOUT == VERTICAL + dimw = 3 * header.width; + dimh = 4 * header.height; +#endif + + if(!MALLOC_ROWS(img, dimw * sizeof(RGBA), dimh)) + return false; + + // Create dst image. + + DDSType type = GetType( header ); + + // Select texture loader. + TextureLoader loader = GetTextureLoader( type ); + if( loader == NULL ) { + return false; + } + + RGBA **face; + if(!MALLOC_ROWS(&face, header.width * sizeof(RGBA), header.height)) + return false; + + // Create face image. + int offset = s.tellg(); + int size = FaceOffset( header ); + + for( int i = 0; i < 6; i++ ) { + + if( !(header.caps.caps2 & face_flags[i]) ) { + // Skip face. + continue; + } + + // Seek device. + s.seekg(offset); + offset += size; + + // Load face from stream. + if( !loader( s, header, face ) ) { + return false; + } + +#if CUBE_LAYOUT == VERTICAL + if( i == 5 ) { +// face = face.mirror(true, true); + } +#endif + + // Compute face offsets. + int offset_x = face_offset[i][0] * header.width; + int offset_y = face_offset[i][1] * header.height; + + // Copy face on the image. + for( uint y = 0; y < header.height; y++ ) + { + RGBA * src = face[y]; + RGBA * dst = (*img)[y + offset_y] + offset_x; + memcpy( dst, src, sizeof(RGBA) * header.width ); + } + } + + return true; + } + +} + +bool dds_read(const std::string &file, DDSINFO &dds) +{ + ifstreamK s; + s.open(file.c_str(), std::ios::binary | std::ios::in); + + if(!s.good()) + return false; + + // Validate header. + uint fourcc; + s.readK(&fourcc, sizeof(uint)); + + if(fourcc != FOURCC_DDS) + return false; + + // Read image header. + DDSHeader header; + s >> header; + + // Check image file format. + if(!s.good() || !IsValid(header) || !IsSupported(header)) + return false; + + RGBA **img = 0; + bool result; + + if(IsCubeMap(header)) + result = LoadCubeMap(s, header, &img); + else + result = LoadTexture(s, header, &img); + + if(result) + { + dds.w = header.width; + dds.h = header.height; + dds.img = img; + } + + return result; +} diff --git a/kernel/kls_dds/dds.h b/kernel/kls_dds/dds.h new file mode 100644 index 0000000..5e7af28 --- /dev/null +++ b/kernel/kls_dds/dds.h @@ -0,0 +1,36 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2007 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef DDS_H +#define DDS_H + +struct RGBA; +struct DDSINFO; + +struct DDSINFO +{ + int w, h; + RGBA **img; +}; + +bool dds_read(const std::string &file, DDSINFO&); + +#endif diff --git a/kernel/kls_dds/fmt_codec_dds.cpp b/kernel/kls_dds/fmt_codec_dds.cpp new file mode 100644 index 0000000..305c207 --- /dev/null +++ b/kernel/kls_dds/fmt_codec_dds.cpp @@ -0,0 +1,143 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2007 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" + +#include "fmt_codec_dds_defs.h" +#include "fmt_codec_dds.h" + +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "../xpm/codec_dds.xpm" + +typedef RGBA* RGBAP; + +inline void FREE_ROWS(RGBAP **A, const int H) +{ + if(*A) + { + for(s32 i = 0;i < H;i++) + { + if((*A)[i]) + free((*A)[i]); + } + + free(*A); + *A = 0; + } +} + +/* + * + * DDS + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.1.0"; + o->name = "DirectDraw Surface"; + o->filter = "*.dds "; + o->mime = ""; + o->mimetype = "image/x-dds"; + o->config = ""; + o->pixmap = codec_dds; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + currentImage = -1; + read_error = false; + + finfo.animated = false; + + dds.img = 0; + dds.w = dds.h = 0; + + if(!dds_read(file, dds)) + return SQE_R_BADFILE; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + image.w = dds.w; + image.h = dds.h; + image.bpp = 32; + + image.compression = "-"; + image.colorspace = fmt_utils::colorSpaceByBpp(32); + + finfo.image.push_back(image); + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + line++; + + memcpy(scan, dds.img[line], dds.w * sizeof(RGBA)); + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + FREE_ROWS(&dds.img, dds.h); + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_dds/fmt_codec_dds_defs.h b/kernel/kls_dds/fmt_codec_dds_defs.h new file mode 100644 index 0000000..182687c --- /dev/null +++ b/kernel/kls_dds/fmt_codec_dds_defs.h @@ -0,0 +1,27 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2007 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_dds +#define KSQUIRREL_CODEC_DEFS_dds + +// define constants here + +#endif diff --git a/kernel/kls_dicom/Makefile.am b/kernel/kls_dicom/Makefile.am new file mode 100644 index 0000000..81d024c --- /dev/null +++ b/kernel/kls_dicom/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I../include -I../kls_png + +bin_SCRIPTS = ksquirrel-libs-dicom2png + +pkglib_LTLIBRARIES = libkls_dicom.la + +libkls_dicom_la_SOURCES = fmt_codec_png.cpp fmt_codec_png_defs.h + +libkls_dicom_la_LDFLAGS = ${SQ_RELEASE} + +libkls_dicom_la_LIBADD = ${SQ_LOCAL_RPATH} -L../kls_png/ksquirrel-libs-png -lksquirrel-libs-png + +AM_CXXFLAGS = -DCODEC_DICOM -DDICOM=\"${bindir}/ksquirrel-libs-dicom2png\" + +EXTRA_DIST = ksquirrel-libs-dicom2png.in diff --git a/kernel/kls_dicom/fmt_codec_png.cpp b/kernel/kls_dicom/fmt_codec_png.cpp new file mode 100644 index 0000000..66c43ee --- /dev/null +++ b/kernel/kls_dicom/fmt_codec_png.cpp @@ -0,0 +1,655 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs-png/png.h" + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_png_defs.h" +#include "fmt_codec_png.h" + +#if defined CODEC_SVG || defined CODEC_DICOM +#include +#include +#include +#include +#endif + +#ifdef CODEC_SVG +#include "../xpm/codec_svg.xpm" +#elif defined CODEC_DICOM +#include "../xpm/codec_dicom.xpm" +#else +#include "../xpm/codec_png.xpm" +#endif + +/* + * + * PNG (pronounced "ping") is a bitmap file format used to transmit and + * store bitmapped images. PNG supports the capability of storing up to + * 16 bits (gray-scale) or 48 bits (truecolor) per pixel, and up to 16 bits + * of alpha data. It handles the progressive display + * of image data and the storage of gamma, + * transparency and textual information, and it uses an efficient and + * lossless form of data compression. + * + */ + +inline bool MALLOC_ROWS(png_bytep **A, const int RB, const int H) +{ + *A = (png_bytep*)malloc(H * sizeof(png_bytep*)); + + if(!*A) + return false; + + for(s32 row = 0; row < H; row++) + (*A)[row] = 0; + + for(s32 row = 0; row < (s32)H; row++) + { + (*A)[row] = (png_bytep)malloc(RB); + + if(!(*A)[row]) + return false; + + memset((*A)[row], 0, RB); + } + + return true; +} + +inline void FREE_ROWS(png_bytep **A, const int H) +{ + if(*A) + { + for(s32 i = 0;i < H;i++) + { + if((*A)[i]) + free((*A)[i]); + } + + free(*A); + *A = 0; + } +} + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ +#ifdef CODEC_SVG + o->version = "0.1.2"; + o->name = "Scalable Vector Graphics"; + o->filter = "*.svg *.svgz "; + o->config = std::string(SVG_UI); // SVG_UI comes from Makefile.am + o->mime = ""; + o->mimetype = "image/svg+xml"; + o->pixmap = codec_svg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DICOM + o->version = "1.1.3"; + o->name = "DICOM"; + o->filter = "*.dcm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-dicom"; + o->pixmap = codec_dicom; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "1.1.3"; + o->name = "Portable Network Graphics"; + o->filter = "*.png "; + o->config = ""; + o->mime = "\x0089\x0050\x004E\x0047\x000D\x000A\x001A\x000A"; + o->mimetype = "image/png"; + o->pixmap = codec_png; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#ifdef CODEC_ANOTHER +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_int; + val.iVal = 1; + + m_settings["scale"] = val; +} +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + png_ptr = 0; + info_ptr = 0; + fptr = 0; + frame = 0; + prev = 0; + cur = 0; + zerror = false; + +#ifdef CODEC_SVG + int status; + + fmt_settings::iterator it = m_settings.find("scale"); + + // percents / 100 + int scale = (it == m_settings.end() || (*it).second.type != settings_value::v_int) + ? 1 : (*it).second.iVal; + + if(scale < 1 || scale > 10) + scale = 1; + + char z[32]; + snprintf(z, 32, "%d", scale); + + pid_t pid = fork(); + + if(!pid) + { + execlp(SVG2PNG, SVG2PNG, "--binary", RSVG, "--input", file.c_str(), "--output", tmp.c_str(), "-z", z, (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DICOM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(DICOM, DICOM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#else + fptr = fopen(file.c_str(), "rb"); +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + if((png_ptr = my_png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0)) == NULL) + { + zerror = true; + return SQE_R_NOMEMORY; + } + + if((info_ptr = my_png_create_info_struct(png_ptr)) == NULL) + { + zerror = true; + return SQE_R_NOMEMORY; + } + + if(setjmp(png_jmpbuf(png_ptr))) + { + zerror = true; + return SQE_R_BADFILE; + } + + my_png_init_io(png_ptr, fptr); + my_png_read_info(png_ptr, info_ptr); + my_png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, (int*)0, (int*)0); + + img.w = next_frame_width = width; + img.h = next_frame_height = height; + img.bpp = bit_depth; + + if(img.bpp == 16) + my_png_set_strip_16(png_ptr); + + if(img.bpp < 8) + my_png_set_packing(png_ptr); + + if(color_type == PNG_COLOR_TYPE_GRAY && img.bpp < 8) + my_png_set_gray_1_2_4_to_8(png_ptr); + + if(color_type == PNG_COLOR_TYPE_PALETTE) + my_png_set_palette_to_rgb(png_ptr); + + if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + my_png_set_gray_to_rgb(png_ptr); + + if(my_png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + my_png_set_tRNS_to_alpha(png_ptr); + + my_png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + + number_passes = my_png_set_interlace_handling(png_ptr); + + my_png_read_update_info(png_ptr, info_ptr); + + finfo.animated = !!my_png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL); + + frames = finfo.animated ? my_png_get_num_frames(png_ptr, info_ptr) : 1; + + if(!frames) return SQE_R_BADFILE; + + img.interlaced = number_passes > 1; + img.passes = finfo.animated ? 1 : number_passes; + + if(finfo.animated) + { + if(!MALLOC_ROWS(&prev, width * sizeof(RGBA), height)) + return SQE_R_NOMEMORY; + + if(!MALLOC_ROWS(&cur, width * sizeof(RGBA), height)) + return SQE_R_NOMEMORY; + } + + std::string color_; + + img.hasalpha = (color_type & PNG_COLOR_MASK_ALPHA); + + switch((color_type & ~PNG_COLOR_MASK_ALPHA)) + { + case PNG_COLOR_TYPE_RGB: color_ = "RGB"; break; + case PNG_COLOR_TYPE_PALETTE: color_ = "Color indexed"; break; + case PNG_COLOR_TYPE_GRAY: color_ = "Grayscale"; break; + + default: + color_ = "Unknown"; + } + + if(img.hasalpha) + color_ += " with ALPHA"; + + img.compression = "Deflate method 8, 32K window"; + img.colorspace = color_; + if(!finfo.animated) img.delay = 0; + +#ifdef PNG_TEXT_SUPPORTED + png_textp lines = info_ptr->text; + + if(!lines || !info_ptr->num_text) + return SQE_OK; + + for(s32 i = 0;i < info_ptr->num_text;i++) + { + fmt_metaentry mt; + + mt.group = lines[i].key; + mt.data = lines[i].text; + + addmeta(mt); + } +#endif + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage == frames) + return SQE_NOTOK; + + if(setjmp(png_jmpbuf(png_ptr))) + { + zerror = true; + return SQE_R_BADFILE; + } + + if(finfo.animated) + { + if(currentImage) + { + if(next_frame_dispose_op == PNG_DISPOSE_OP_BACKGROUND) + { + for(u32 j = next_frame_y_offset,i = 0;i < next_frame_height;j++,i++) + memset(cur[j]+next_frame_x_offset*sizeof(RGBA), 0, next_frame_width * sizeof(RGBA)); + } + else if(next_frame_dispose_op == PNG_DISPOSE_OP_PREVIOUS) + { + for(u32 i = 0;i < height;i++) + memcpy(cur[i], prev[i], width*sizeof(RGBA)); + } + else // next_frame_dispose_op == PNG_DISPOSE_OP_NONE + { + } + + for(u32 i = 0;i < height;i++) + memcpy(prev[i], cur[i], width*sizeof(RGBA)); + } + else if(my_png_get_first_frame_is_hidden(png_ptr, info_ptr)) + { + if(!MALLOC_ROWS(&frame, width * sizeof(RGBA), height)) + return SQE_R_NOMEMORY; + + my_png_read_frame_head(png_ptr, info_ptr); + my_png_read_image(png_ptr, frame); + + FREE_ROWS(&frame, height); + + frames--; + + if(frames == 1) + { + my_png_read_frame_head(png_ptr, info_ptr); + finfo.animated = false; + img.passes = number_passes; + finfo.image.push_back(img); + return SQE_OK; + } + else if(!frames) + return SQE_R_BADFILE; // oops? + } + + FREE_ROWS(&frame, next_frame_height); + + my_png_read_frame_head(png_ptr, info_ptr); + + if(my_png_get_valid(png_ptr, info_ptr, PNG_INFO_fcTL)) + { + my_png_get_next_frame_fcTL(png_ptr, info_ptr, + &next_frame_width, &next_frame_height, + &next_frame_x_offset, &next_frame_y_offset, + &next_frame_delay_num, &next_frame_delay_den, + &next_frame_dispose_op, &next_frame_blend_op); + } + else + { + next_frame_width = width; + next_frame_height = height; + next_frame_x_offset = 0; + next_frame_y_offset = 0; + next_frame_dispose_op = PNG_DISPOSE_OP_BACKGROUND; + next_frame_blend_op = PNG_BLEND_OP_SOURCE; + } + + if(!next_frame_delay_den) next_frame_delay_den = 100; + + img.delay = (s32)(((double)next_frame_delay_num / next_frame_delay_den) * 1000); + + if(next_frame_width + next_frame_x_offset > width || next_frame_height + next_frame_y_offset > height) + return SQE_R_BADFILE; + + if(!MALLOC_ROWS(&frame, next_frame_width * sizeof(RGBA), next_frame_height)) + return SQE_R_NOMEMORY; + + my_png_read_image(png_ptr, frame); + + // copy all pixel values including alpha + if(!currentImage || next_frame_blend_op == PNG_BLEND_OP_SOURCE) + { + for(u32 j = next_frame_y_offset,i = 0;i < next_frame_height;j++,i++) + memcpy(cur[j]+next_frame_x_offset*sizeof(RGBA), frame[i], next_frame_width * sizeof(RGBA)); + } + else // over + { + RGBA *src, *dst; + + for(u32 j = next_frame_y_offset,i = 0;i < next_frame_height;j++,i++) + { + src = (RGBA *)frame[i]; + dst = (RGBA *)(cur[j]+next_frame_x_offset*sizeof(RGBA)); + u32 k = next_frame_width; + + while(k--) + { + // fully transparent foreground + if(src->a == 0) + ; + else if(src->a == 255 || dst->a == 0) + *dst = *src; + else // composite + { + dst->r = ((src->a * (src->r - dst->r))>>8) + dst->r; + dst->g = ((src->a * (src->g - dst->g))>>8) + dst->g; + dst->b = ((src->a * (src->b - dst->b))>>8) + dst->b; + //dst->a = ((src->a * (src->a - dst->a))>>8) + dst->a; + } + + src++; + dst++; + } + } + } + } + + finfo.image.push_back(img); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + fmt_image *im = image(currentImage); + + line++; + + if(zerror || setjmp(png_jmpbuf(png_ptr))) + { + zerror = true; + return SQE_R_BADFILE; + } + + if(finfo.animated) + memcpy(scan, cur[line], im->w * sizeof(RGBA)); + else + my_png_read_row(png_ptr, (png_bytep)scan, png_bytep_NULL); + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(png_ptr) my_png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); + + if(fptr) fclose(fptr); + + FREE_ROWS(&frame, next_frame_height); + FREE_ROWS(&prev, height); + FREE_ROWS(&cur, height); + + finfo.meta.clear(); + finfo.image.clear(); +} + +#ifdef CODEC_PNG + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = true; + opt->compression_scheme = CompressionInternal; + opt->compression_min = 1; + opt->compression_max = 9; + opt->compression_def = 7; + opt->passes = 8; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + m_png_ptr = 0; + m_info_ptr = 0; + m_fptr = 0; + m_zerror = false; + + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + m_fptr = fopen(file.c_str(), "wb"); + + if(!m_fptr) + return SQE_W_NOFILE; + + m_png_ptr = my_png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + + if(!m_png_ptr) + { + m_zerror = true; + return SQE_W_NOMEMORY; + } + + m_info_ptr = my_png_create_info_struct(m_png_ptr); + + if(!m_info_ptr) + { + m_zerror = true; + return SQE_W_NOMEMORY; + } + + if(setjmp(png_jmpbuf(m_png_ptr))) + { + m_zerror = true; + return SQE_W_ERROR; + } + + my_png_init_io(m_png_ptr, m_fptr); + + my_png_set_IHDR(m_png_ptr, m_info_ptr, writeimage.w, writeimage.h, 8, PNG_COLOR_TYPE_RGB_ALPHA, + ((writeopt.interlaced) ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE), + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_color_8 sig_bit; + + sig_bit.red = 8; + sig_bit.green = 8; + sig_bit.blue = 8; + sig_bit.alpha = 8; + + my_png_set_sBIT(m_png_ptr, m_info_ptr, &sig_bit); + + s32 factor = (writeopt.compression_level < 1 || writeopt.compression_level > 9) ? 1 : writeopt.compression_level; + + my_png_set_compression_level(m_png_ptr, factor); + + my_png_write_info(m_png_ptr, m_info_ptr); + + my_png_set_shift(m_png_ptr, &sig_bit); + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + my_png_set_swap(m_png_ptr); + + my_png_set_packswap(m_png_ptr); + + my_png_set_interlace_handling(m_png_ptr); + + return SQE_OK; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + if(m_zerror || setjmp(png_jmpbuf(m_png_ptr))) + { + m_zerror = true; + return SQE_W_ERROR; + } + + m_row_pointer = (png_bytep)scan; + + my_png_write_rows(m_png_ptr, &m_row_pointer, 1); + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + if(m_png_ptr && !m_zerror) my_png_write_end(m_png_ptr, m_info_ptr); + if(m_png_ptr) my_png_destroy_write_struct(&m_png_ptr, &m_info_ptr); + if(m_fptr) fclose(m_fptr); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("png"); +} + +#endif + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_dicom/fmt_codec_png_defs.h b/kernel/kls_dicom/fmt_codec_png_defs.h new file mode 100644 index 0000000..afef4ac --- /dev/null +++ b/kernel/kls_dicom/fmt_codec_png_defs.h @@ -0,0 +1,27 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_png +#define KSQUIRREL_READ_IMAGE_png + +// Nothing to define at this moment :) + +#endif diff --git a/kernel/kls_dicom/ksquirrel-libs-dicom2png.in b/kernel/kls_dicom/ksquirrel-libs-dicom2png.in new file mode 100644 index 0000000..96e0138 --- /dev/null +++ b/kernel/kls_dicom/ksquirrel-libs-dicom2png.in @@ -0,0 +1,3 @@ +#!/bin/sh + +@MEDCON@ --without-prefix -f "$1" -e 0:0 -c - png > "$2" \ No newline at end of file diff --git a/kernel/kls_djvu/Makefile.am b/kernel/kls_djvu/Makefile.am new file mode 100644 index 0000000..e546bff --- /dev/null +++ b/kernel/kls_djvu/Makefile.am @@ -0,0 +1,17 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_djvu.la + +libkls_djvu_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_djvu_la_LDFLAGS = ${SQ_RELEASE} + +libkls_djvu_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DDJVU_UI=\"${pkgdatadir}/libkls_djvu.so.ui\" -DCODEC_DJVU -DDJVU=\"${DJVU}\" -DCODEC_ANOTHER + +EXTRA_DIST = libkls_djvu.so.ui + +install-data-am: + $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) + $(INSTALL) --mode=0644 libkls_djvu.so.ui $(DESTDIR)$(pkgdatadir)/libkls_djvu.so.ui diff --git a/kernel/kls_djvu/fmt_codec_pnm.cpp b/kernel/kls_djvu/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_djvu/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_djvu/fmt_codec_pnm_defs.h b/kernel/kls_djvu/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_djvu/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_djvu/libkls_djvu.so.ui b/kernel/kls_djvu/libkls_djvu.so.ui new file mode 100644 index 0000000..5469d42 --- /dev/null +++ b/kernel/kls_djvu/libkls_djvu.so.ui @@ -0,0 +1,195 @@ + +Form1 + + + Form1 + + + + 0 + 0 + 313 + 118 + + + + Form1 + + + + unnamed + + + 0 + + + + layout1 + + + + unnamed + + + 0 + + + + textLabel2 + + + <b>Page number to decode:</b> + + + + + line1 + + + HLine + + + Sunken + + + Horizontal + + + + + + + page + + + 1 + + + 1000 + + + Horizontal + + + Below + + + 40 + + + + + no_spinBox + + + # + + + 1000 + + + 1 + + + + + layout1_2 + + + + unnamed + + + 0 + + + + textLabel2_2 + + + <b>Scale down</b> + + + + + line1_2 + + + HLine + + + Sunken + + + Horizontal + + + + + + + scaledown + + + 1 + + + 12 + + + Horizontal + + + Below + + + 1 + + + + + no_spinBox_2 + + + x + + + no + + + 12 + + + 1 + + + + + + + page + valueChanged(int) + no_spinBox + setValue(int) + + + no_spinBox + valueChanged(int) + page + setValue(int) + + + scaledown + valueChanged(int) + no_spinBox_2 + setValue(int) + + + no_spinBox_2 + valueChanged(int) + scaledown + setValue(int) + + + + diff --git a/kernel/kls_dxf/Makefile.am b/kernel/kls_dxf/Makefile.am new file mode 100644 index 0000000..7d3fc63 --- /dev/null +++ b/kernel/kls_dxf/Makefile.am @@ -0,0 +1,17 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_dxf.la + +libkls_dxf_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_dxf_la_LDFLAGS = ${SQ_RELEASE} + +libkls_dxf_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DDXF_UI=\"${pkgdatadir}/libkls_dxf.so.ui\" -DCODEC_DXF -DVEC2WEB=\"${VEC2WEB}\" -DCODEC_ANOTHER + +EXTRA_DIST = libkls_dxf.so.ui + +install-data-am: + $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) + $(INSTALL) --mode=0644 libkls_dxf.so.ui $(DESTDIR)$(pkgdatadir)/libkls_dxf.so.ui diff --git a/kernel/kls_dxf/fmt_codec_pnm.cpp b/kernel/kls_dxf/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_dxf/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_dxf/fmt_codec_pnm_defs.h b/kernel/kls_dxf/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_dxf/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_dxf/libkls_dxf.so.ui b/kernel/kls_dxf/libkls_dxf.so.ui new file mode 100644 index 0000000..96a4c98 --- /dev/null +++ b/kernel/kls_dxf/libkls_dxf.so.ui @@ -0,0 +1,192 @@ + +Form1 + + + Form1 + + + + 0 + 0 + 313 + 118 + + + + Form1 + + + + unnamed + + + 0 + + + + layout1 + + + + unnamed + + + 0 + + + + textLabel2 + + + <b>Width</b> + + + + + line1 + + + HLine + + + Sunken + + + Horizontal + + + + + + + width + + + 0 + + + 10000 + + + Horizontal + + + Below + + + 500 + + + + + no_spinBox + + + default + + + 10000 + + + 0 + + + + + layout1_2 + + + + unnamed + + + 0 + + + + textLabel2_2 + + + <b>Height</b> + + + + + line1_2 + + + HLine + + + Sunken + + + Horizontal + + + + + + + height + + + 0 + + + 10000 + + + Horizontal + + + Below + + + 500 + + + + + no_spinBox_2 + + + default + + + 10000 + + + 0 + + + + + + + width + valueChanged(int) + no_spinBox + setValue(int) + + + no_spinBox + valueChanged(int) + width + setValue(int) + + + height + valueChanged(int) + no_spinBox_2 + setValue(int) + + + no_spinBox_2 + valueChanged(int) + height + setValue(int) + + + + diff --git a/kernel/kls_eps/Makefile.am b/kernel/kls_eps/Makefile.am new file mode 100644 index 0000000..5aa673f --- /dev/null +++ b/kernel/kls_eps/Makefile.am @@ -0,0 +1,11 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_eps.la + +libkls_eps_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_eps_la_LDFLAGS = ${SQ_RELEASE} -lm + +libkls_eps_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DCODEC_EPS -DEPS2PPM=\"${EPS2PPM}\" diff --git a/kernel/kls_eps/fmt_codec_pnm.cpp b/kernel/kls_eps/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_eps/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_eps/fmt_codec_pnm_defs.h b/kernel/kls_eps/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_eps/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_fig/Makefile.am b/kernel/kls_fig/Makefile.am new file mode 100644 index 0000000..7240c61 --- /dev/null +++ b/kernel/kls_fig/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I../include + +bin_SCRIPTS = ksquirrel-libs-fig2ppm + +pkglib_LTLIBRARIES = libkls_fig.la + +libkls_fig_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_fig_la_LDFLAGS = ${SQ_RELEASE} + +libkls_fig_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DCODEC_FIG -DXFIG_S=\"${bindir}/ksquirrel-libs-fig2ppm\" + +EXTRA_DIST = ksquirrel-libs-fig2ppm.in \ No newline at end of file diff --git a/kernel/kls_fig/fmt_codec_pnm.cpp b/kernel/kls_fig/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_fig/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_fig/fmt_codec_pnm_defs.h b/kernel/kls_fig/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_fig/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_fig/ksquirrel-libs-fig2ppm.in b/kernel/kls_fig/ksquirrel-libs-fig2ppm.in new file mode 100644 index 0000000..2bbd537 --- /dev/null +++ b/kernel/kls_fig/ksquirrel-libs-fig2ppm.in @@ -0,0 +1,3 @@ +#!/bin/sh + +@XFIG@ -L ppm "$1" > "$2" \ No newline at end of file diff --git a/kernel/kls_fli/Makefile.am b/kernel/kls_fli/Makefile.am new file mode 100644 index 0000000..7570336 --- /dev/null +++ b/kernel/kls_fli/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_fli.la + +libkls_fli_la_SOURCES = fmt_codec_fli.cpp fmt_codec_fli_defs.h + +libkls_fli_la_LDFLAGS = ${SQ_RELEASE} + +libkls_fli_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_fli/fmt_codec_fli.cpp b/kernel/kls_fli/fmt_codec_fli.cpp new file mode 100644 index 0000000..d186d98 --- /dev/null +++ b/kernel/kls_fli/fmt_codec_fli.cpp @@ -0,0 +1,449 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_fli_defs.h" +#include "fmt_codec_fli.h" + +#include "../xpm/codec_fli.xpm" + +/* + * + * The FLI file format (sometimes called Flic) + * is one of the most popular + * animation formats found in the MS-DOS and Windows environments today. FLI is + * used widely in animation programs, computer games, and CAD applications + * requiring 3D manipulation of vector drawings. Flic, in common + * with most animation formats, does not support either audio or video data, but + * instead stores only sequences of still image data. + * + */ + +// maximum number of frames in FLI is 1024 +#define MAX_FRAME 1024 + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.3.2"; + o->name = "FLI Animation"; + o->filter = "*.fli "; + o->config = ""; + o->mime = ""; + o->mimetype = "video/x-flic"; + o->pixmap = codec_fli; + o->readable = true; + o->canbemultiple = true; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + if(!frs.readK(&flic, sizeof(FLICHEADER))) + return SQE_R_BADFILE; + + if(flic.FileId != 0xAF11)// && flic.FileId != 0xAF12) + return SQE_R_BADFILE; + + if(flic.Flags != 3) + cerr << "libSQ_read_fli: WARNING: Flags != 3" << endl; + + memset(pal, 0, 768); + + currentImage = -1; + + buf = (u8**)calloc(flic.Height, sizeof(u8*)); + + if(!buf) + return SQE_R_NOMEMORY; + + for(s32 i = 0;i < flic.Height;i++) + { + buf[i] = (u8*)0; + } + + for(s32 i = 0;i < flic.Height;i++) + { + buf[i] = (u8*)calloc(flic.Width, sizeof(u8)); + + if(!buf[i]) + return SQE_R_NOMEMORY; + } + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage == flic.NumberOfFrames || currentImage == MAX_FRAME) + return SQE_NOTOK; + + fmt_image image; + + image.w = flic.Width; + image.h = flic.Height; + image.bpp = 8; + image.delay = (s32)((float)flic.FrameDelay * 14.3); + finfo.animated = (currentImage) ? true : false; + +// prs32f("%dx%d@%d, delay: %d\n", flic.Width, flic.Height, flic.PixelDepth, finfo.image[currentImage].delay); + + CHUNKHEADER chunk; + CHUNKHEADER subchunk; + u16 subchunks; + + fstream::pos_type pos = frs.tellg(); +// prs32f("POS AFTER HEADER: %d\n", pos); + + while(true) + { + if(!skip_flood(frs)) + return SQE_R_BADFILE; + + if(!frs.readK(&chunk, sizeof(CHUNKHEADER))) + return SQE_R_BADFILE; + +// prs32f("Read MAIN chunk: size: %d, type: %X\n", chunk.size, chunk.type); + + if(chunk.type != CHUNK_PREFIX_TYPE && + chunk.type != CHUNK_SCRIPT_CHUNK && + chunk.type != CHUNK_FRAME_TYPE && + chunk.type != CHUNK_SEGMENT_TABLE && + chunk.type != CHUNK_HUFFMAN_TABLE) + return SQE_R_BADFILE; + + if(chunk.type != CHUNK_FRAME_TYPE) + frs.seekg(chunk.size - sizeof(CHUNKHEADER), ios::cur); + else + { + if(!frs.readK(&subchunks, sizeof(u16))) + return SQE_R_BADFILE; +// prs32f("Chunk #%X has %d subchunks\n", chunk.type, subchunks); + frs.seekg(sizeof(u16) * 4, ios::cur); + break; + } + } + +// prs32f("POS MAIN: %d\n", ftell(fptr)); +// fsetpos(fptr, (fpos_t*)&pos); +// fseek(fptr, chunk.size, SEEK_CUR); +// prs32f("POS2 MAIN: %d\n", ftell(fptr)); + + while(subchunks--) + { + pos = frs.tellg(); + + if(!frs.readK(&subchunk, sizeof(CHUNKHEADER))) + return SQE_R_BADFILE; + +// prs32f("*** Subchunk: %d\n", subchunk.type); + + switch(subchunk.type) + { + case CHUNK_COLOR_64: + case CHUNK_COLOR_256: + { +// prs32f("*** Palette64 CHUNK\n"); + u8 skip, count; + u16 packets; + RGB e; + + if(!frs.readK(&packets, sizeof(u16))) + return SQE_R_BADFILE; +// prs32f("COLOR_64 packets: %d\n", packets); + + for(s32 i = 0;i < packets;i++) + { + if(!frs.readK(&skip, 1)) return SQE_R_BADFILE; + if(!frs.readK(&count, 1)) return SQE_R_BADFILE; +// prs32f("COLOR64 skip: %d, count: %d\n", skip, count); + + if(count) + { + for(s32 j = 0;j < count;j++) + { + if(!frs.readK(&e, sizeof(RGB))) return SQE_R_BADFILE; +// prs32f("COLOR_64 PALLETTE CHANGE %d,%d,%d\n", e.r, e.g, e.b); + } + } + else + { +// prs32f("Reading pallette...\n"); + if(!frs.readK(pal, sizeof(RGB) * 256)) return SQE_R_BADFILE; + + u8 *pp = (u8 *)pal; + + if(subchunk.type == CHUNK_COLOR_64) + for(s32 j = 0;j < 768;j++) + pp[j] <<= 2; + +// for(s32 j = 0;j < 256;j++) +// prs32f("COLOR_64 PALLETTE %d,%d,%d\n", pal[j].r, pal[j].g, pal[j].b); +// prs32f("\n"); + } + } + } + break; + + case CHUNK_RLE: + { +// prs32f("*** RLE DATA CHUNK\n"); + u8 value; + s8 c; + s32 count; + + for(s32 j = 0;j < image.h;j++) + { + s32 index = 0; + count = 0; + if(!frs.readK(&c, 1)) return SQE_R_BADFILE; + + while(count < image.w) + { + if(!frs.readK(&c, 1)) return SQE_R_BADFILE; + + if(c < 0) + { + c = -c; + + for(s32 i = 0;i < c;i++) + { + if(!frs.readK(&value, 1)) return SQE_R_BADFILE; + buf[j][index] = value; + index++; + } + + count += c; + } + else + { + if(!frs.readK(&value, 1)) return SQE_R_BADFILE; + + for(s32 i = 0;i < c;i++) + { + buf[j][index] = value; + index++; + } + + count += c; + } + } + } + } + break; + + case CHUNK_DELTA_FLI: + { + u16 starty, totaly, ally, index; + u8 packets, skip, byte; + s8 size; + s32 count; + + if(!frs.readK(&starty, 2)) return SQE_R_BADFILE; + if(!frs.readK(&totaly, 2)) return SQE_R_BADFILE; + + ally = starty + totaly; + +// prs32f("Y: %d, Total: %d\n", starty, totaly); + + for(s32 j = starty;j < ally;j++) + { + count = 0; + index = 0; + + if(!frs.readK(&packets, 1)) return SQE_R_BADFILE; + + while(count < image.w) + { + for(s32 k = 0;k < packets;k++) + { +// prs32f("LINE %d\n", j); + if(!frs.readK(&skip, 1)) return SQE_R_BADFILE; + if(!frs.readK(&size, 1)) return SQE_R_BADFILE; + + index += skip; + +// prs32f("SKIP: %d, SIZE: %d\n", skip, size); + + if(size > 0) + { + if(!frs.readK(buf[j]+index, size)) return SQE_R_BADFILE; + } + else if(size < 0) + { + size = -size; + if(!frs.readK(&byte, 1)) return SQE_R_BADFILE; + memset(buf[j]+index, byte, size); + } + + index += size; + count += size; + } + + break; + } + } + } + break; + + case CHUNK_BLACK: + break; + + case CHUNK_COPY: + { +// prs32f("*** COPY DATA CHUNK\n"); + + for(s32 j = 0;j < image.h;j++) + { + if(!frs.readK(buf[j], image.w)) return SQE_R_BADFILE; + } + } + break; + + default: +// prs32f("*** UNKNOWN CHUNK! SEEKING ANYWAY\n"); + frs.seekg(pos); + frs.seekg(subchunk.size, ios::cur); + } + +// prs32f("POS: %d\n", ftell(fptr)); +// prs32f("POS2: %d\n", ftell(fptr)); + } + + image.compression = "RLE/DELTA_FLI"; + image.colorspace = "Color indexed"; + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + line++; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + for(s32 i = 0;i < im->w;i++) + { + memcpy(scan+i, pal+buf[line][i], sizeof(RGB)); + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(buf) + { + for(s32 i = 0;i < flic.Height;i++) + if(buf[i]) + free(buf[i]); + + free(buf); + } + + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool find_chunk_type(const u16 type) +{ + static const u16 A[] = + { + CHUNK_PREFIX_TYPE, + CHUNK_SCRIPT_CHUNK, + CHUNK_FRAME_TYPE, + CHUNK_SEGMENT_TABLE, + CHUNK_HUFFMAN_TABLE + }; + + static const s32 S = 5; + + for(s32 i = 0;i < S;i++) + if(type == A[i]) + return true; + + return false; +} + +bool fmt_codec::skip_flood(ifstreamK &s) +{ + u8 _f[4]; + u16 b; + fstream::pos_type _pos; + +// prs32f("SKIP_FLOOD pos: %d\n", ftell(f)); + + if(!s.readK(_f, 4)) return false; + + do + { + _pos = s.tellg(); + if(!s.readK(&b, 2)) return false; +// prs32f("SKIP_FLOOD b: %X\n", b); + s.seekg(-1, ios::cur); + }while(!find_chunk_type(b)); + + _pos -= 4; + + s.seekg(_pos); + + return true; + +// prs32f("SKIP_FLOOD pos2: %d\n", ftell(f)); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_fli/fmt_codec_fli_defs.h b/kernel/kls_fli/fmt_codec_fli_defs.h new file mode 100644 index 0000000..dd08b94 --- /dev/null +++ b/kernel/kls_fli/fmt_codec_fli_defs.h @@ -0,0 +1,92 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_fli +#define KSQUIRREL_READ_IMAGE_fli + +struct FLICHEADER +{ + u32 FileSize; /* Total size of file */ + u16 FileId; /* File format indicator */ + u16 NumberOfFrames; /* Total number of frames */ + u16 Width; /* Screen width in pixels */ + u16 Height; /* Screen height in pixels */ + u16 PixelDepth; /* Number of bits per pixel */ + u16 Flags; /* Set to 03h */ + u32 FrameDelay; /* Time delay between frames */ + u16 Reserved1; /* Not used (Set to 00h) */ + +// The following fields are set to 00h in a .FLI file + u32 DateCreated; /* Time/Date the file was created */ + u32 CreatorSN; /* Serial number of creator program */ + u32 LastUpdated; /* Time/Date the file last changed */ + u32 UpdaterSN; /* Serial number of updater program */ + u16 XAspect; /* X-axis of display aspect ratio */ + u16 YAspect; /* Y-axis of display aspect ratio */ + u8 Reserved2[38]; /* Not used (Set to 00h) */ + u32 Frame1Offset; /* Offset of first frame */ + u32 Frame2Offset; /* Offset of second frame */ + u8 Reserved3[40]; /* Not used (Set to 00h) */ + +}PACKED; + +struct CHUNKHEADER +{ + u32 size; /* Total size of chunk */ + u16 type; /* Chunk identifier */ +// u16 subchunks; /* Number of subchunks in this chunk */ +// u8 res[8]; /* Not used (Set to 00h) */ + +}PACKED; + +#define CHUNK_CEL_DATA 3 +#define CHUNK_COLOR_256 4 +#define CHUNK_DELTA_FLC 7 +#define CHUNK_COLOR_64 11 +#define CHUNK_DELTA_FLI 12 +#define CHUNK_BLACK 13 +#define CHUNK_RLE 15 +#define CHUNK_COPY 16 +#define CHUNK_PSTAMP 18 +#define CHUNK_DTA_BRUN 25 +#define CHUNK_DTA_COPY 26 +#define CHUNK_DTA_LC 27 +#define CHUNK_LABEL 31 +#define CHUNK_BMP_MASK 32 +#define CHUNK_MLEV_MASK 33 +#define CHUNK_SEGMENT 34 +#define CHUNK_KEY_IMAGE 35 +#define CHUNK_KEY_PAL 36 +#define CHUNK_REGION 37 +#define CHUNK_WAVE 38 +#define CHUNK_USERSTR 39 +#define CHUNK_RGN_MASK 40 +#define CHUNK_LABELEX 41 +#define CHUNK_SHIFT 42 +#define CHUNK_PATHMAP 43 + +#define CHUNK_PREFIX_TYPE 0xF100 +#define CHUNK_SCRIPT_CHUNK 0xF1E0 +#define CHUNK_FRAME_TYPE 0xF1FA +#define CHUNK_SEGMENT_TABLE 0xF1FB +#define CHUNK_HUFFMAN_TABLE 0xF1FC + +#endif diff --git a/kernel/kls_gif/Makefile.am b/kernel/kls_gif/Makefile.am new file mode 100644 index 0000000..62f5ed5 --- /dev/null +++ b/kernel/kls_gif/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_gif.la + +libkls_gif_la_SOURCES = fmt_codec_gif.cpp fmt_codec_gif_defs.h + +libkls_gif_la_LDFLAGS = ${SQ_RELEASE} + +libkls_gif_la_LIBADD = ${SQ_LOCAL_RPATH} ${SQ_GIFLIBS} diff --git a/kernel/kls_gif/fmt_codec_gif.cpp b/kernel/kls_gif/fmt_codec_gif.cpp new file mode 100644 index 0000000..80f2dbb --- /dev/null +++ b/kernel/kls_gif/fmt_codec_gif.cpp @@ -0,0 +1,516 @@ +/* This file is part of the ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004,2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License (LGPL) as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_gif_defs.h" + +extern "C" { +#include "gif_lib.h" +} + +#include "fmt_codec_gif.h" + +#include "../xpm/codec_gif.xpm" + +/* + * + * Originally designed to facilitate image transfer and online + * storage for use by CompuServe and its customers, + * GIF is primarily an exchange and storage + * format, although it is based on, and is supported by, many + * applications. + * + */ + +static s32 +InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */ +InterlacedJumps[] = { 8, 8, 4, 2 }; /* be read - offsets and jumps... */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "1.3.1"; + o->name = "Compuserve GIF"; + o->filter = "*.gif "; + o->config = ""; + o->mime = "\x0047\x0049\x0046\x0038[\x0039\x0037]\x0061"; + o->mimetype = "image/gif"; + o->pixmap = codec_gif; + o->readable = true; + o->canbemultiple = true; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + frs.close(); + + transIndex = -1; + + Last = 0; + Lines = 0; + buf = 0; + saved = 0; + + gif = DGifOpenFileName(file.c_str()); + + // for safety... + if(!gif) + return SQE_R_BADFILE; + + linesz = gif->SWidth * sizeof(GifPixelType); + + if((buf = (u8*)malloc(linesz)) == NULL) + return SQE_R_NOMEMORY; + + if((saved = (RGBA *)calloc(linesz, sizeof(RGBA))) == NULL) + return SQE_R_NOMEMORY; + + if(gif->SColorMap) + { + back.r = gif->SColorMap->Colors[gif->SBackGroundColor].Red; + back.g = gif->SColorMap->Colors[gif->SBackGroundColor].Green; + back.b = gif->SColorMap->Colors[gif->SBackGroundColor].Blue; + back.a = 255; + } + else + memset(&back, 0, sizeof(RGBA)); + + layer = -1; + line = 0; + curLine = 0; + + Lines_h = gif->SHeight; + Lines = (RGBA **)malloc(Lines_h * sizeof(RGBA*)); + + if(!Lines) + return SQE_R_NOMEMORY; + + for(s32 i = 0;i < Lines_h;i++) + Lines[i] = (RGBA *)0; + + map = (gif->Image.ColorMap) ? gif->Image.ColorMap : gif->SColorMap; + + Last = (RGBA **)malloc(gif->SHeight * sizeof(RGBA*)); + + if(!Last) + return SQE_R_NOMEMORY; + + for(s32 i = 0;i < gif->SHeight;i++) + Last[i] = (RGBA *)0; + + for(s32 i = 0;i < gif->SHeight;i++) + { + Last[i] = (RGBA *)calloc(gif->SWidth, sizeof(RGBA)); + + if(!Last[i]) + return SQE_R_NOMEMORY; + +// for(s32 k = 0;k < gif->SWidth;k++) +// memcpy(Last[i]+k, &back, sizeof(RGBA)); + } + + currentImage = -1; + lastDisposal = DISPOSAL_NO; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + layer++; + currentPass++; + line = 0; + curLine = 0; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + bool foundExt = false; + + currentImage++; + + fmt_image image; + + image.interlaced = gif->Image.Interlace; + image.passes = (gif->Image.Interlace) ? 4 : 1; + + while(true) + { + if (DGifGetRecordType(gif, &record) == GIF_ERROR) + { + PrintGifError(); + return SQE_R_BADFILE; + } + + switch(record) + { + case IMAGE_DESC_RECORD_TYPE: + if(DGifGetImageDesc(gif) == GIF_ERROR) + { + PrintGifError(); + return SQE_R_BADFILE; + } + + if(!foundExt) + { + lastDisposal = disposal; + disposal = DISPOSAL_NO; + image.delay = 100; + transIndex = -1; + image.hasalpha = true; + } + + lastRow = (currentImage) ? Row : gif->Image.Top; + lastCol = (currentImage) ? Col : gif->Image.Left; + Row = gif->Image.Top; + Col = gif->Image.Left; + image.w = gif->SWidth; + image.h = gif->SHeight; + lastWidth = (currentImage) ? Width : gif->Image.Width; + lastHeight = (currentImage) ? Height : gif->Image.Height; + Width = gif->Image.Width; + Height = gif->Image.Height; + image.bpp = 8; + + curLine = 0; + + if(gif->Image.Left + gif->Image.Width > gif->SWidth || gif->Image.Top + gif->Image.Height > gif->SHeight) + { + return SQE_R_BADFILE; + } + break; + + case EXTENSION_RECORD_TYPE: + if(DGifGetExtension(gif, &ExtCode, &Extension) == GIF_ERROR) + { + PrintGifError(); + return SQE_R_BADFILE; + } + + if(!Extension) + break; + + if(ExtCode == 249) + { + foundExt = true; + + lastDisposal = disposal; + disposal = (Extension[1] >> 2) & 7; + bool b = Extension[1] & 1; + s32 u = (unsigned)*(Extension + 2); + image.delay = (!u) ? 100 : (u * 10); + + if(b) + transIndex = Extension[4]; + + image.hasalpha = b; + } + else if(ExtCode == 254 && Extension[0]) + { + fmt_metaentry mt; + s8 d[Extension[0]+1]; + + memcpy(d, (s8*)Extension+1, Extension[0]); + d[Extension[0]] = '\0'; + + for(s32 s = 0;s < Extension[0];s++) + if(d[s] == '\n') + d[s] = ' '; + + mt.group = "Comment"; + mt.data = d; + + addmeta(mt); + } + + while(Extension) + { + if(DGifGetExtensionNext(gif, &Extension) == GIF_ERROR) + { + PrintGifError(); + return SQE_R_BADFILE; + } + } + break; + + case TERMINATE_RECORD_TYPE: + return SQE_NOTOK; + + default: ; + } + + if(record == IMAGE_DESC_RECORD_TYPE) + { + if(currentImage >= 1) + finfo.animated = true; + + map = (gif->Image.ColorMap) ? gif->Image.ColorMap : gif->SColorMap; + + back.a = (transIndex != -1) ? 0 : 255; + + for(s32 k = 0;k < gif->SWidth;k++) + memcpy(saved+k, &back, sizeof(RGBA)); + + image.compression = "LZW"; + image.colorspace = "Color indexed"; + image.interlaced = gif->Image.Interlace; + image.passes = (gif->Image.Interlace) ? 4 : 1; + + finfo.image.push_back(image); + + layer = -1; + currentPass = -1; + + return SQE_OK; + } + } +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + if(curLine < Row || curLine >= Row + Height) + { + if(currentPass == im->passes-1) + { + memcpy(scan, Last[curLine], im->w * sizeof(RGBA)); + + if(lastDisposal == DISPOSAL_BACKGROUND) + if(curLine >= lastRow && curLine < lastRow+lastHeight) + { + memcpy(scan+lastCol, saved, lastWidth * sizeof(RGBA)); + memcpy(Last[curLine], scan, im->w * sizeof(RGBA)); + } + } + + curLine++; + + return SQE_OK; + } + + curLine++; + + s32 i; + s32 index; + + if(gif->Image.Interlace) + { + memcpy(scan, Last[curLine-1], im->w * sizeof(RGBA)); + + if(line == 0) + j = InterlacedOffset[layer]; + + if(line == j) + { + if(DGifGetLine(gif, buf, Width) == GIF_ERROR) + { + PrintGifError(); + memset(scan, 255, im->w * sizeof(RGBA)); + return SQE_R_BADFILE; + } + else + { + j += InterlacedJumps[layer]; + + for(i = 0;i < Width;i++) + { + index = Col + i; + + if(buf[i] == transIndex && transIndex != -1) + { + RGB rgb = *((RGB *)&(map->Colors[buf[i]])); + + if(back == rgb && !currentImage) + (scan+index)->a = 0; + else if(back == rgb && lastDisposal != DISPOSAL_BACKGROUND && currentImage) + { + RGBA *t = &Last[curLine-1][index]; + memcpy(scan+index, t, sizeof(RGBA)); + } + else if(back == rgb && lastDisposal == DISPOSAL_BACKGROUND && currentImage) + { + (scan+index)->a = 0; + } + else if(currentImage) + { + RGBA *t = &Last[curLine-1][index]; + + if(lastDisposal == DISPOSAL_BACKGROUND) + { + memcpy(scan+index, &back, sizeof(RGBA));//(scan+index)->a=0; + + if(t->a == 0) + (scan+index)->a=0; + } + } + } + else + { + memcpy(scan+index, &(map->Colors[buf[i]]), sizeof(RGB)); + (scan+index)->a = 255; + } + } + + Lines[line] = (RGBA*)realloc(Lines[line], im->w * sizeof(RGBA)); + + if(!Lines[line]) + return SQE_R_NOMEMORY; + + memcpy(Lines[line], scan, im->w * sizeof(RGBA)); + } + } // if(line == j) + else + { + if(Lines[line]) + memcpy(scan, Lines[line], im->w * sizeof(RGBA)); + else + memset(scan, 255, im->w * sizeof(RGBA)); + } + + if(currentPass == im->passes-1) + memcpy(Last[curLine-1], scan, im->w * sizeof(RGBA)); + + line++; + } + else // !s32erlaced + { + if(DGifGetLine(gif, buf, Width) == GIF_ERROR) + { + memset(scan, 255, im->w * sizeof(RGBA)); + PrintGifError(); + return SQE_R_BADFILE; + } + else + { + memcpy(scan, Last[curLine-1], im->w * sizeof(RGBA)); + + if(lastDisposal == DISPOSAL_BACKGROUND) + { + if(curLine-1 >= lastRow && curLine-1 < lastRow+lastHeight) + memcpy(scan+lastCol, saved, lastWidth * sizeof(RGBA)); + } + + for(i = 0;i < Width;i++) + { + index = Col + i; + + if(buf[i] == transIndex && transIndex != -1) + { + RGB rgb = *((RGB *)&(map->Colors[buf[i]])); + + if(back == rgb && !currentImage) + (scan+index)->a = 0; + else if(back == rgb && lastDisposal != DISPOSAL_BACKGROUND && currentImage) + { + RGBA *t = &Last[curLine-1][index]; + memcpy(scan+index, t, sizeof(RGBA));// = 255; + } + else if(back == rgb && lastDisposal == DISPOSAL_BACKGROUND && currentImage) + { + (scan+index)->a = 0; + } + else if(currentImage) + { + RGBA *t = &Last[curLine-1][index]; + + if(lastDisposal == DISPOSAL_BACKGROUND) + { + memcpy(scan+index, &back, sizeof(RGBA));//(scan+index)->a=0; + + if(t->a == 0) + (scan+index)->a=0; + } + } + }// if transIndex + else + { + memcpy(scan+index, &(map->Colors[buf[i]]), sizeof(RGB)); + (scan+index)->a = 255; + } + } // for + + memcpy(Last[curLine-1], scan, im->w * sizeof(RGBA)); + } + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(buf) free(buf); + if(saved) free(saved); + + if(Lines) + { + for(s32 i = 0;i < Lines_h;i++) + if(Lines[i]) + free(Lines[i]); + + free(Lines); + Lines = 0; + } + + if(Last) + { + for(s32 i = 0;i < gif->SHeight;i++) + if(Last[i]) + free(Last[i]); + + free(Last); + Last = 0; + } + + finfo.meta.clear(); + finfo.image.clear(); + + if(gif) DGifCloseFile(gif); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_gif/fmt_codec_gif_defs.h b/kernel/kls_gif/fmt_codec_gif_defs.h new file mode 100644 index 0000000..02b4f41 --- /dev/null +++ b/kernel/kls_gif/fmt_codec_gif_defs.h @@ -0,0 +1,32 @@ +/* This file is part of the ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License (LGPL) as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_gif +#define KSQUIRREL_READ_IMAGE_gif + +#define SQ_NEED_OPERATOR_RGBA_RGB + +#define DISPOSAL_NO 0 +#define DISPOSAL_LEFT 1 +#define DISPOSAL_BACKGROUND 2 +#define DISPOSAL_PREVIOUS 3 + +#endif diff --git a/kernel/kls_hdr/Makefile.am b/kernel/kls_hdr/Makefile.am new file mode 100644 index 0000000..3c76848 --- /dev/null +++ b/kernel/kls_hdr/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_hdr.la + +libkls_hdr_la_SOURCES = fmt_codec_hdr.cpp fmt_codec_hdr_defs.h + +libkls_hdr_la_LDFLAGS = ${SQ_RELEASE} + +libkls_hdr_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_hdr/fmt_codec_hdr.cpp b/kernel/kls_hdr/fmt_codec_hdr.cpp new file mode 100644 index 0000000..9819504 --- /dev/null +++ b/kernel/kls_hdr/fmt_codec_hdr.cpp @@ -0,0 +1,332 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" + +#include "fmt_codec_hdr_defs.h" +#include "fmt_codec_hdr.h" + +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "../xpm/codec_hdr.xpm" + +/* + * + * Radiance HDR image + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.1.0"; + o->name = "Radiance HDR image"; + o->filter = "*.hdr "; + o->config = ""; + o->mime = "#.RADIANCE"; + o->mimetype = "image/x-hdr"; + o->pixmap = codec_hdr; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + scanline = 0; + + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + read_error = false; + + finfo.animated = false; + + if(!getHdrHead()) return SQE_R_BADFILE; + + if(strcmp(hdr.sig, "#?RADIANCE")) return SQE_R_BADFILE; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + image.w = hdr.width; + image.h = hdr.height; + image.bpp = 32; + + scanline = new u8 [hdr.width * sizeof(RGBA)]; + + if(!scanline) return SQE_R_NOMEMORY; + + image.compression = "RGBE"; + image.colorspace = fmt_utils::colorSpaceByBpp(32); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + u32 r, g, b, e, i, j; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + if(!read_scan(scanline, im->w)) + return SQE_R_BADFILE; + + for(j = 0, i = 0; j < (u32)im->w * 4; j += 4, i++) + { + float t; + + e = scanline[j + 3]; + r = scanline[j + 0]; + g = scanline[j + 1]; + b = scanline[j + 2]; + + //t = (float)pow(2.f, ((ILint)e) - 128); + if (e != 0) + e = (e - 1) << 23; + + t = *(float *)&e; + + (scan + i)->r = u8((r / 255.0f) * t); + (scan + i)->g = u8((g / 255.0f) * t); + (scan + i)->b = u8((b / 255.0f) * t); + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); + + delete [] scanline; + scanline = 0; +} + +// +// These two methods were taken from DevIL +// http://imagelib.org +// + +bool fmt_codec::read_scan(u8 *scanline, const s32 w) +{ + u8 *runner, c; + u32 r, g, b, e, read, shift; + + if(!frs.readK(&c, sizeof(u8))) return false; r = c; + if(!frs.readK(&c, sizeof(u8))) return false; g = c; + if(!frs.readK(&c, sizeof(u8))) return false; b = c; + if(!frs.readK(&c, sizeof(u8))) return false; e = c; + + //check if the scanline is in the new format + //if so, e, r, g, g are stored separated and are + //rle-compressed independently. + if (r == 2 && g == 2) + { + u32 length = (b << 8) | e; + u32 j, t, k; + + if (length > (u32)w) + length = w; //fix broken files + + for(k = 0; k < 4; ++k) + { + runner = scanline + k; + j = 0; + + while (j < length) + { + if(!frs.readK(&c, sizeof(u8))) return false; + + t = c; + + if(t > 128) + { //Run? + if(!frs.readK(&c, sizeof(u8))) return false; + + t &= 127; + + //copy current byte + while (t > 0 && j < length) + { + *runner = c; + runner += 4; + --t; + ++j; + } + } + else + { //No Run. + //read new bytes + while (t > 0 && j < length) + { + if(!frs.readK(&c, sizeof(u8))) return false; + + *runner = c; + runner += 4; + --t; + ++j; + } + } + } + } + + return true; //done decoding a scanline in separated format + } + + //if we come here, we are dealing with old-style scanlines + shift = 0; + read = 0; + runner = scanline; + + while(read < (u32)w) + { + if (read != 0) + { + if(!frs.readK(&c, sizeof(u8))) return false; r = c; + if(!frs.readK(&c, sizeof(u8))) return false; g = c; + if(!frs.readK(&c, sizeof(u8))) return false; b = c; + if(!frs.readK(&c, sizeof(u8))) return false; e = c; + } + + //if all three mantissas are 1, then this is a rle + //count dword + if (r == 1 && g == 1 && b == 1) + { + u32 length = e; + u32 j; + + for (j = length << shift; j > 0; --j) + { + memcpy(runner, runner - 4, 4); + runner += 4; + } + //if more than one rle count dword is read + //consecutively, they are higher order bytes + //of the first read value. shift keeps track of + //that. + shift += 8; + read += length; + } + else + { + runner[0] = r; + runner[1] = g; + runner[2] = b; + runner[3] = e; + + shift = 0; + runner += 4; + ++read; + } + } + + return true; +} + +bool fmt_codec::getHdrHead() +{ + bool done = false; + s8 a, b; + s8 x[2], y[2]; + s8 buff[80]; + u32 count = 0; + + if(!frs.readK(hdr.sig, sizeof(hdr.sig)-1)) return false; + + hdr.sig[10] = '\0'; + + //skip lines until an empty line is found. + //this marks the end of header information, + //the next line contains the image's dimension. + + //TODO: read header contents into variables + //(EXPOSURE, orientation, xyz correction, ...) + + if(!frs.readK(&a, sizeof(s8))) + return false; + + while(!done) + { + if(!frs.readK(&b, sizeof(s8))) return false; + + if (b == '\n' && a == '\n') + done = true; + else + a = b; + } + + //read dimensions (note that this assumes a somewhat valid image) + if(!frs.readK(&a, sizeof(s8))) return false; + + while (a != '\n') + { + buff[count] = a; + + if(!frs.readK(&a, sizeof(s8))) return false; + + ++count; + } + + buff[count] = '\0'; + + sscanf(buff, "%s %d %s %d", x, &hdr.width, y, &hdr.height); + + return true; +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_hdr/fmt_codec_hdr_defs.h b/kernel/kls_hdr/fmt_codec_hdr_defs.h new file mode 100644 index 0000000..7689c06 --- /dev/null +++ b/kernel/kls_hdr/fmt_codec_hdr_defs.h @@ -0,0 +1,32 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_hdr +#define KSQUIRREL_CODEC_DEFS_hdr + +struct hdr_header +{ + s8 sig[11]; //must be "#?RADIANCE" + s32 width, height; + +}PACKED; + +#endif diff --git a/kernel/kls_ico/Makefile.am b/kernel/kls_ico/Makefile.am new file mode 100644 index 0000000..d81b368 --- /dev/null +++ b/kernel/kls_ico/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_ico.la + +libkls_ico_la_SOURCES = fmt_codec_ico.cpp fmt_codec_ico_defs.h + +libkls_ico_la_LDFLAGS = ${SQ_RELEASE} + +libkls_ico_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_ico/fmt_codec_ico.cpp b/kernel/kls_ico/fmt_codec_ico.cpp new file mode 100644 index 0000000..af6a2f7 --- /dev/null +++ b/kernel/kls_ico/fmt_codec_ico.cpp @@ -0,0 +1,296 @@ +/* This file is part of ksquirrel (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fmt_utils.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" + +#include "fmt_codec_ico_defs.h" +#include "fmt_codec_ico.h" + +#include "../xpm/codec_ico.xpm" + +/* + * + * An icon-resource file contains image data for icons used by Windows + * applications. The file consists of an icon directory identifying the number + * and types of icon images in the file, plus one or more icon images. The + * default filename extension for an icon-resource file is .ICO. + * +*/ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.4.2"; + o->name = "Windows icons"; + o->filter = "*.ico *.cur "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-ico"; + o->pixmap = codec_ico; + o->readable = true; + o->canbemultiple = true; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + + pal_entr = 0; + bAND = 0; + + if(!frs.readK(&ifh, sizeof(ICO_HEADER))) + return SQE_R_BADFILE; + + if(ifh.idType != 1 && ifh.idType != 2) + return SQE_R_BADFILE; + + ide = (ICO_DIRENTRY*)calloc(ifh.idCount, sizeof(ICO_DIRENTRY)); + + if(!ide) + return SQE_R_NOMEMORY; + + if(!frs.readK(ide, sizeof(ICO_DIRENTRY) * ifh.idCount)) + return SQE_R_BADFILE; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage == ifh.idCount) + return SQE_NOTOK; + + fmt_image image; + + RGBA rgba; + s32 i; + fstream::pos_type pos; + + image.w = ide[currentImage].bWidth; + image.h = ide[currentImage].bHeight; + + frs.seekg(ide[currentImage].dwImageOffset, ios::beg); + + if(!frs.readK(&bih, sizeof(BITMAPINFO_HEADER))) + return SQE_R_BADFILE; + + image.bpp = bih.BitCount; + + if(image.bpp < 16) + { + pal_entr = 1 << image.bpp; + + for(i = 0;i < pal_entr;i++) + { + if(!frs.readK(&rgba, sizeof(RGBA))) return SQE_R_BADFILE; + + pal[i].r = rgba.b; + pal[i].g = rgba.g; + pal[i].b = rgba.r; + } + } + else + { + pal_entr = 0; + } + + pos = frs.tellg(); + + s32 count = image.w * image.h; + s32 count2 = (image.bpp < 16) ? (count / (8 / image.bpp)) : (count * (image.bpp / 8)); + s32 count3 = count / 8; + + frs.seekg(/*ide[currentImage].dwBytes - sizeof(BITMAPINFO_HEADER) - */count2, ios::cur); + + bAND = (u8 *)realloc(bAND, count * sizeof(u8)); + + if(!bAND) + return SQE_R_NOMEMORY; + + u8 realAND[count3]; + + if(!frs.readK(realAND, count3)) return SQE_R_BADFILE; + + s32 r = 0; + + for(i = 0;i < count3;i++) + { + for(s32 z = 0,f = 128;z < 8;z++,f >>= 1) + { + bAND[r] = (realAND[i] & f) ? 1 : 0; + r++; + } + } + + frs.seekg(pos); + + image.needflip = true; + image.hasalpha = true; + + image.compression = "-"; + image.colorspace = ((pal_entr) ? "Color indexed":"RGB"); + + finfo.image.push_back(image); + + pixel = 0; + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + s32 i, j, count; + u8 bt, ind; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(im->bpp) + { + case 1: + j = im->w / 8; + count = 0; + + for(i = 0;i < j;i++) + { + if(!frs.readK(&bt, 1)) return SQE_R_BADFILE; + + for(s32 z = 0, f = 128;z < 8;z++,f >>= 1) + { + ind = (bt & f) ? 1 : 0; + + memcpy(scan+count, pal+ind, sizeof(RGB)); + + count++; + pixel++; + } + } + break; + + case 4: + j = 0; + do + { + if(!frs.readK(&bt, 1)) return SQE_R_BADFILE; + + ind = bt >> 4; + memcpy(scan+j, pal+ind, sizeof(RGB)); +// (scan+j)->a = (bAND[pixel]) ? 0 : 255; + j++; + pixel++; + ind = bt&15; + memcpy(scan+j, pal+ind, sizeof(RGB)); +// (scan+j)->a = (bAND[pixel]) ? 0 : 255; + j++; + pixel++; + }while(j < im->w); + + break; + + case 8: + for(i = 0;i < im->w;i++) + { + if(!frs.readK(&bt, 1)) return SQE_R_BADFILE; + + memcpy(scan+i, pal+bt, sizeof(RGB)); +// (scan+i)->a = (bAND[pixel]) ? 0 : 255; + pixel++; + } + break; + + case 24: + { + RGB rgb; + + for(i = 0;i < im->w;i++) + { + if(!frs.readK(&rgb, sizeof(RGB))) return SQE_R_BADFILE; + + (scan+i)->r = rgb.b; + (scan+i)->g = rgb.g; + (scan+i)->b = rgb.r; + pixel++; + } + } + break; + + case 32: + { + RGBA rgba; + + for(i = 0;i < im->w;i++) + { + if(!frs.readK(&rgba, sizeof(RGBA))) return SQE_R_BADFILE; + + (scan+i)->r = rgba.b; + (scan+i)->g = rgba.g; + (scan+i)->b = rgba.r; + (scan+i)->a = rgba.a; + pixel++; + } + } + break; + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + if(bAND) + free(bAND); + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_ico/fmt_codec_ico_defs.h b/kernel/kls_ico/fmt_codec_ico_defs.h new file mode 100644 index 0000000..996f40e --- /dev/null +++ b/kernel/kls_ico/fmt_codec_ico_defs.h @@ -0,0 +1,63 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_ico +#define KSQUIRREL_READ_IMAGE_ico + +struct ICO_DIRENTRY +{ + u8 bWidth; + u8 bHeight; + u8 bColorCount; + u8 bReserved; /* 0 */ + u16 wPlanes; /* 0 */ + u16 wBitCount; /* 0 */ + u32 dwBytes; + u32 dwImageOffset; + +}PACKED; + + +struct ICO_HEADER +{ + u16 idReserved; + u16 idType; /* must be 1 */ + u16 idCount; + +}PACKED; + +struct BITMAPINFO_HEADER +{ + u32 Size; + u32 Width; + u32 Height; + u16 Planes; + u16 BitCount; + u32 Compression; /* not used -->> */ + u32 SizeImage; + u32 XPelsPerMeter; + u32 YPelsPerMeter; + u32 ClrUsed; + u32 ClrImportant; + +}PACKED; + +#endif diff --git a/kernel/kls_iff/Makefile.am b/kernel/kls_iff/Makefile.am new file mode 100644 index 0000000..8b52a35 --- /dev/null +++ b/kernel/kls_iff/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I../include + +bin_SCRIPTS = ksquirrel-libs-iff2ppm + +pkglib_LTLIBRARIES = libkls_iff.la + +libkls_iff_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_iff_la_LDFLAGS = ${SQ_RELEASE} + +libkls_iff_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DCODEC_NETPBM -DCODEC_IFF -DNETPBM_S=\"${bindir}/ksquirrel-libs-iff2ppm\" + +EXTRA_DIST = ksquirrel-libs-iff2ppm.in \ No newline at end of file diff --git a/kernel/kls_iff/fmt_codec_pnm.cpp b/kernel/kls_iff/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_iff/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_iff/fmt_codec_pnm_defs.h b/kernel/kls_iff/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_iff/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_iff/ksquirrel-libs-iff2ppm.in b/kernel/kls_iff/ksquirrel-libs-iff2ppm.in new file mode 100644 index 0000000..34b68f0 --- /dev/null +++ b/kernel/kls_iff/ksquirrel-libs-iff2ppm.in @@ -0,0 +1,3 @@ +#!/bin/sh + +@ILBMTOPPM@ "$1" > "$2" \ No newline at end of file diff --git a/kernel/kls_jbig/Makefile.am b/kernel/kls_jbig/Makefile.am new file mode 100644 index 0000000..a74686f --- /dev/null +++ b/kernel/kls_jbig/Makefile.am @@ -0,0 +1,11 @@ +SUBDIRS = libjbig + +INCLUDES = -I../include -Ilibjbig + +pkglib_LTLIBRARIES = libkls_jbig.la + +libkls_jbig_la_SOURCES = fmt_codec_jbig.cpp fmt_codec_jbig_defs.h jbig2mem.cpp jbig2mem.h + +libkls_jbig_la_LDFLAGS = ${SQ_RELEASE} + +libkls_jbig_la_LIBADD = ${SQ_LOCAL_RPATH} -Llibjbig -ljbig \ No newline at end of file diff --git a/kernel/kls_jbig/fmt_codec_jbig.cpp b/kernel/kls_jbig/fmt_codec_jbig.cpp new file mode 100644 index 0000000..d1cfa81 --- /dev/null +++ b/kernel/kls_jbig/fmt_codec_jbig.cpp @@ -0,0 +1,148 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fmt_utils.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" + +#include "fmt_codec_jbig_defs.h" +#include "fmt_codec_jbig.h" + +#include "../xpm/codec_jbig.xpm" + +#include "jbig2mem.h" + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.1.1"; + o->name = "JBIG"; + o->filter = "*.jbg *.jbig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-jbig"; + o->pixmap = codec_jbig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + frs.close(); + + const char *argv[2] = + { + file.c_str(), + tmp.c_str() + }; + + if(jbig2mem((char **)argv)) + return SQE_R_NOMEMORY; + + frs.open(tmp.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + read_error = false; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + u32 w, h, bpp; + frs.readK(&w, sizeof(u32)); + frs.readK(&h, sizeof(u32)); + frs.readK(&bpp, sizeof(u32)); + + if(bpp != 24) + return SQE_R_BADFILE; + + image.w = w; + image.h = h; + image.bpp = bpp; + + image.compression = "?"; + image.colorspace = fmt_utils::colorSpaceByBpp(1); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + for(s32 i = 0;i < im->w;i++) + { + frs.readK(&rgb, sizeof(RGB)); + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_jbig/fmt_codec_jbig_defs.h b/kernel/kls_jbig/fmt_codec_jbig_defs.h new file mode 100644 index 0000000..9f9a5bc --- /dev/null +++ b/kernel/kls_jbig/fmt_codec_jbig_defs.h @@ -0,0 +1,27 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_jbig +#define KSQUIRREL_CODEC_DEFS_jbig + +// define constants here + +#endif diff --git a/kernel/kls_jbig/jbig2mem.cpp b/kernel/kls_jbig/jbig2mem.cpp new file mode 100644 index 0000000..9ae1abf --- /dev/null +++ b/kernel/kls_jbig/jbig2mem.cpp @@ -0,0 +1,270 @@ +/* + * jbgtopbm - JBIG to Portable Bitmap converter + * + * Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/jbigkit/ + * + * $Id: jbgtopbm.c,v 1.11 2004-06-11 15:17:49+01 mgk25 Exp $ + */ + +#include +#include +#include +#include + +#include "jbig.h" + +double koeff = 1.0; + +void write_it(unsigned char *data, size_t len, void *file) +{ + int bb; + unsigned char cc; + + FILE *ff = (FILE *)file; + + for(size_t i = 0;i < len;i++) + { + bb = int(koeff * (*(data+i))); + + if(bb > 255) cc = 255; + else cc = bb; + + fwrite(&cc, 1, 1, ff); + fwrite(&cc, 1, 1, ff); + fwrite(&cc, 1, 1, ff); + } +} + +int read_file(unsigned char **buf, size_t *buflen, size_t *len, FILE *f) +{ + if (*buflen == 0) { + *buflen = 4000; + *len = 0; + *buf = (unsigned char *) malloc(*buflen); + if (!*buf) { + fprintf(stderr, "Sorry, not enough memory available!\n"); + return 0; + } + } + do { + *len += fread(*buf + *len, 1, *buflen - *len, f); + if (*len == *buflen) { + *buflen *= 2; + *buf = (unsigned char *) realloc(*buf, *buflen); + if (!*buf) { + fprintf(stderr, "Sorry, not enough memory available!\n"); + return 0; + } + } + if (ferror(f)) { + perror("Problem while reading input file"); + return 0; + } + } while (!feof(f)); + *buflen = *len; + *buf = (unsigned char *) realloc(*buf, *buflen); + if (!*buf) { + fprintf(stderr, "Oops, realloc failed when shrinking buffer!\n"); + return 0; + } + + return 1; +} + +int jbig2mem (char *argv[]) +{ + FILE *fin = stdin, *fout = stdout; + const char *fnin = NULL, *fnout = NULL; + int i, result; + struct jbg_dec_state s; + unsigned char *buffer, *p; + size_t buflen, len, cnt; + unsigned long xmax = 4294967295UL, ymax = 4294967295UL, max; + int plane = -1, use_graycode = 1, multi = 0; + +printf("+JBIG %s, %s\n", argv[0], argv[1]); + + buflen = 8000; + buffer = (unsigned char *) malloc(buflen); + if (!buffer) { + return 1; + } + +fnin = argv[0]; +fnout = argv[1]; + + fin = fopen(fnin, "rb"); + if (!fin) { + free(buffer); + return 1; + } + + fout = fopen(fnout, "wb"); + if (!fout) { + fclose(fin); + free(buffer); + return 1; + } + + /* send input file to decoder */ + jbg_dec_init(&s); + jbg_dec_maxsize(&s, xmax, ymax); + /* read BIH first to check VLENGTH */ + len = fread(buffer, 1, 20, fin); + + if(len < 20) + { + fclose(fin); + fclose(fout); + remove(fnout); + return 1; + } + + if (buffer[19] & JBG_VLENGTH) { + /* VLENGTH = 1 => we might encounter a NEWLEN, therefore read entire + * input file into memory and run two passes over it */ + if(!read_file(&buffer, &buflen, &len, fin)) + { + fclose(fin); + fclose(fout); + remove(fnout); + return 1; + } + /* scan for NEWLEN marker segments and update BIE header accordingly */ + result = jbg_newlen(buffer, len); + /* feed data to decoder */ + if (result == JBG_EOK) { + p = (unsigned char *) buffer; + result = JBG_EAGAIN; + while (len > 0 && + (result == JBG_EAGAIN || (result == JBG_EOK && multi))) { + result = jbg_dec_in(&s, p, len, &cnt); + p += cnt; + len -= cnt; + } + } + } else { + /* VLENGTH = 0 => we can simply pass the input file directly to decoder */ + result = JBG_EAGAIN; + do { + cnt = 0; + p = (unsigned char *) buffer; + while (len > 0 && + (result == JBG_EAGAIN || (result == JBG_EOK && multi))) { + result = jbg_dec_in(&s, p, len, &cnt); + p += cnt; + len -= cnt; + } + if (!(result == JBG_EAGAIN || (result == JBG_EOK && multi))) + break; + len = fread(buffer, 1, buflen, fin); + } while (len > 0); + + if (ferror(fin)) { + fclose(fin); + fclose(fout); + remove(fnout); + return 1; + } + } + if (result != JBG_EOK && result != JBG_EOK_INTR) { + fprintf(stderr, "Problem with input file '%s': %s\n", + fnin, jbg_strerror(result, JBG_EN)); + + fclose(fout); + remove(fnout); + return 1; + } + if (plane >= 0 && jbg_dec_getplanes(&s) <= plane) { + fprintf(stderr, "Image has only %d planes!\n", jbg_dec_getplanes(&s)); + fclose(fout); + remove(fnout); + return 1; + } + + if (jbg_dec_getplanes(&s) == 1 || plane >= 0) + { + int w, h, bpp = 24; + + w = jbg_dec_getwidth(&s); + h = jbg_dec_getheight(&s); + + fwrite(&w, sizeof(int), 1, fout); + fwrite(&h, sizeof(int), 1, fout); + fwrite(&bpp, sizeof(int), 1, fout); + + unsigned char *d = jbg_dec_getimage(&s, plane < 0 ? 0 : plane), bt; + + int G = 0, index; + bool brk = false; + unsigned char S1; + + for(int f = 0;f < h;f++) + { + for(int i = 0, g = 0;;g++) + { + bt = *(d + G); + G++; + + for(int F = 256;F >= 2;F /= 2) + { + S1 = (unsigned char)(F / 2); + index = (bt&S1) ? 0 : 255; + + fwrite(&index, 1, 1, fout); + fwrite(&index, 1, 1, fout); + fwrite(&index, 1, 1, fout); + + if(++i >= w) + { + brk = true; + break; + } + } + + if(brk) + { + brk = false; + break; + } + } + } + } else { + /* write PGM output file */ + if ((size_t) jbg_dec_getplanes(&s) > sizeof(unsigned long) * 8) + { + fprintf(stderr, "Image has too many planes (%d)!\n", jbg_dec_getplanes(&s)); + fclose(fout); + jbg_dec_free(&s); + return 1; + } + max = 0; + for (i = jbg_dec_getplanes(&s); i > 0; i--) + max = (max << 1) | 1; + + int w, h, bpp = 24; + + w = jbg_dec_getwidth(&s); + h = jbg_dec_getheight(&s); + + fwrite(&w, sizeof(int), 1, fout); + fwrite(&h, sizeof(int), 1, fout); + fwrite(&bpp, sizeof(int), 1, fout); + + koeff = 255.0 / max; + + jbg_dec_merge_planes(&s, use_graycode, write_it, fout); + } + + /* check for file errors and close fout */ + if (ferror(fout) || fclose(fout)) { + fprintf(stderr, "Problem while writing output file '%s", fnout); + perror("'"); + jbg_dec_free(&s); + return 1; + } + + jbg_dec_free(&s); + + return 0; +} diff --git a/kernel/kls_jbig/jbig2mem.h b/kernel/kls_jbig/jbig2mem.h new file mode 100644 index 0000000..36ae619 --- /dev/null +++ b/kernel/kls_jbig/jbig2mem.h @@ -0,0 +1,6 @@ +#ifndef JBIG2MEM_H +#define JBIG2MEM_H + +int jbig2mem(char *argv[]); + +#endif diff --git a/kernel/kls_jbig/libjbig/ANNOUNCE b/kernel/kls_jbig/libjbig/ANNOUNCE new file mode 100644 index 0000000..35baa23 --- /dev/null +++ b/kernel/kls_jbig/libjbig/ANNOUNCE @@ -0,0 +1,147 @@ + +JBIG-KIT lossless image compression library +------------------------------------------- + +by Markus Kuhn + + +The latest release of JBIG-KIT can be downloaded from + + http://www.cl.cam.ac.uk/~mgk25/jbigkit/ + +JBIG-KIT implements a highly effective data compression algorithm for +bi-level high-resolution images such as fax pages or scanned +documents. + +JBIG-KIT provides a portable library of compression and decompression +functions with a documented interface. You can very easily include +into your image or document processing software. In addition, JBIG-KIT +provides ready-to-use compression and decompression programs with a +simple command line interface (similar to the converters found in Jef +Poskanzer's PBM graphics file conversion package). + +JBIG-KIT implements the specification + + International Standard ISO/IEC 11544:1993 and ITU-T Recommendation + T.82(1993), "Information technology - Coded representation of picture + and audio information - progressive bi-level image compression", + , + +which is commonly referred to as the "JBIG1 standard". JBIG (Joint +Bi-level Image experts Group) is the committee which developed this +international standard for the lossless compression of images using +arithmetic coding. Like the well-known compression algorithms JPEG and +MPEG, JBIG has also been developed and published by the International +Organization for Standardization (ISO) and the International +Telecommunication Union (ITU). See also + + http://www.jbig.org/jbighomepage.html + http://www.iso.ch/ + http://www.itu.int/ + +The JBIG compression algorithm offers the following features: + + - Close to state-of-the-art lossless compression ratio for high + resolution bi-level images. + + - About 1.1 to 1.5 times better compression ratio on typical + scanned documents compared to G4 fax compression (ITU-T T.6), + which has been the best compression algorithm for scanned + documents available prior to JBIG. + + - Up to 30 times better compression of scanned images with dithered + images compared to G4 fax compression. + + - About 2 times better compression on typical 300 dpi documents + compared to 'gzip -9' on raw bitmaps. + + - About 3-4 times better compression than GIF on typical 300 dpi + documents. + + - Even much better competitive compression results on computer + generated images which are free of scanning distortions. + + - JBIG supports hierarchical "progressive" encoding, that means it is + possible to encode a low resolution image first, followed by + resolution enhancement data. This allows, for instance, a document + browser to display already a good 75 dpi low resolution version of + an image, while the data necessary to reconstruct the full 300 dpi + version for laser printer reproduction is still arriving (say + over a slow network link or mass storage medium). + + - The various resolution layers of a JBIG image in progressive + encoding mode together require not much more space than a + normal non-progressive mode encoded image (which JBIG also + supports). + + - The progressive encoding mode utilizes a quite sophisticated + resolution reduction algorithm which offers high quality low + resolution versions that preserve the shape of characters as well + as the integrity of thin lines and dithered images. + + - JBIG supports multiple bit planes and can this way also be used + for grayscale and color images, although the main field of + application is compression of bi-level images, i.e. images with + only two different pixel values. For grayscale images with up to + 6 bit per pixel, JBIG performs superior to JPEG's lossless + mode. + +JBIG-KIT is free software under the GNU General Public License. Other +license arrangements suitable for commercial applications are +available as well, please contact the author for details. JBIG-KIT +provides a portable library implemented in ANSI/ISO C for encoding and +decoding JBIG data streams, along with documentation. The library is +not intended for 8-bit or 16-bit machine architectures (e.g., old +MS-DOS C compilers) on which a number of very efficient optimization +techniques used in this software are not possible. For maximum +performance, a 32-bit processor is required (64-bit systems work too, +of course). On architectures with 16-bit pointer arithmetic, only very +small images can be processed. + +Special features of the JBIG-KIT implementation are: + + - Fully reentrant multithread-capable design (no global or static + variables, isolated malloc()/free() calls, etc.). + + - Capable of handling incomplete and growing JBIG data streams in + order to allow earliest display of low resolution versions. + + - Capable of handling several incoming data streams simultaneously + in one single process and thread. + + - Especially designed with applications in mind that want to display + incoming data as early as possible (e.g., similar to the way in + which Netscape Navigator handles incoming GIF images). + + - Implements all JBIG features and options including progressive and + sequential encoding, multiple bit planes, user specified + resolution reduction and deterministic prediction tables, adaptive + template changes for optimal performance on half-tone images, + deterministic prediction, typical prediction in lowest and + differential layers, various stripe orderings, etc. Only the SEQ + and HITOLO options are currently not supported by the decoder + (they are normally never required, but could be added later in + case of user requirements). + + - Suitable for fax applications, satisfies ITU-T T.85 profile + + - Efficient code, optimized utilization of 32-bit processor + registers. + + - Very easy to use documented C library interface. + + - Included Gray code conversion routines for efficient encoding + of grayscale images. + + - Ready-to-use pbmtojbg and jbgtopbm converters. + +I will try to provide free support and maintenance for this software +for the foreseeable future, depending on my available time. + +Happy compressing ... + +Markus Kuhn + +-- +Markus Kuhn, Computer Laboratory, University of Cambridge +http://www.cl.cam.ac.uk/~mgk25/ || CB3 0FD, Great Britain diff --git a/kernel/kls_jbig/libjbig/COPYING b/kernel/kls_jbig/libjbig/COPYING new file mode 100644 index 0000000..a43ea21 --- /dev/null +++ b/kernel/kls_jbig/libjbig/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/kernel/kls_jbig/libjbig/Makefile.am b/kernel/kls_jbig/libjbig/Makefile.am new file mode 100644 index 0000000..4fd99b2 --- /dev/null +++ b/kernel/kls_jbig/libjbig/Makefile.am @@ -0,0 +1,5 @@ +noinst_LTLIBRARIES = libjbig.la + +libjbig_la_SOURCES = jbig.c jbig.h jbig_tab.c + +EXTRA_DIST = COPYING ANNOUNCE \ No newline at end of file diff --git a/kernel/kls_jbig/libjbig/jbig.c b/kernel/kls_jbig/libjbig/jbig.c new file mode 100644 index 0000000..6d8afa3 --- /dev/null +++ b/kernel/kls_jbig/libjbig/jbig.c @@ -0,0 +1,3190 @@ +/* + * Portable Free JBIG image compression library + * + * Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/ + * + * $Id: jbig.c,v 1.22 2004-06-11 15:17:06+01 mgk25 Exp $ + * + * This module implements a portable standard C encoder and decoder + * using the JBIG lossless bi-level image compression algorithm as + * specified in International Standard ISO 11544:1993 or equivalently + * as specified in ITU-T Recommendation T.82. See the file jbig.doc + * for usage instructions and application examples. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * If you want to use this program under different license conditions, + * then contact the author for an arrangement. + * + * It is possible that certain products which can be built using this + * software module might form inventions protected by patent rights in + * some countries (e.g., by patents about arithmetic coding algorithms + * owned by IBM and AT&T in the USA). Provision of this software by the + * author does NOT include any licences for any patents. In those + * countries where a patent licence is required for certain applications + * of this software module, you will have to obtain such a licence + * yourself. + */ + +#ifdef DEBUG +#include +#else +#define NDEBUG +#endif + +#include +#include +#include + +#include "jbig.h" + + +/* optional export of arithmetic coder functions for test purposes */ +#define ARITH static +#ifdef __GNUC__ +#define ARITH_INL static __inline__ +#else +#define ARITH_INL static +#endif + +#define MX_MAX 127 /* maximal supported mx offset for + * adaptive template in the encoder */ + +#define TPB2CX 0x195 /* contexts for TP special pixels */ +#define TPB3CX 0x0e5 +#define TPDCX 0xc3f + +/* marker codes */ +#define MARKER_STUFF 0x00 +#define MARKER_RESERVE 0x01 +#define MARKER_SDNORM 0x02 +#define MARKER_SDRST 0x03 +#define MARKER_ABORT 0x04 +#define MARKER_NEWLEN 0x05 +#define MARKER_ATMOVE 0x06 +#define MARKER_COMMENT 0x07 +#define MARKER_ESC 0xff + +/* loop array indices */ +#define STRIPE 0 +#define LAYER 1 +#define PLANE 2 + +/* special jbg_buf pointers (instead of NULL) */ +#define SDE_DONE ((struct jbg_buf *) -1) +#define SDE_TODO ((struct jbg_buf *) 0) + +/* object code version id */ + +const char jbg_version[] = +" JBIG-KIT " JBG_VERSION " -- Markus Kuhn -- " +"$Id: jbig.c,v 1.22 2004-06-11 15:17:06+01 mgk25 Exp $ "; + +/* + * the following array specifies for each combination of the 3 + * ordering bits, which ii[] variable represents which dimension + * of s->sde. + */ +static const int iindex[8][3] = { + { 2, 1, 0 }, /* no ordering bit set */ + { -1, -1, -1}, /* SMID -> illegal combination */ + { 2, 0, 1 }, /* ILEAVE */ + { 1, 0, 2 }, /* SMID + ILEAVE */ + { 0, 2, 1 }, /* SEQ */ + { 1, 2, 0 }, /* SEQ + SMID */ + { 0, 1, 2 }, /* SEQ + ILEAVE */ + { -1, -1, -1 } /* SEQ + SMID + ILEAVE -> illegal combination */ +}; + +unsigned char *jbg_next_pscdms(unsigned char *p, size_t len); + + +/* + * Array [language][message] with text string error messages that correspond + * to return values from public functions in this library. + */ +#define NEMSG 9 /* number of error codes */ +#define NEMSG_LANG 3 /* number of supported languages */ +static const char *errmsg[NEMSG_LANG][NEMSG] = { + /* English (JBG_EN) */ + { + "Everything is ok", /* JBG_EOK */ + "Reached specified maximum size", /* JBG_EOK_INTR */ + "Unexpected end of data", /* JBG_EAGAIN */ + "Not enough memory available", /* JBG_ENOMEM */ + "ABORT marker found", /* JBG_EABORT */ + "Unknown marker segment encountered", /* JBG_EMARKER */ + "Incremental BIE does not fit to previous one", /* JBG_ENOCONT */ + "Invalid data encountered", /* JBG_EINVAL */ + "Unimplemented features used" /* JBG_EIMPL */ + }, + /* German (JBG_DE_8859_1) */ + { + "Kein Problem aufgetreten", /* JBG_EOK */ + "Angegebene maximale Bildgr\366\337e erreicht", /* JBG_EOK_INTR */ + "Unerwartetes Ende der Daten", /* JBG_EAGAIN */ + "Nicht gen\374gend Speicher vorhanden", /* JBG_ENOMEM */ + "Es wurde eine Abbruch-Sequenz gefunden", /* JBG_EABORT */ + "Eine unbekannte Markierungssequenz wurde gefunden", /* JBG_EMARKER */ + "Neue Daten passen nicht zu vorangegangenen Daten", /* JBG_ENOCONT */ + "Es wurden ung\374ltige Daten gefunden", /* JBG_EINVAL */ + "Noch nicht implementierte Optionen wurden benutzt" /* JBG_EIMPL */ + }, + /* German (JBG_DE_UTF_8) */ + { + "Kein Problem aufgetreten", /* JBG_EOK */ + "Angegebene maximale Bildgr\303\266\303\237e erreicht", /* JBG_EOK_INTR */ + "Unerwartetes Ende der Daten", /* JBG_EAGAIN */ + "Nicht gen\303\274gend Speicher vorhanden", /* JBG_ENOMEM */ + "Es wurde eine Abbruch-Sequenz gefunden", /* JBG_EABORT */ + "Eine unbekannte Markierungssequenz wurde gefunden", /* JBG_EMARKER */ + "Neue Daten passen nicht zu vorangegangenen Daten", /* JBG_ENOCONT */ + "Es wurden ung\303\274ltige Daten gefunden", /* JBG_EINVAL */ + "Noch nicht implementierte Optionen wurden benutzt" /* JBG_EIMPL */ + } +}; + + + +/* + * The following three functions are the only places in this code, were + * C library memory management functions are called. The whole JBIG + * library has been designed in order to allow multi-threaded + * execution. No static or global variables are used, so all fuctions + * are fully reentrant. However if you want to use this multi-thread + * capability and your malloc, realloc and free are not reentrant, + * then simply add the necessary semaphores or mutex primitives below. + * In contrast to C's malloc() and realloc(), but like C's calloc(), + * these functions take two parameters nmemb and size that are multiplied + * before being passed on to the corresponding C function. + * This we can catch all overflows during a size_t multiplication a + * a single place. + */ + +#ifndef SIZE_MAX +#define SIZE_MAX ((size_t) -1) /* largest value of size_t */ +#endif + +static void *checked_malloc(size_t nmemb, size_t size) +{ + void *p; + + /* Full manual exception handling is ugly here for performance + * reasons. If an adequate handling of lack of memory is required, + * then use C++ and throw a C++ exception instead of abort(). */ + + /* assert that nmemb * size <= SIZE_MAX */ + if (size > SIZE_MAX / nmemb) + abort(); + + p = malloc(nmemb * size); + + if (!p) + abort(); + +#if 0 + fprintf(stderr, "%p = malloc(%lu * %lu)\n", p, + (unsigned long) nmemb, (unsigned long) size); +#endif + + return p; +} + + +static void *checked_realloc(void *ptr, size_t nmemb, size_t size) +{ + void *p; + + /* Full manual exception handling is ugly here for performance + * reasons. If an adequate handling of lack of memory is required, + * then use C++ and throw a C++ exception here instead of abort(). */ + + /* assert that nmemb * size <= SIZE_MAX */ + if (size > SIZE_MAX / nmemb) + abort(); + + p = realloc(ptr, nmemb * size); + + if (!p) + abort(); + +#if 0 + fprintf(stderr, "%p = realloc(%p, %lu * %lu)\n", p, ptr, + (unsigned long) nmemb, (unsigned long) size); +#endif + + return p; +} + + +static void checked_free(void *ptr) +{ + free(ptr); + +#if 0 + fprintf(stderr, "free(%p)\n", ptr); +#endif + +} + + + +/* + * The next functions implement the arithmedic encoder and decoder + * required for JBIG. The same algorithm is also used in the arithmetic + * variant of JPEG. + */ + +#ifdef DEBUG +static long encoded_pixels = 0; +#endif + +ARITH void arith_encode_init(struct jbg_arenc_state *s, int reuse_st) +{ + int i; + + if (!reuse_st) + for (i = 0; i < 4096; s->st[i++] = 0); + s->c = 0; + s->a = 0x10000L; + s->sc = 0; + s->ct = 11; + s->buffer = -1; /* empty */ + + return; +} + + +ARITH void arith_encode_flush(struct jbg_arenc_state *s) +{ + unsigned long temp; + +#ifdef DEBUG + fprintf(stderr, " encoded pixels = %ld, a = %05lx, c = %08lx\n", + encoded_pixels, s->a, s->c); +#endif + + /* find the s->c in the coding interval with the largest + * number of trailing zero bits */ + if ((temp = (s->a - 1 + s->c) & 0xffff0000L) < s->c) + s->c = temp + 0x8000; + else + s->c = temp; + /* send remaining bytes to output */ + s->c <<= s->ct; + if (s->c & 0xf8000000L) { + /* one final overflow has to be handled */ + if (s->buffer >= 0) { + s->byte_out(s->buffer + 1, s->file); + if (s->buffer + 1 == MARKER_ESC) + s->byte_out(MARKER_STUFF, s->file); + } + /* output 0x00 bytes only when more non-0x00 will follow */ + if (s->c & 0x7fff800L) + for (; s->sc; --s->sc) + s->byte_out(0x00, s->file); + } else { + if (s->buffer >= 0) + s->byte_out(s->buffer, s->file); + /* T.82 figure 30 says buffer+1 for the above line! Typo? */ + for (; s->sc; --s->sc) { + s->byte_out(0xff, s->file); + s->byte_out(MARKER_STUFF, s->file); + } + } + /* output final bytes only if they are not 0x00 */ + if (s->c & 0x7fff800L) { + s->byte_out((s->c >> 19) & 0xff, s->file); + if (((s->c >> 19) & 0xff) == MARKER_ESC) + s->byte_out(MARKER_STUFF, s->file); + if (s->c & 0x7f800L) { + s->byte_out((s->c >> 11) & 0xff, s->file); + if (((s->c >> 11) & 0xff) == MARKER_ESC) + s->byte_out(MARKER_STUFF, s->file); + } + } + + return; +} + + +ARITH_INL void arith_encode(struct jbg_arenc_state *s, int cx, int pix) +{ + extern short jbg_lsz[]; + extern unsigned char jbg_nmps[], jbg_nlps[]; + register unsigned lsz, ss; + register unsigned char *st; + long temp; + +#ifdef DEBUG + ++encoded_pixels; +#endif + + assert(cx >= 0 && cx < 4096); + st = s->st + cx; + ss = *st & 0x7f; + assert(ss < 113); + lsz = jbg_lsz[ss]; + +#if 0 + fprintf(stderr, "pix = %d, cx = %d, mps = %d, st = %3d, lsz = 0x%04x, " + "a = 0x%05lx, c = 0x%08lx, ct = %2d, buf = 0x%02x\n", + pix, cx, !!(s->st[cx] & 0x80), ss, lsz, s->a, s->c, s->ct, + s->buffer); +#endif + + if (((pix << 7) ^ s->st[cx]) & 0x80) { + /* encode the less probable symbol */ + if ((s->a -= lsz) >= lsz) { + /* If the interval size (lsz) for the less probable symbol (LPS) + * is larger than the interval size for the MPS, then exchange + * the two symbols for coding efficiency, otherwise code the LPS + * as usual: */ + s->c += s->a; + s->a = lsz; + } + /* Check whether MPS/LPS exchange is necessary + * and chose next probability estimator status */ + *st &= 0x80; + *st ^= jbg_nlps[ss]; + } else { + /* encode the more probable symbol */ + if ((s->a -= lsz) & 0xffff8000L) + return; /* A >= 0x8000 -> ready, no renormalization required */ + if (s->a < lsz) { + /* If the interval size (lsz) for the less probable symbol (LPS) + * is larger than the interval size for the MPS, then exchange + * the two symbols for coding efficiency: */ + s->c += s->a; + s->a = lsz; + } + /* chose next probability estimator status */ + *st &= 0x80; + *st |= jbg_nmps[ss]; + } + + /* renormalization of coding interval */ + do { + s->a <<= 1; + s->c <<= 1; + --s->ct; + if (s->ct == 0) { + /* another byte is ready for output */ + temp = s->c >> 19; + if (temp & 0xffffff00L) { + /* handle overflow over all buffered 0xff bytes */ + if (s->buffer >= 0) { + ++s->buffer; + s->byte_out(s->buffer, s->file); + if (s->buffer == MARKER_ESC) + s->byte_out(MARKER_STUFF, s->file); + } + for (; s->sc; --s->sc) + s->byte_out(0x00, s->file); + s->buffer = temp & 0xff; /* new output byte, might overflow later */ + assert(s->buffer != 0xff); + /* can s->buffer really never become 0xff here? */ + } else if (temp == 0xff) { + /* buffer 0xff byte (which might overflow later) */ + ++s->sc; + } else { + /* output all buffered 0xff bytes, they will not overflow any more */ + if (s->buffer >= 0) + s->byte_out(s->buffer, s->file); + for (; s->sc; --s->sc) { + s->byte_out(0xff, s->file); + s->byte_out(MARKER_STUFF, s->file); + } + s->buffer = temp; /* buffer new output byte (can still overflow) */ + } + s->c &= 0x7ffffL; + s->ct = 8; + } + } while (s->a < 0x8000); + + return; +} + + +ARITH void arith_decode_init(struct jbg_ardec_state *s, int reuse_st) +{ + int i; + + if (!reuse_st) + for (i = 0; i < 4096; s->st[i++] = 0); + s->c = 0; + s->a = 1; + s->ct = 0; + s->result = JBG_OK; + s->startup = 1; + return; +} + + +ARITH_INL int arith_decode(struct jbg_ardec_state *s, int cx) +{ + extern short jbg_lsz[]; + extern unsigned char jbg_nmps[], jbg_nlps[]; + register unsigned lsz, ss; + register unsigned char *st; + int pix; + + /* renormalization */ + while (s->a < 0x8000 || s->startup) { + if (s->ct < 1 && s->result != JBG_READY) { + /* first we have to move a new byte into s->c */ + if (s->pscd_ptr >= s->pscd_end) { + s->result = JBG_MORE; + return -1; + } + if (*s->pscd_ptr == 0xff) + if (s->pscd_ptr + 1 >= s->pscd_end) { + s->result = JBG_MARKER; + return -1; + } else { + if (*(s->pscd_ptr + 1) == MARKER_STUFF) { + s->c |= 0xffL << (8 - s->ct); + s->ct += 8; + s->pscd_ptr += 2; + s->result = JBG_OK; + } else + s->result = JBG_READY; + } + else { + s->c |= (long)*(s->pscd_ptr++) << (8 - s->ct); + s->ct += 8; + s->result = JBG_OK; + } + } + s->c <<= 1; + s->a <<= 1; + --s->ct; + if (s->a == 0x10000L) + s->startup = 0; + } + + st = s->st + cx; + ss = *st & 0x7f; + assert(ss < 113); + lsz = jbg_lsz[ss]; + +#if 0 + fprintf(stderr, "cx = %d, mps = %d, st = %3d, lsz = 0x%04x, a = 0x%05lx, " + "c = 0x%08lx, ct = %2d\n", + cx, !!(s->st[cx] & 0x80), ss, lsz, s->a, s->c, s->ct); +#endif + + if ((s->c >> 16) < (s->a -= lsz)) + if (s->a & 0xffff8000L) + return *st >> 7; + else { + /* MPS_EXCHANGE */ + if (s->a < lsz) { + pix = 1 - (*st >> 7); + /* Check whether MPS/LPS exchange is necessary + * and chose next probability estimator status */ + *st &= 0x80; + *st ^= jbg_nlps[ss]; + } else { + pix = *st >> 7; + *st &= 0x80; + *st |= jbg_nmps[ss]; + } + } + else { + /* LPS_EXCHANGE */ + if (s->a < lsz) { + s->c -= s->a << 16; + s->a = lsz; + pix = *st >> 7; + *st &= 0x80; + *st |= jbg_nmps[ss]; + } else { + s->c -= s->a << 16; + s->a = lsz; + pix = 1 - (*st >> 7); + /* Check whether MPS/LPS exchange is necessary + * and chose next probability estimator status */ + *st &= 0x80; + *st ^= jbg_nlps[ss]; + } + } + + return pix; +} + + + +/* + * Memory management for buffers which are used for temporarily + * storing SDEs by the encoder. + * + * The following functions manage a set of struct jbg_buf storage + * containers were each can keep JBG_BUFSIZE bytes. The jbg_buf + * containers can be linked to form linear double-chained lists for + * which a number of operations are provided. Blocks which are + * tempoarily not used any more are returned to a freelist which each + * encoder keeps. Only the destructor of the encoder actually returns + * the block via checked_free() to the stdlib memory management. + */ + + +/* + * Allocate a new buffer block and initialize it. Try to get it from + * the free_list, and if it is empty, call checked_malloc(). + */ +static struct jbg_buf *jbg_buf_init(struct jbg_buf **free_list) +{ + struct jbg_buf *new_block; + + /* Test whether a block from the free list is available */ + if (*free_list) { + new_block = *free_list; + *free_list = new_block->next; + } else { + /* request a new memory block */ + new_block = (struct jbg_buf *) checked_malloc(1, sizeof(struct jbg_buf)); + } + new_block->len = 0; + new_block->next = NULL; + new_block->previous = NULL; + new_block->last = new_block; + new_block->free_list = free_list; + + return new_block; +} + + +/* + * Return an entire free_list to the memory management of stdlib. + * This is only done by jbg_enc_free(). + */ +static void jbg_buf_free(struct jbg_buf **free_list) +{ + struct jbg_buf *tmp; + + while (*free_list) { + tmp = (*free_list)->next; + checked_free(*free_list); + *free_list = tmp; + } + + return; +} + + +/* + * Append a single byte to a single list that starts with the block + * *(struct jbg_buf *) head. The type of *head is void here in order to + * keep the interface of the arithmetic encoder gereric, which uses this + * function as a call-back function in order to deliver single bytes + * for a PSCD. + */ +static void jbg_buf_write(int b, void *head) +{ + struct jbg_buf *now; + + now = ((struct jbg_buf *) head)->last; + if (now->len < JBG_BUFSIZE - 1) { + now->d[now->len++] = b; + return; + } + now->next = jbg_buf_init(((struct jbg_buf *) head)->free_list); + now->next->previous = now; + now->next->d[now->next->len++] = b; + ((struct jbg_buf *) head)->last = now->next; + + return; +} + + +/* + * Remove any trailing zero bytes from the end of a linked jbg_buf list, + * however make sure that no zero byte is removed which directly + * follows a 0xff byte (i.e., keep MARKER_ESC MARKER_STUFF sequences + * intact). This function is used to remove any redundant final zero + * bytes from a PSCD. + */ +static void jbg_buf_remove_zeros(struct jbg_buf *head) +{ + struct jbg_buf *last; + + while (1) { + /* remove trailing 0x00 in last block of list until this block is empty */ + last = head->last; + while (last->len && last->d[last->len - 1] == 0) + last->len--; + /* if block became really empty, remove it in case it is not the + * only remaining block and then loop to next block */ + if (last->previous && !last->len) { + head->last->next = *head->free_list; + *head->free_list = head->last; + head->last = last->previous; + head->last->next = NULL; + } else + break; + } + + /* + * If the final non-zero byte is 0xff (MARKER_ESC), then we just have + * removed a MARKER_STUFF and we will append it again now in order + * to preserve PSCD status of byte stream. + */ + if (head->last->len && head->last->d[head->last->len - 1] == MARKER_ESC) + jbg_buf_write(MARKER_STUFF, head); + + return; +} + + +/* + * The jbg_buf list which starts with block *new_prefix is concatenated + * with the list which starts with block **start and *start will then point + * to the first block of the new list. + */ +static void jbg_buf_prefix(struct jbg_buf *new_prefix, struct jbg_buf **start) +{ + new_prefix->last->next = *start; + new_prefix->last->next->previous = new_prefix->last; + new_prefix->last = new_prefix->last->next->last; + *start = new_prefix; + + return; +} + + +/* + * Send the contents of a jbg_buf list that starts with block **head to + * the call back function data_out and return the blocks of the jbg_buf + * list to the freelist from which these jbg_buf blocks have been taken. + * After the call, *head == NULL. + */ +static void jbg_buf_output(struct jbg_buf **head, + void (*data_out)(unsigned char *start, + size_t len, void *file), + void *file) +{ + struct jbg_buf *tmp; + + while (*head) { + data_out((*head)->d, (*head)->len, file); + tmp = (*head)->next; + (*head)->next = *(*head)->free_list; + *(*head)->free_list = *head; + *head = tmp; + } + + return; +} + + +/* + * Calculate y = ceil(x/2) applied n times, which is equivalent to + * y = ceil(x/(2^n)). This function is used to + * determine the number of pixels per row or column after n resolution + * reductions. E.g. X[d-1] = jbg_ceil_half(X[d], 1) and X[0] = + * jbg_ceil_half(X[d], d) as defined in clause 6.2.3 of T.82. + */ +unsigned long jbg_ceil_half(unsigned long x, int n) +{ + unsigned long mask; + + assert(n >= 0 && n < 32); + mask = (1UL << n) - 1; /* the lowest n bits are 1 here */ + return (x >> n) + ((mask & x) != 0); +} + + +/* + * Set L0 (the number of lines in a stripe at lowest resolution) + * to a default value, such that there are about 35 stripes, as + * suggested in Annex C of ITU-T T.82, without exceeding the + * limit 128/2^D suggested in Annex A. + */ +static void jbg_set_default_l0(struct jbg_enc_state *s) +{ + s->l0 = jbg_ceil_half(s->yd, s->d) / 35; /* 35 stripes/image */ + while ((s->l0 << s->d) > 128) /* but <= 128 lines/stripe */ + --s->l0; + if (s->l0 < 2) s->l0 = 2; +} + + +/* + * Calculate the number of stripes, as defined in clause 6.2.3 of T.82. + */ +static unsigned long jbg_stripes(unsigned long l0, unsigned long yd, + unsigned long d) +{ + unsigned long y0 = jbg_ceil_half(yd, d); + + return y0 / l0 + (y0 % l0 != 0); +} + + +/* + * Initialize the status struct for the encoder. + */ +void jbg_enc_init(struct jbg_enc_state *s, unsigned long x, unsigned long y, + int planes, unsigned char **p, + void (*data_out)(unsigned char *start, size_t len, + void *file), + void *file) +{ + unsigned long l, lx; + int i; + + extern char jbg_resred[], jbg_dptable[]; + + s->xd = x; + s->yd = y; + s->yd1 = y; /* This is the hight initially announced in BIH. To provoke + generation of NEWLEN for T.85 compatibility tests, + overwrite with new value s->yd1 > s->yd */ + s->planes = planes; + s->data_out = data_out; + s->file = file; + + s->d = 0; + s->dl = 0; + s->dh = s->d; + jbg_set_default_l0(s); + s->mx = 8; + s->my = 0; + s->order = JBG_ILEAVE | JBG_SMID; + s->options = JBG_TPBON | JBG_TPDON | JBG_DPON; + s->dppriv = jbg_dptable; + s->res_tab = jbg_resred; + + s->highres = (int *) checked_malloc(planes, sizeof(int)); + s->lhp[0] = p; + s->lhp[1] = (unsigned char **) + checked_malloc(planes, sizeof(unsigned char *)); + for (i = 0; i < planes; i++) { + s->highres[i] = 0; + s->lhp[1][i] = (unsigned char *) + checked_malloc(jbg_ceil_half(y, 1), jbg_ceil_half(x, 1+3)); + } + + s->free_list = NULL; + s->s = (struct jbg_arenc_state *) + checked_malloc(s->planes, sizeof(struct jbg_arenc_state)); + s->tx = (int *) checked_malloc(s->planes, sizeof(int)); + lx = jbg_ceil_half(x, 1); + s->tp = (char *) checked_malloc(lx, sizeof(char)); + for (l = 0; l < lx; s->tp[l++] = 2); + s->sde = NULL; + + return; +} + + +/* + * This function selects the number of differential layers based on + * the maximum size requested for the lowest resolution layer. If + * possible, a number of differential layers is selected, which will + * keep the size of the lowest resolution layer below or equal to the + * given width x and height y. However not more than 6 differential + * resolution layers will be used. In addition, a reasonable value for + * l0 (height of one stripe in the lowest resolution layer) is + * selected, which obeys the recommended limitations for l0 in annex A + * and C of the JBIG standard. The selected number of resolution layers + * is returned. + */ +int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long x, + unsigned long y) +{ + for (s->d = 0; s->d < 6; s->d++) + if (jbg_ceil_half(s->xd, s->d) <= x && jbg_ceil_half(s->yd, s->d) <= y) + break; + s->dl = 0; + s->dh = s->d; + jbg_set_default_l0(s); + return s->d; +} + + +/* + * As an alternative to jbg_enc_lrlmax(), the following function allows + * to specify the number of layers directly. The stripe height and layer + * range is also adjusted automatically here. + */ +void jbg_enc_layers(struct jbg_enc_state *s, int d) +{ + if (d < 0 || d > 31) + return; + s->d = d; + s->dl = 0; + s->dh = s->d; + jbg_set_default_l0(s); + return; +} + + +/* + * Specify the highest and lowest resolution layers which will be + * written to the output file. Call this function not before + * jbg_enc_layers() or jbg_enc_lrlmax(), because these two functions + * reset the lowest and highest resolution layer to default values. + * Negative values are ignored. The total number of layers is returned. + */ +int jbg_enc_lrange(struct jbg_enc_state *s, int dl, int dh) +{ + if (dl >= 0 && dl <= s->d) s->dl = dl; + if (dh >= s->dl && dh <= s->d) s->dh = dh; + + return s->d; +} + + +/* + * The following function allows to specify the bits describing the + * options of the format as well as the maximum AT movement window and + * the number of layer 0 lines per stripes. + */ +void jbg_enc_options(struct jbg_enc_state *s, int order, int options, + unsigned long l0, int mx, int my) +{ + if (order >= 0 && order <= 0x0f) s->order = order; + if (options >= 0) s->options = options; + if (l0 > 0) s->l0 = l0; + if (mx >= 0 && my < 128) s->mx = mx; + if (my >= 0 && my < 256) s->my = my; + + return; +} + + +/* + * This function actually does all the tricky work involved in producing + * a SDE, which is stored in the appropriate s->sde[][][] element + * for later output in the correct order. + */ +static void encode_sde(struct jbg_enc_state *s, + long stripe, int layer, int plane) +{ + unsigned char *hp, *lp1, *lp2, *p0, *p1, *q1, *q2; + unsigned long hl, ll, hx, hy, lx, ly, hbpl, lbpl; + unsigned long line_h0 = 0, line_h1 = 0; + unsigned long line_h2, line_h3, line_l1, line_l2, line_l3; + struct jbg_arenc_state *se; + unsigned long i, j, y; + long o; + unsigned a, p, t; + int ltp, ltp_old, cx; + unsigned long c_all, c[MX_MAX + 1], cmin, cmax, clmin, clmax; + int tmax, at_determined; + int new_tx; + long new_tx_line = -1; + struct jbg_buf *new_jbg_buf; + +#ifdef DEBUG + static long tp_lines, tp_exceptions, tp_pixels, dp_pixels; + static long encoded_pixels; +#endif + + /* return immediately if this stripe has already been encoded */ + if (s->sde[stripe][layer][plane] != SDE_TODO) + return; + +#ifdef DEBUG + if (stripe == 0) + tp_lines = tp_exceptions = tp_pixels = dp_pixels = encoded_pixels = 0; + fprintf(stderr, "encode_sde: s/d/p = %2ld/%2d/%2d\n", + stripe, layer, plane); +#endif + + /* number of lines per stripe in highres image */ + hl = s->l0 << layer; + /* number of lines per stripe in lowres image */ + ll = hl >> 1; + /* current line number in highres image */ + y = stripe * hl; + /* number of pixels in highres image */ + hx = jbg_ceil_half(s->xd, s->d - layer); + hy = jbg_ceil_half(s->yd, s->d - layer); + /* number of pixels in lowres image */ + lx = jbg_ceil_half(hx, 1); + ly = jbg_ceil_half(hy, 1); + /* bytes per line in highres and lowres image */ + hbpl = jbg_ceil_half(hx, 3); + lbpl = jbg_ceil_half(lx, 3); + /* pointer to first image byte of highres stripe */ + hp = s->lhp[s->highres[plane]][plane] + stripe * hl * hbpl; + lp2 = s->lhp[1 - s->highres[plane]][plane] + stripe * ll * lbpl; + lp1 = lp2 + lbpl; + + /* initialize arithmetic encoder */ + se = s->s + plane; + arith_encode_init(se, stripe != 0); + s->sde[stripe][layer][plane] = jbg_buf_init(&s->free_list); + se->byte_out = jbg_buf_write; + se->file = s->sde[stripe][layer][plane]; + + /* initialize adaptive template movement algorithm */ + c_all = 0; + for (t = 0; t <= s->mx; t++) + c[t] = 0; + if (stripe == 0) + s->tx[plane] = 0; + new_tx = -1; + at_determined = 0; /* we haven't yet decided the template move */ + if (s->mx == 0) + at_determined = 1; + + /* initialize typical prediction */ + ltp = 0; + if (stripe == 0) + ltp_old = 0; + else { + ltp_old = 1; + p1 = hp - hbpl; + if (y > 1) { + q1 = p1 - hbpl; + while (p1 < hp && (ltp_old = (*p1++ == *q1++)) != 0); + } else + while (p1 < hp && (ltp_old = (*p1++ == 0)) != 0); + } + + if (layer == 0) { + + /* + * Encode lowest resolution layer + */ + + for (i = 0; i < hl && y < hy; i++, y++) { + + /* check whether it is worth to perform an ATMOVE */ + if (!at_determined && c_all > 2048) { + cmin = clmin = 0xffffffffL; + cmax = clmax = 0; + tmax = 0; + for (t = (s->options & JBG_LRLTWO) ? 5 : 3; t <= s->mx; t++) { + if (c[t] > cmax) cmax = c[t]; + if (c[t] < cmin) cmin = c[t]; + if (c[t] > c[tmax]) tmax = t; + } + clmin = (c[0] < cmin) ? c[0] : cmin; + clmax = (c[0] > cmax) ? c[0] : cmax; + if (c_all - cmax < (c_all >> 3) && + cmax - c[s->tx[plane]] > c_all - cmax && + cmax - c[s->tx[plane]] > (c_all >> 4) && + /* ^ T.82 said < here, fixed in Cor.1/25 */ + cmax - (c_all - c[s->tx[plane]]) > c_all - cmax && + cmax - (c_all - c[s->tx[plane]]) > (c_all >> 4) && + cmax - cmin > (c_all >> 2) && + (s->tx[plane] || clmax - clmin > (c_all >> 3))) { + /* we have decided to perform an ATMOVE */ + new_tx = tmax; + if (!(s->options & JBG_DELAY_AT)) { + new_tx_line = i; + s->tx[plane] = new_tx; + } +#ifdef DEBUG + fprintf(stderr, "ATMOVE: line=%ld, tx=%d, c_all=%ld\n", + i, new_tx, c_all); +#endif + } + at_determined = 1; + } + assert(s->tx[plane] >= 0); /* i.e., tx can safely be cast to unsigned */ + + /* typical prediction */ + if (s->options & JBG_TPBON) { + ltp = 1; + p1 = hp; + if (y > 0) { + q1 = hp - hbpl; + while (q1 < hp && (ltp = (*p1++ == *q1++)) != 0); + } else + while (p1 < hp + hbpl && (ltp = (*p1++ == 0)) != 0); + arith_encode(se, (s->options & JBG_LRLTWO) ? TPB2CX : TPB3CX, + ltp == ltp_old); +#ifdef DEBUG + tp_lines += ltp; +#endif + ltp_old = ltp; + if (ltp) { + /* skip next line */ + hp += hbpl; + continue; + } + } + + /* + * Layout of the variables line_h1, line_h2, line_h3, which contain + * as bits the neighbour pixels of the currently coded pixel X: + * + * 76543210765432107654321076543210 line_h3 + * 76543210765432107654321076543210 line_h2 + * 76543210765432107654321X76543210 line_h1 + */ + + line_h1 = line_h2 = line_h3 = 0; + if (y > 0) line_h2 = (long)*(hp - hbpl) << 8; + if (y > 1) line_h3 = (long)*(hp - hbpl - hbpl) << 8; + + /* encode line */ + for (j = 0; j < hx; hp++) { + line_h1 |= *hp; + if (j < hbpl * 8 - 8 && y > 0) { + line_h2 |= *(hp - hbpl + 1); + if (y > 1) + line_h3 |= *(hp - hbpl - hbpl + 1); + } + if (s->options & JBG_LRLTWO) { + /* two line template */ + do { + line_h1 <<= 1; line_h2 <<= 1; line_h3 <<= 1; + if (s->tx[plane]) { + if ((unsigned) s->tx[plane] > j) + a = 0; + else { + o = (j - s->tx[plane]) - (j & ~7L); + a = (hp[o >> 3] >> (7 - (o & 7))) & 1; + a <<= 4; + } + assert(s->tx[plane] > 23 || + a == ((line_h1 >> (4 + s->tx[plane])) & 0x010)); + arith_encode(se, (((line_h2 >> 10) & 0x3e0) | a | + ((line_h1 >> 9) & 0x00f)), + (line_h1 >> 8) & 1); + } + else + arith_encode(se, (((line_h2 >> 10) & 0x3f0) | + ((line_h1 >> 9) & 0x00f)), + (line_h1 >> 8) & 1); +#ifdef DEBUG + encoded_pixels++; +#endif + /* statistics for adaptive template changes */ + if (!at_determined && j >= s->mx && j < hx-2) { + p = (line_h1 & 0x100) != 0; /* current pixel value */ + c[0] += ((line_h2 & 0x4000) != 0) == p; /* default position */ + assert(!(((line_h2 >> 6) ^ line_h1) & 0x100) == + (((line_h2 & 0x4000) != 0) == p)); + for (t = 5; t <= s->mx && t <= j; t++) { + o = (j - t) - (j & ~7L); + a = (hp[o >> 3] >> (7 - (o & 7))) & 1; + assert(t > 23 || + (a == p) == !(((line_h1 >> t) ^ line_h1) & 0x100)); + c[t] += a == p; + } + for (; t <= s->mx; t++) { + c[t] += 0 == p; + } + ++c_all; + } + } while (++j & 7 && j < hx); + } else { + /* three line template */ + do { + line_h1 <<= 1; line_h2 <<= 1; line_h3 <<= 1; + if (s->tx[plane]) { + if ((unsigned) s->tx[plane] > j) + a = 0; + else { + o = (j - s->tx[plane]) - (j & ~7L); + a = (hp[o >> 3] >> (7 - (o & 7))) & 1; + a <<= 2; + } + assert(s->tx[plane] > 23 || + a == ((line_h1 >> (6 + s->tx[plane])) & 0x004)); + arith_encode(se, (((line_h3 >> 8) & 0x380) | + ((line_h2 >> 12) & 0x078) | a | + ((line_h1 >> 9) & 0x003)), + (line_h1 >> 8) & 1); + } else + arith_encode(se, (((line_h3 >> 8) & 0x380) | + ((line_h2 >> 12) & 0x07c) | + ((line_h1 >> 9) & 0x003)), + (line_h1 >> 8) & 1); +#ifdef DEBUG + encoded_pixels++; +#endif + /* statistics for adaptive template changes */ + if (!at_determined && j >= s->mx && j < hx-2) { + p = (line_h1 & 0x100) != 0; /* current pixel value */ + c[0] += ((line_h2 & 0x4000) != 0) == p; /* default position */ + assert(!(((line_h2 >> 6) ^ line_h1) & 0x100) == + (((line_h2 & 0x4000) != 0) == p)); + for (t = 3; t <= s->mx && t <= j; t++) { + o = (j - t) - (j & ~7L); + a = (hp[o >> 3] >> (7 - (o & 7))) & 1; + assert(t > 23 || + (a == p) == !(((line_h1 >> t) ^ line_h1) & 0x100)); + c[t] += a == p; + } + for (; t <= s->mx; t++) { + c[t] += 0 == p; + } + ++c_all; + } + } while (++j & 7 && j < hx); + } /* if (s->options & JBG_LRLTWO) */ + } /* for (j = ...) */ + } /* for (i = ...) */ + + } else { + + /* + * Encode differential layer + */ + + for (i = 0; i < hl && y < hy; i++, y++) { + + /* check whether it is worth to perform an ATMOVE */ + if (!at_determined && c_all > 2048) { + cmin = clmin = 0xffffffffL; + cmax = clmax = 0; + tmax = 0; + for (t = 3; t <= s->mx; t++) { + if (c[t] > cmax) cmax = c[t]; + if (c[t] < cmin) cmin = c[t]; + if (c[t] > c[tmax]) tmax = t; + } + clmin = (c[0] < cmin) ? c[0] : cmin; + clmax = (c[0] > cmax) ? c[0] : cmax; + if (c_all - cmax < (c_all >> 3) && + cmax - c[s->tx[plane]] > c_all - cmax && + cmax - c[s->tx[plane]] > (c_all >> 4) && + /* ^ T.82 said < here, fixed in Cor.1/25 */ + cmax - (c_all - c[s->tx[plane]]) > c_all - cmax && + cmax - (c_all - c[s->tx[plane]]) > (c_all >> 4) && + cmax - cmin > (c_all >> 2) && + (s->tx[plane] || clmax - clmin > (c_all >> 3))) { + /* we have decided to perform an ATMOVE */ + new_tx = tmax; + if (!(s->options & JBG_DELAY_AT)) { + new_tx_line = i; + s->tx[plane] = new_tx; + } +#ifdef DEBUG + fprintf(stderr, "ATMOVE: line=%ld, tx=%d, c_all=%ld\n", + i, new_tx, c_all); +#endif + } + at_determined = 1; + } + + if ((i >> 1) >= ll - 1 || (y >> 1) >= ly - 1) + lp1 = lp2; + + /* typical prediction */ + if (s->options & JBG_TPDON && (i & 1) == 0) { + q1 = lp1; q2 = lp2; + p0 = p1 = hp; + if (i < hl - 1 && y < hy - 1) + p0 = hp + hbpl; + if (y > 1) + line_l3 = (long)*(q2 - lbpl) << 8; + else + line_l3 = 0; + line_l2 = (long)*q2 << 8; + line_l1 = (long)*q1 << 8; + ltp = 1; + for (j = 0; j < lx && ltp; q1++, q2++) { + if (j < lbpl * 8 - 8) { + if (y > 1) + line_l3 |= *(q2 - lbpl + 1); + line_l2 |= *(q2 + 1); + line_l1 |= *(q1 + 1); + } + do { + if ((j >> 2) < hbpl) { + line_h1 = *(p1++); + line_h0 = *(p0++); + } + do { + line_l3 <<= 1; + line_l2 <<= 1; + line_l1 <<= 1; + line_h1 <<= 2; + line_h0 <<= 2; + cx = (((line_l3 >> 15) & 0x007) | + ((line_l2 >> 12) & 0x038) | + ((line_l1 >> 9) & 0x1c0)); + if (cx == 0x000) + if ((line_h1 & 0x300) == 0 && (line_h0 & 0x300) == 0) + s->tp[j] = 0; + else { + ltp = 0; +#ifdef DEBUG + tp_exceptions++; +#endif + } + else if (cx == 0x1ff) + if ((line_h1 & 0x300) == 0x300 && (line_h0 & 0x300) == 0x300) + s->tp[j] = 1; + else { + ltp = 0; +#ifdef DEBUG + tp_exceptions++; +#endif + } + else + s->tp[j] = 2; + } while (++j & 3 && j < lx); + } while (j & 7 && j < lx); + } /* for (j = ...) */ + arith_encode(se, TPDCX, !ltp); +#ifdef DEBUG + tp_lines += ltp; +#endif + } + + + /* + * Layout of the variables line_h1, line_h2, line_h3, which contain + * as bits the high resolution neighbour pixels of the currently coded + * highres pixel X: + * + * 76543210 76543210 76543210 76543210 line_h3 + * 76543210 76543210 76543210 76543210 line_h2 + * 76543210 76543210 7654321X 76543210 line_h1 + * + * Layout of the variables line_l1, line_l2, line_l3, which contain + * the low resolution pixels near the currently coded pixel as bits. + * The lowres pixel in which the currently coded highres pixel is + * located is marked as Y: + * + * 76543210 76543210 76543210 76543210 line_l3 + * 76543210 7654321Y 76543210 76543210 line_l2 + * 76543210 76543210 76543210 76543210 line_l1 + */ + + + line_h1 = line_h2 = line_h3 = line_l1 = line_l2 = line_l3 = 0; + if (y > 0) line_h2 = (long)*(hp - hbpl) << 8; + if (y > 1) { + line_h3 = (long)*(hp - hbpl - hbpl) << 8; + line_l3 = (long)*(lp2 - lbpl) << 8; + } + line_l2 = (long)*lp2 << 8; + line_l1 = (long)*lp1 << 8; + + /* encode line */ + for (j = 0; j < hx; lp1++, lp2++) { + if ((j >> 1) < lbpl * 8 - 8) { + if (y > 1) + line_l3 |= *(lp2 - lbpl + 1); + line_l2 |= *(lp2 + 1); + line_l1 |= *(lp1 + 1); + } + do { /* ... while (j & 15 && j < hx) */ + + assert(hp - (s->lhp[s->highres[plane]][plane] + + (stripe * hl + i) * hbpl) + == (ptrdiff_t) j >> 3); + + assert(lp2 - (s->lhp[1-s->highres[plane]][plane] + + (stripe * ll + (i>>1)) * lbpl) + == (ptrdiff_t) j >> 4); + + line_h1 |= *hp; + if (j < hbpl * 8 - 8) { + if (y > 0) { + line_h2 |= *(hp - hbpl + 1); + if (y > 1) + line_h3 |= *(hp - hbpl - hbpl + 1); + } + } + do { /* ... while (j & 7 && j < hx) */ + line_l1 <<= 1; line_l2 <<= 1; line_l3 <<= 1; + if (ltp && s->tp[j >> 1] < 2) { + /* pixel are typical and have not to be encoded */ + line_h1 <<= 2; line_h2 <<= 2; line_h3 <<= 2; +#ifdef DEBUG + do { + ++tp_pixels; + } while (++j & 1 && j < hx); +#else + j += 2; +#endif + } else + do { /* ... while (++j & 1 && j < hx) */ + line_h1 <<= 1; line_h2 <<= 1; line_h3 <<= 1; + + /* deterministic prediction */ + if (s->options & JBG_DPON) { + if ((y & 1) == 0) { + if ((j & 1) == 0) { + /* phase 0 */ + if (s->dppriv[((line_l3 >> 16) & 0x003) | + ((line_l2 >> 14) & 0x00c) | + ((line_h1 >> 5) & 0x010) | + ((line_h2 >> 10) & 0x0e0)] < 2) { +#ifdef DEBUG + ++dp_pixels; +#endif + continue; + } + } else { + /* phase 1 */ + if (s->dppriv[(((line_l3 >> 16) & 0x003) | + ((line_l2 >> 14) & 0x00c) | + ((line_h1 >> 5) & 0x030) | + ((line_h2 >> 10) & 0x1c0)) + 256] < 2) { +#ifdef DEBUG + ++dp_pixels; +#endif + continue; + } + } + } else { + if ((j & 1) == 0) { + /* phase 2 */ + if (s->dppriv[(((line_l3 >> 16) & 0x003) | + ((line_l2 >> 14) & 0x00c) | + ((line_h1 >> 5) & 0x010) | + ((line_h2 >> 10) & 0x0e0) | + ((line_h3 >> 7) & 0x700)) + 768] < 2) { +#ifdef DEBUG + ++dp_pixels; +#endif + continue; + } + } else { + /* phase 3 */ + if (s->dppriv[(((line_l3 >> 16) & 0x003) | + ((line_l2 >> 14) & 0x00c) | + ((line_h1 >> 5) & 0x030) | + ((line_h2 >> 10) & 0x1c0) | + ((line_h3 >> 7) & 0xe00)) + 2816] < 2) { +#ifdef DEBUG + ++dp_pixels; +#endif + continue; + } + } + } + } + + /* determine context */ + if (s->tx[plane]) { + if ((unsigned) s->tx[plane] > j) + a = 0; + else { + o = (j - s->tx[plane]) - (j & ~7L); + a = (hp[o >> 3] >> (7 - (o & 7))) & 1; + a <<= 4; + } + assert(s->tx[plane] > 23 || + a == ((line_h1 >> (4 + s->tx[plane])) & 0x010)); + cx = (((line_h1 >> 9) & 0x003) | a | + ((line_h2 >> 13) & 0x00c) | + ((line_h3 >> 11) & 0x020)); + } else + cx = (((line_h1 >> 9) & 0x003) | + ((line_h2 >> 13) & 0x01c) | + ((line_h3 >> 11) & 0x020)); + if (j & 1) + cx |= (((line_l2 >> 9) & 0x0c0) | + ((line_l1 >> 7) & 0x300)) | (1UL << 10); + else + cx |= (((line_l2 >> 10) & 0x0c0) | + ((line_l1 >> 8) & 0x300)); + cx |= (y & 1) << 11; + + arith_encode(se, cx, (line_h1 >> 8) & 1); +#ifdef DEBUG + encoded_pixels++; +#endif + + /* statistics for adaptive template changes */ + if (!at_determined && j >= s->mx) { + c[0] += !(((line_h2 >> 6) ^ line_h1) & 0x100); + for (t = 3; t <= s->mx; t++) + c[t] += !(((line_h1 >> t) ^ line_h1) & 0x100); + ++c_all; + } + + } while (++j & 1 && j < hx); + } while (j & 7 && j < hx); + hp++; + } while (j & 15 && j < hx); + } /* for (j = ...) */ + + /* low resolution pixels are used twice */ + if ((i & 1) == 0) { + lp1 -= lbpl; + lp2 -= lbpl; + } + + } /* for (i = ...) */ + } + + arith_encode_flush(se); + jbg_buf_remove_zeros(s->sde[stripe][layer][plane]); + jbg_buf_write(MARKER_ESC, s->sde[stripe][layer][plane]); + jbg_buf_write(MARKER_SDNORM, s->sde[stripe][layer][plane]); + + /* add ATMOVE */ + if (new_tx != -1) { + if (s->options & JBG_DELAY_AT) { + /* ATMOVE will become active at the first line of the next stripe */ + s->tx[plane] = new_tx; + jbg_buf_write(MARKER_ESC, s->sde[stripe][layer][plane]); + jbg_buf_write(MARKER_ATMOVE, s->sde[stripe][layer][plane]); + jbg_buf_write(0, s->sde[stripe][layer][plane]); + jbg_buf_write(0, s->sde[stripe][layer][plane]); + jbg_buf_write(0, s->sde[stripe][layer][plane]); + jbg_buf_write(0, s->sde[stripe][layer][plane]); + jbg_buf_write(s->tx[plane], s->sde[stripe][layer][plane]); + jbg_buf_write(0, s->sde[stripe][layer][plane]); + } else { + /* ATMOVE has already become active during this stripe + * => we have to prefix the SDE data with an ATMOVE marker */ + new_jbg_buf = jbg_buf_init(&s->free_list); + jbg_buf_write(MARKER_ESC, new_jbg_buf); + jbg_buf_write(MARKER_ATMOVE, new_jbg_buf); + jbg_buf_write((new_tx_line >> 24) & 0xff, new_jbg_buf); + jbg_buf_write((new_tx_line >> 16) & 0xff, new_jbg_buf); + jbg_buf_write((new_tx_line >> 8) & 0xff, new_jbg_buf); + jbg_buf_write(new_tx_line & 0xff, new_jbg_buf); + jbg_buf_write(new_tx, new_jbg_buf); + jbg_buf_write(0, new_jbg_buf); + jbg_buf_prefix(new_jbg_buf, &s->sde[stripe][layer][plane]); + } + } + +#if 0 + if (stripe == s->stripes - 1) + fprintf(stderr, "tp_lines = %ld, tp_exceptions = %ld, tp_pixels = %ld, " + "dp_pixels = %ld, encoded_pixels = %ld\n", + tp_lines, tp_exceptions, tp_pixels, dp_pixels, encoded_pixels); +#endif + + return; +} + + +/* + * Create the next lower resolution version of an image + */ +static void resolution_reduction(struct jbg_enc_state *s, int plane, + int higher_layer) +{ + unsigned long hx, hy, lx, ly, hbpl, lbpl; + unsigned char *hp1, *hp2, *hp3, *lp; + unsigned long line_h1, line_h2, line_h3, line_l2; + unsigned long i, j; + int pix, k, l; + + /* number of pixels in highres image */ + hx = jbg_ceil_half(s->xd, s->d - higher_layer); + hy = jbg_ceil_half(s->yd, s->d - higher_layer); + /* number of pixels in lowres image */ + lx = jbg_ceil_half(hx, 1); + ly = jbg_ceil_half(hy, 1); + /* bytes per line in highres and lowres image */ + hbpl = jbg_ceil_half(hx, 3); + lbpl = jbg_ceil_half(lx, 3); + /* pointers to first image bytes */ + hp2 = s->lhp[s->highres[plane]][plane]; + hp1 = hp2 + hbpl; + hp3 = hp2 - hbpl; + lp = s->lhp[1 - s->highres[plane]][plane]; + +#ifdef DEBUG + fprintf(stderr, "resolution_reduction: plane = %d, higher_layer = %d\n", + plane, higher_layer); +#endif + + /* + * Layout of the variables line_h1, line_h2, line_h3, which contain + * as bits the high resolution neighbour pixels of the currently coded + * lowres pixel /\: + * \/ + * + * 76543210 76543210 76543210 76543210 line_h3 + * 76543210 76543210 765432/\ 76543210 line_h2 + * 76543210 76543210 765432\/ 76543210 line_h1 + * + * Layout of the variable line_l2, which contains the low resolution + * pixels near the currently coded pixel as bits. The lowres pixel + * which is currently coded is marked as X: + * + * 76543210 76543210 76543210 76543210 line_l2 + * X + */ + + for (i = 0; i < ly; i++) { + if (2*i + 1 >= hy) + hp1 = hp2; + pix = 0; + line_h1 = line_h2 = line_h3 = line_l2 = 0; + for (j = 0; j < lbpl * 8; j += 8) { + *lp = 0; + line_l2 |= i ? *(lp-lbpl) : 0; + for (k = 0; k < 8 && j + k < lx; k += 4) { + if (((j + k) >> 2) < hbpl) { + line_h3 |= i ? *hp3 : 0; + ++hp3; + line_h2 |= *(hp2++); + line_h1 |= *(hp1++); + } + for (l = 0; l < 4 && j + k + l < lx; l++) { + line_h3 <<= 2; + line_h2 <<= 2; + line_h1 <<= 2; + line_l2 <<= 1; + pix = s->res_tab[((line_h1 >> 8) & 0x007) | + ((line_h2 >> 5) & 0x038) | + ((line_h3 >> 2) & 0x1c0) | + (pix << 9) | ((line_l2 << 2) & 0xc00)]; + *lp = (*lp << 1) | pix; + } + } + ++lp; + } + *(lp - 1) <<= lbpl * 8 - lx; + hp1 += hbpl; + hp2 += hbpl; + hp3 += hbpl; + } + +#ifdef DEBUG + { + FILE *f; + char fn[50]; + + sprintf(fn, "dbg_d=%02d.pbm", higher_layer - 1); + f = fopen(fn, "wb"); + fprintf(f, "P4\n%lu %lu\n", lx, ly); + fwrite(s->lhp[1 - s->highres[plane]][plane], 1, lbpl * ly, f); + fclose(f); + } +#endif + + return; +} + + +/* + * This function is called inside the three loops of jbg_enc_out() in + * order to write the next SDE. It has first to generate the required + * SDE and all SDEs which have to be encoded before this SDE can be + * created. The problem here is that if we want to output a lower + * resolution layer, we have to allpy the resolution reduction + * algorithm in order to get it. As we try to safe as much memory as + * possible, the resolution reduction will overwrite previous higher + * resolution bitmaps. Consequently, we have to encode and buffer SDEs + * which depend on higher resolution layers before we can start the + * resolution reduction. All this logic about which SDE has to be + * encoded before resolution reduction is allowed is handled here. + * This approach might be a little bit more complex than alternative + * ways to do it, but it allows us to do the encoding with the minimal + * possible amount of temporary memory. + */ +static void output_sde(struct jbg_enc_state *s, + unsigned long stripe, int layer, int plane) +{ + int lfcl; /* lowest fully coded layer */ + long i; + unsigned long u; + + assert(s->sde[stripe][layer][plane] != SDE_DONE); + + if (s->sde[stripe][layer][plane] != SDE_TODO) { +#ifdef DEBUG + fprintf(stderr, "writing SDE: s/d/p = %2lu/%2d/%2d\n", + stripe, layer, plane); +#endif + jbg_buf_output(&s->sde[stripe][layer][plane], s->data_out, s->file); + s->sde[stripe][layer][plane] = SDE_DONE; + return; + } + + /* Determine the smallest resolution layer in this plane for which + * not yet all stripes have been encoded into SDEs. This layer will + * have to be completely coded, before we can apply the next + * resolution reduction step. */ + lfcl = 0; + for (i = s->d; i >= 0; i--) + if (s->sde[s->stripes - 1][i][plane] == SDE_TODO) { + lfcl = i + 1; + break; + } + if (lfcl > s->d && s->d > 0 && stripe == 0) { + /* perform the first resolution reduction */ + resolution_reduction(s, plane, s->d); + } + /* In case HITOLO is not used, we have to encode and store the higher + * resolution layers first, although we do not need them right now. */ + while (lfcl - 1 > layer) { + for (u = 0; u < s->stripes; u++) + encode_sde(s, u, lfcl - 1, plane); + --lfcl; + s->highres[plane] ^= 1; + if (lfcl > 1) + resolution_reduction(s, plane, lfcl - 1); + } + + encode_sde(s, stripe, layer, plane); + +#ifdef DEBUG + fprintf(stderr, "writing SDE: s/d/p = %2lu/%2d/%2d\n", stripe, layer, plane); +#endif + jbg_buf_output(&s->sde[stripe][layer][plane], s->data_out, s->file); + s->sde[stripe][layer][plane] = SDE_DONE; + + if (stripe == s->stripes - 1 && layer > 0 && + s->sde[0][layer-1][plane] == SDE_TODO) { + s->highres[plane] ^= 1; + if (layer > 1) + resolution_reduction(s, plane, layer - 1); + } + + return; +} + + +/* + * Convert the table which controls the deterministic prediction + * process from the internal format into the representation required + * for the 1728 byte long DPTABLE element of a BIH. + * + * The bit order of the DPTABLE format (see also ITU-T T.82 figure 13) is + * + * high res: 4 5 6 low res: 0 1 + * 7 8 9 2 3 + * 10 11 12 + * + * were 4 table entries are packed into one byte, while we here use + * internally an unpacked 6912 byte long table indexed by the following + * bit order: + * + * high res: 7 6 5 high res: 8 7 6 low res: 1 0 + * (phase 0) 4 . . (phase 1) 5 4 . 3 2 + * . . . . . . + * + * high res: 10 9 8 high res: 11 10 9 + * (phase 2) 7 6 5 (phase 3) 8 7 6 + * 4 . . 5 4 . + */ +void jbg_int2dppriv(unsigned char *dptable, const char *internal) +{ + int i, j, k; + int trans0[ 8] = { 1, 0, 3, 2, 7, 6, 5, 4 }; + int trans1[ 9] = { 1, 0, 3, 2, 8, 7, 6, 5, 4 }; + int trans2[11] = { 1, 0, 3, 2, 10, 9, 8, 7, 6, 5, 4 }; + int trans3[12] = { 1, 0, 3, 2, 11, 10, 9, 8, 7, 6, 5, 4 }; + + for (i = 0; i < 1728; dptable[i++] = 0); + +#define FILL_TABLE1(offset, len, trans) \ + for (i = 0; i < len; i++) { \ + k = 0; \ + for (j = 0; j < 8; j++) \ + k |= ((i >> j) & 1) << trans[j]; \ + dptable[(i + offset) >> 2] |= \ + (internal[k + offset] & 3) << ((3 - (i&3)) << 1); \ + } + + FILL_TABLE1( 0, 256, trans0); + FILL_TABLE1( 256, 512, trans1); + FILL_TABLE1( 768, 2048, trans2); + FILL_TABLE1(2816, 4096, trans3); + + return; +} + + +/* + * Convert the table which controls the deterministic prediction + * process from the 1728 byte long DPTABLE format into the 6912 byte long + * internal format. + */ +void jbg_dppriv2int(char *internal, const unsigned char *dptable) +{ + int i, j, k; + int trans0[ 8] = { 1, 0, 3, 2, 7, 6, 5, 4 }; + int trans1[ 9] = { 1, 0, 3, 2, 8, 7, 6, 5, 4 }; + int trans2[11] = { 1, 0, 3, 2, 10, 9, 8, 7, 6, 5, 4 }; + int trans3[12] = { 1, 0, 3, 2, 11, 10, 9, 8, 7, 6, 5, 4 }; + +#define FILL_TABLE2(offset, len, trans) \ + for (i = 0; i < len; i++) { \ + k = 0; \ + for (j = 0; j < 8; j++) \ + k |= ((i >> j) & 1) << trans[j]; \ + internal[k + offset] = \ + (dptable[(i + offset) >> 2] >> ((3 - (i & 3)) << 1)) & 3; \ + } + + FILL_TABLE2( 0, 256, trans0); + FILL_TABLE2( 256, 512, trans1); + FILL_TABLE2( 768, 2048, trans2); + FILL_TABLE2(2816, 4096, trans3); + + return; +} + + +/* + * Encode one full BIE and pass the generated data to the specified + * call-back function + */ +void jbg_enc_out(struct jbg_enc_state *s) +{ + unsigned long bpl; + unsigned char buf[20]; + unsigned long xd, yd, y; + long ii[3], is[3], ie[3]; /* generic variables for the 3 nested loops */ + unsigned long stripe; + int layer, plane; + int order; + unsigned char dpbuf[1728]; + extern char jbg_dptable[]; + + /* some sanity checks */ + s->order &= JBG_HITOLO | JBG_SEQ | JBG_ILEAVE | JBG_SMID; + order = s->order & (JBG_SEQ | JBG_ILEAVE | JBG_SMID); + if (iindex[order][0] < 0) + s->order = order = JBG_SMID | JBG_ILEAVE; + if (s->options & JBG_DPON && s->dppriv != jbg_dptable) + s->options |= JBG_DPPRIV; + if (s->mx > MX_MAX) + s->mx = MX_MAX; + s->my = 0; + if (s->mx && s->mx < ((s->options & JBG_LRLTWO) ? 5U : 3U)) + s->mx = 0; + if (s->d > 255 || s->d < 0 || s->dh > s->d || s->dh < 0 || + s->dl < 0 || s->dl > s->dh || s->planes < 0 || s->planes > 255) + return; + /* prevent uint32 overflow: s->l0 * 2 ^ s->d < 2 ^ 32 */ + if (s->d > 31 || (s->d != 0 && s->l0 >= (1UL << (32 - s->d)))) + return; + if (s->yd1 < s->yd) + s->yd1 = s->yd; + if (s->yd1 > s->yd) + s->options |= JBG_VLENGTH; + + /* ensure correct zero padding of bitmap at the final byte of each line */ + if (s->xd & 7) { + bpl = jbg_ceil_half(s->xd, 3); /* bytes per line */ + for (plane = 0; plane < s->planes; plane++) + for (y = 0; y < s->yd; y++) + s->lhp[0][plane][y * bpl + bpl - 1] &= ~((1 << (8 - (s->xd & 7))) - 1); + } + + /* prepare BIH */ + buf[0] = s->dl; + buf[1] = s->dh; + buf[2] = s->planes; + buf[3] = 0; + xd = jbg_ceil_half(s->xd, s->d - s->dh); + yd = jbg_ceil_half(s->yd1, s->d - s->dh); + buf[4] = xd >> 24; + buf[5] = (xd >> 16) & 0xff; + buf[6] = (xd >> 8) & 0xff; + buf[7] = xd & 0xff; + buf[8] = yd >> 24; + buf[9] = (yd >> 16) & 0xff; + buf[10] = (yd >> 8) & 0xff; + buf[11] = yd & 0xff; + buf[12] = s->l0 >> 24; + buf[13] = (s->l0 >> 16) & 0xff; + buf[14] = (s->l0 >> 8) & 0xff; + buf[15] = s->l0 & 0xff; + buf[16] = s->mx; + buf[17] = s->my; + buf[18] = s->order; + buf[19] = s->options & 0x7f; + +#if 0 + /* sanitize L0 (if it was set to 0xffffffff for T.85-style NEWLEN tests) */ + if (s->l0 > (s->yd >> s->d)) + s->l0 = s->yd >> s->d; +#endif + + /* calculate number of stripes that will be required */ + s->stripes = jbg_stripes(s->l0, s->yd, s->d); + + /* allocate buffers for SDE pointers */ + if (s->sde == NULL) { + s->sde = (struct jbg_buf ****) + checked_malloc(s->stripes, sizeof(struct jbg_buf ***)); + for (stripe = 0; stripe < s->stripes; stripe++) { + s->sde[stripe] = (struct jbg_buf ***) + checked_malloc(s->d + 1, sizeof(struct jbg_buf **)); + for (layer = 0; layer < s->d + 1; layer++) { + s->sde[stripe][layer] = (struct jbg_buf **) + checked_malloc(s->planes, sizeof(struct jbg_buf *)); + for (plane = 0; plane < s->planes; plane++) + s->sde[stripe][layer][plane] = SDE_TODO; + } + } + } + + /* output BIH */ + s->data_out(buf, 20, s->file); + if ((s->options & (JBG_DPON | JBG_DPPRIV | JBG_DPLAST)) == + (JBG_DPON | JBG_DPPRIV)) { + /* write private table */ + jbg_int2dppriv(dpbuf, s->dppriv); + s->data_out(dpbuf, 1728, s->file); + } + +#if 0 + /* + * Encode everything first. This is a simple-minded alternative to + * all the tricky on-demand encoding logic in output_sde() for + * debugging purposes. + */ + for (layer = s->dh; layer >= s->dl; layer--) { + for (plane = 0; plane < s->planes; plane++) { + if (layer > 0) + resolution_reduction(s, plane, layer); + for (stripe = 0; stripe < s->stripes; stripe++) + encode_sde(s, stripe, layer, plane); + s->highres[plane] ^= 1; + } + } +#endif + + /* + * Generic loops over all SDEs. Which loop represents layer, plane and + * stripe depends on the option flags. + */ + + /* start and end value vor each loop */ + is[iindex[order][STRIPE]] = 0; + ie[iindex[order][STRIPE]] = s->stripes - 1; + is[iindex[order][LAYER]] = s->dl; + ie[iindex[order][LAYER]] = s->dh; + is[iindex[order][PLANE]] = 0; + ie[iindex[order][PLANE]] = s->planes - 1; + + for (ii[0] = is[0]; ii[0] <= ie[0]; ii[0]++) + for (ii[1] = is[1]; ii[1] <= ie[1]; ii[1]++) + for (ii[2] = is[2]; ii[2] <= ie[2]; ii[2]++) { + + stripe = ii[iindex[order][STRIPE]]; + if (s->order & JBG_HITOLO) + layer = s->dh - (ii[iindex[order][LAYER]] - s->dl); + else + layer = ii[iindex[order][LAYER]]; + plane = ii[iindex[order][PLANE]]; + + output_sde(s, stripe, layer, plane); + + /* + * When we generate a NEWLEN test case (s->yd1 > s->yd), output + * NEWLEN after last stripe if we have only a single + * resolution layer or plane (see ITU-T T.85 profile), otherwise + * output NEWLEN before last stripe. + */ + if (s->yd1 > s->yd && + (stripe == s->stripes - 1 || + (stripe == s->stripes - 2 && + (s->dl != s->dh || s->planes > 1)))) { + s->yd1 = s->yd; + yd = jbg_ceil_half(s->yd, s->d - s->dh); + buf[0] = MARKER_ESC; + buf[1] = MARKER_NEWLEN; + buf[2] = yd >> 24; + buf[3] = (yd >> 16) & 0xff; + buf[4] = (yd >> 8) & 0xff; + buf[5] = yd & 0xff; + s->data_out(buf, 6, s->file); +#ifdef DEBUG + fprintf(stderr, "NEWLEN: yd=%lu\n", yd); +#endif + if (stripe == s->stripes - 1) { + buf[1] = MARKER_SDNORM; + s->data_out(buf, 2, s->file); + } + } + + } + + return; +} + + +void jbg_enc_free(struct jbg_enc_state *s) +{ + unsigned long stripe; + int layer, plane; + +#ifdef DEBUG + fprintf(stderr, "jbg_enc_free(%p)\n", (void *) s); +#endif + + /* clear buffers for SDEs */ + if (s->sde) { + for (stripe = 0; stripe < s->stripes; stripe++) { + for (layer = 0; layer < s->d + 1; layer++) { + for (plane = 0; plane < s->planes; plane++) + if (s->sde[stripe][layer][plane] != SDE_DONE && + s->sde[stripe][layer][plane] != SDE_TODO) + jbg_buf_free(&s->sde[stripe][layer][plane]); + checked_free(s->sde[stripe][layer]); + } + checked_free(s->sde[stripe]); + } + checked_free(s->sde); + } + + /* clear free_list */ + jbg_buf_free(&s->free_list); + + /* clear memory for arithmetic encoder states */ + checked_free(s->s); + + /* clear memory for differential-layer typical prediction buffer */ + checked_free(s->tp); + + /* clear memory for adaptive template pixel offsets */ + checked_free(s->tx); + + /* clear lowres image buffers */ + if (s->lhp[1]) { + for (plane = 0; plane < s->planes; plane++) + checked_free(s->lhp[1][plane]); + checked_free(s->lhp[1]); + } + + /* clear buffer for index of highres image in lhp */ + checked_free(s->highres); + + return; +} + + +/* + * Convert the error codes used by jbg_dec_in() into a string + * written in the selected language and character set. + */ +const char *jbg_strerror(int errnum, int language) +{ + if (errnum < 0 || errnum >= NEMSG) + return "Unknown error code passed to jbg_strerror()"; + if (language < 0 || language >= NEMSG_LANG) + return "Unknown language code passed to jbg_strerror()"; + + return errmsg[language][errnum]; +} + + +/* + * The constructor for a decoder + */ +void jbg_dec_init(struct jbg_dec_state *s) +{ + s->order = 0; + s->d = -1; + s->bie_len = 0; + s->buf_len = 0; + s->dppriv = NULL; + s->xmax = 4294967295UL; + s->ymax = 4294967295UL; + s->dmax = 256; + s->s = NULL; + + return; +} + + +/* + * Specify a maximum image size for the decoder. If the JBIG file has + * the order bit ILEAVE, but not the bit SEQ set, then the decoder + * will abort to decode after the image has reached the maximal + * resolution layer which is still not wider than xmax or higher than + * ymax. + */ +void jbg_dec_maxsize(struct jbg_dec_state *s, unsigned long xmax, + unsigned long ymax) +{ + if (xmax > 0) s->xmax = xmax; + if (ymax > 0) s->ymax = ymax; + + return; +} + + +/* + * Decode the new len PSDC bytes to which data points and add them to + * the current stripe. Return the number of bytes which have actually + * been read (this will be less than len if a marker segment was + * part of the data or if the final byte was 0xff were this code + * can not determine, whether we have a marker segment. + */ +static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, + size_t len) +{ + unsigned long stripe; + unsigned int layer, plane; + unsigned long hl, ll, y, hx, hy, lx, ly, hbpl, lbpl; + unsigned char *hp, *lp1, *lp2, *p1, *q1; + register unsigned long line_h1, line_h2, line_h3; + register unsigned long line_l1, line_l2, line_l3; + struct jbg_ardec_state *se; + unsigned long x; + long o; + unsigned a; + int n; + int pix, cx = 0, slntp, tx; + + /* SDE loop variables */ + stripe = s->ii[iindex[s->order & 7][STRIPE]]; + layer = s->ii[iindex[s->order & 7][LAYER]]; + plane = s->ii[iindex[s->order & 7][PLANE]]; + + /* forward data to arithmetic decoder */ + se = s->s[plane] + layer - s->dl; + se->pscd_ptr = data; + se->pscd_end = data + len; + + /* number of lines per stripe in highres image */ + hl = s->l0 << layer; + /* number of lines per stripe in lowres image */ + ll = hl >> 1; + /* current line number in highres image */ + y = stripe * hl + s->i; + /* number of pixels in highres image */ + hx = jbg_ceil_half(s->xd, s->d - layer); + hy = jbg_ceil_half(s->yd, s->d - layer); + /* number of pixels in lowres image */ + lx = jbg_ceil_half(hx, 1); + ly = jbg_ceil_half(hy, 1); + /* bytes per line in highres and lowres image */ + hbpl = jbg_ceil_half(hx, 3); + lbpl = jbg_ceil_half(lx, 3); + /* pointer to highres and lowres image bytes */ + hp = s->lhp[ layer & 1][plane] + (stripe * hl + s->i) * hbpl + + (s->x >> 3); + lp2 = s->lhp[(layer-1) & 1][plane] + (stripe * ll + (s->i >> 1)) * lbpl + + (s->x >> 4); + lp1 = lp2 + lbpl; + + /* restore a few local variables */ + line_h1 = s->line_h1; + line_h2 = s->line_h2; + line_h3 = s->line_h3; + line_l1 = s->line_l1; + line_l2 = s->line_l2; + line_l3 = s->line_l3; + x = s->x; + + if (s->x == 0 && s->i == 0 && + (stripe == 0 || s->reset[plane][layer - s->dl])) { + s->tx[plane][layer - s->dl] = s->ty[plane][layer - s->dl] = 0; + if (s->pseudo) + s->lntp[plane][layer - s->dl] = 1; + } + +#ifdef DEBUG + if (s->x == 0 && s->i == 0 && s->pseudo) + fprintf(stderr, "decode_pscd(%p, %p, %ld): s/d/p = %2lu/%2u/%2u\n", + (void *) s, (void *) data, (long) len, stripe, layer, plane); +#endif + + if (layer == 0) { + + /* + * Decode lowest resolution layer + */ + + for (; s->i < hl && y < hy; s->i++, y++) { + + /* adaptive template changes */ + if (x == 0) + for (n = 0; n < s->at_moves; n++) + if (s->at_line[n] == s->i) { + s->tx[plane][layer - s->dl] = s->at_tx[n]; + s->ty[plane][layer - s->dl] = s->at_ty[n]; +#ifdef DEBUG + fprintf(stderr, "ATMOVE: line=%lu, tx=%d, ty=%d.\n", s->i, + s->tx[plane][layer - s->dl], s->ty[plane][layer - s->dl]); +#endif + } + tx = s->tx[plane][layer - s->dl]; + assert(tx >= 0); /* i.e., tx can safely be cast to unsigned */ + + /* typical prediction */ + if (s->options & JBG_TPBON && s->pseudo) { + slntp = arith_decode(se, (s->options & JBG_LRLTWO) ? TPB2CX : TPB3CX); + if (se->result == JBG_MORE || se->result == JBG_MARKER) + goto leave; + s->lntp[plane][layer - s->dl] = + !(slntp ^ s->lntp[plane][layer - s->dl]); + if (s->lntp[plane][layer - s->dl]) { + /* this line is 'not typical' and has to be coded completely */ + s->pseudo = 0; + } else { + /* this line is 'typical' (i.e. identical to the previous one) */ + p1 = hp; + if (s->i == 0 && (stripe == 0 || s->reset[plane][layer - s->dl])) + while (p1 < hp + hbpl) *p1++ = 0; + else { + q1 = hp - hbpl; + while (q1 < hp) *p1++ = *q1++; + } + hp += hbpl; + continue; + } + } + + /* + * Layout of the variables line_h1, line_h2, line_h3, which contain + * as bits the neighbour pixels of the currently decoded pixel X: + * + * 76543210 76543210 76543210 76543210 line_h3 + * 76543210 76543210 76543210 76543210 line_h2 + * 76543210 76543210 76543210 76543210 X line_h1 + */ + + if (x == 0) { + line_h1 = line_h2 = line_h3 = 0; + if (s->i > 0 || (y > 0 && !s->reset[plane][layer - s->dl])) + line_h2 = (long)*(hp - hbpl) << 8; + if (s->i > 1 || (y > 1 && !s->reset[plane][layer - s->dl])) + line_h3 = (long)*(hp - hbpl - hbpl) << 8; + } + + /* + * Another tiny JBIG standard bug: + * + * While implementing the line_h3 handling here, I discovered + * another problem with the ITU-T T.82(1993 E) specification. + * This might be a somewhat pathological case, however. The + * standard is unclear about how a decoder should behave in the + * following situation: + * + * Assume we are in layer 0 and all stripes are single lines + * (L0=1 allowed by table 9). We are now decoding the first (and + * only) line of the third stripe. Assume, the first stripe was + * terminated by SDRST and the second stripe was terminated by + * SDNORM. While decoding the only line of the third stripe with + * the three-line template, we need access to pixels from the + * previous two stripes. We know that the previous stripe + * terminated with SDNROM, so we access the pixel from the + * second stripe. But do we have to replace the pixels from the + * first stripe by background pixels, because this stripe ended + * with SDRST? The standard, especially clause 6.2.5 does never + * mention this case, so the behaviour is undefined here. My + * current implementation remembers only the marker used to + * terminate the previous stripe. In the above example, the + * pixels of the first stripe are accessed despite the fact that + * this stripe ended with SDRST. An alternative (only slightly + * more complicated) implementation would be to remember the end + * marker (SDNORM or SDRST) of the previous two stripes in a + * plane/layer and to act accordingly when accessing the two + * previous lines. What am I supposed to do here? + * + * As the standard is unclear about the correct behaviour in the + * situation of the above example, I strongly suggest to avoid + * the following situation while encoding data with JBIG: + * + * LRLTWO = 0, L0=1 and both SDNORM and SDRST appear in layer 0. + * + * I guess that only a very few if any encoders will switch + * between SDNORM and SDRST, so let us hope that this ambiguity + * in the standard will never cause any interoperability + * problems. + * + * Markus Kuhn -- 1995-04-30 + */ + + /* decode line */ + while (x < hx) { + if ((x & 7) == 0) { + if (x < hbpl * 8 - 8 && + (s->i > 0 || (y > 0 && !s->reset[plane][layer - s->dl]))) { + line_h2 |= *(hp - hbpl + 1); + if (s->i > 1 || (y > 1 && !s->reset[plane][layer - s->dl])) + line_h3 |= *(hp - hbpl - hbpl + 1); + } + } + if (s->options & JBG_LRLTWO) { + /* two line template */ + do { + if (tx) { + if ((unsigned) tx > x) + a = 0; + else if (tx < 8) + a = ((line_h1 >> (tx - 5)) & 0x010); + else { + o = (x - tx) - (x & ~7L); + a = (hp[o >> 3] >> (7 - (o & 7))) & 1; + a <<= 4; + } + assert(tx > 31 || + a == ((line_h1 >> (tx - 5)) & 0x010)); + pix = arith_decode(se, (((line_h2 >> 9) & 0x3e0) | a | + (line_h1 & 0x00f))); + } else + pix = arith_decode(se, (((line_h2 >> 9) & 0x3f0) | + (line_h1 & 0x00f))); + if (se->result == JBG_MORE || se->result == JBG_MARKER) + goto leave; + line_h1 = (line_h1 << 1) | pix; + line_h2 <<= 1; + } while ((++x & 7) && x < hx); + } else { + /* three line template */ + do { + if (tx) { + if ((unsigned) tx > x) + a = 0; + else if (tx < 8) + a = ((line_h1 >> (tx - 3)) & 0x004); + else { + o = (x - tx) - (x & ~7L); + a = (hp[o >> 3] >> (7 - (o & 7))) & 1; + a <<= 2; + } + assert(tx > 31 || + a == ((line_h1 >> (tx - 3)) & 0x004)); + pix = arith_decode(se, (((line_h3 >> 7) & 0x380) | + ((line_h2 >> 11) & 0x078) | a | + (line_h1 & 0x003))); + } else + pix = arith_decode(se, (((line_h3 >> 7) & 0x380) | + ((line_h2 >> 11) & 0x07c) | + (line_h1 & 0x003))); + if (se->result == JBG_MORE || se->result == JBG_MARKER) + goto leave; + + line_h1 = (line_h1 << 1) | pix; + line_h2 <<= 1; + line_h3 <<= 1; + } while ((++x & 7) && x < hx); + } /* if (s->options & JBG_LRLTWO) */ + *hp++ = line_h1; + } /* while */ + *(hp - 1) <<= hbpl * 8 - hx; + x = 0; + s->pseudo = 1; + } /* for (i = ...) */ + + } else { + + /* + * Decode differential layer + */ + + for (; s->i < hl && y < hy; s->i++, y++) { + + /* adaptive template changes */ + if (x == 0) + for (n = 0; n < s->at_moves; n++) + if (s->at_line[n] == s->i) { + s->tx[plane][layer - s->dl] = s->at_tx[n]; + s->ty[plane][layer - s->dl] = s->at_ty[n]; +#ifdef DEBUG + fprintf(stderr, "ATMOVE: line=%lu, tx=%d, ty=%d.\n", s->i, + s->tx[plane][layer - s->dl], s->ty[plane][layer - s->dl]); +#endif + } + tx = s->tx[plane][layer - s->dl]; + + /* handle lower border of low-resolution image */ + if ((s->i >> 1) >= ll - 1 || (y >> 1) >= ly - 1) + lp1 = lp2; + + /* typical prediction */ + if (s->options & JBG_TPDON && s->pseudo) { + s->lntp[plane][layer - s->dl] = arith_decode(se, TPDCX); + if (se->result == JBG_MORE || se->result == JBG_MARKER) + goto leave; + s->pseudo = 0; + } + + + /* + * Layout of the variables line_h1, line_h2, line_h3, which contain + * as bits the high resolution neighbour pixels of the currently + * decoded highres pixel X: + * + * 76543210 76543210 76543210 76543210 line_h3 + * 76543210 76543210 76543210 76543210 line_h2 + * 76543210 76543210 76543210 76543210 X line_h1 + * + * Layout of the variables line_l1, line_l2, line_l3, which contain + * the low resolution pixels near the currently decoded pixel as bits. + * The lowres pixel in which the currently coded highres pixel is + * located is marked as Y: + * + * 76543210 76543210 76543210 76543210 line_l3 + * 76543210 76543210 Y6543210 76543210 line_l2 + * 76543210 76543210 76543210 76543210 line_l1 + */ + + + if (x == 0) { + line_h1 = line_h2 = line_h3 = line_l1 = line_l2 = line_l3 = 0; + if (s->i > 0 || (y > 0 && !s->reset[plane][layer - s->dl])) { + line_h2 = (long)*(hp - hbpl) << 8; + if (s->i > 1 || (y > 1 && !s->reset[plane][layer - s->dl])) + line_h3 = (long)*(hp - hbpl - hbpl) << 8; + } + if (s->i > 1 || (y > 1 && !s->reset[plane][layer-s->dl])) + line_l3 = (long)*(lp2 - lbpl) << 8; + line_l2 = (long)*lp2 << 8; + line_l1 = (long)*lp1 << 8; + } + + /* decode line */ + while (x < hx) { + if ((x & 15) == 0) + if ((x >> 1) < lbpl * 8 - 8) { + line_l1 |= *(lp1 + 1); + line_l2 |= *(lp2 + 1); + if (s->i > 1 || + (y > 1 && !s->reset[plane][layer - s->dl])) + line_l3 |= *(lp2 - lbpl + 1); + } + do { + + assert(hp - (s->lhp[ layer &1][plane] + (stripe * hl + s->i) + * hbpl) == (ptrdiff_t) x >> 3); + assert(lp2 - (s->lhp[(layer-1) &1][plane] + (stripe * ll + (s->i>>1)) + * lbpl) == (ptrdiff_t) x >> 4); + + if ((x & 7) == 0) + if (x < hbpl * 8 - 8) { + if (s->i > 0 || (y > 0 && !s->reset[plane][layer - s->dl])) { + line_h2 |= *(hp + 1 - hbpl); + if (s->i > 1 || (y > 1 && !s->reset[plane][layer - s->dl])) + line_h3 |= *(hp + 1 - hbpl - hbpl); + } + } + do { + if (!s->lntp[plane][layer - s->dl]) + cx = (((line_l3 >> 14) & 0x007) | + ((line_l2 >> 11) & 0x038) | + ((line_l1 >> 8) & 0x1c0)); + if (!s->lntp[plane][layer - s->dl] && + (cx == 0x000 || cx == 0x1ff)) { + /* pixels are typical and have not to be decoded */ + do { + line_h1 = (line_h1 << 1) | (cx & 1); + } while ((++x & 1) && x < hx); + line_h2 <<= 2; line_h3 <<= 2; + } else + do { + + /* deterministic prediction */ + if (s->options & JBG_DPON) + if ((y & 1) == 0) + if ((x & 1) == 0) + /* phase 0 */ + pix = s->dppriv[((line_l3 >> 15) & 0x003) | + ((line_l2 >> 13) & 0x00c) | + ((line_h1 << 4) & 0x010) | + ((line_h2 >> 9) & 0x0e0)]; + else + /* phase 1 */ + pix = s->dppriv[(((line_l3 >> 15) & 0x003) | + ((line_l2 >> 13) & 0x00c) | + ((line_h1 << 4) & 0x030) | + ((line_h2 >> 9) & 0x1c0)) + 256]; + else + if ((x & 1) == 0) + /* phase 2 */ + pix = s->dppriv[(((line_l3 >> 15) & 0x003) | + ((line_l2 >> 13) & 0x00c) | + ((line_h1 << 4) & 0x010) | + ((line_h2 >> 9) & 0x0e0) | + ((line_h3 >> 6) & 0x700)) + 768]; + else + /* phase 3 */ + pix = s->dppriv[(((line_l3 >> 15) & 0x003) | + ((line_l2 >> 13) & 0x00c) | + ((line_h1 << 4) & 0x030) | + ((line_h2 >> 9) & 0x1c0) | + ((line_h3 >> 6) & 0xe00)) + 2816]; + else + pix = 2; + + if (pix & 2) { + if (tx) + cx = ((line_h1 & 0x003) | + (((line_h1 << 2) >> (tx - 3)) & 0x010) | + ((line_h2 >> 12) & 0x00c) | + ((line_h3 >> 10) & 0x020)); + else + cx = ((line_h1 & 0x003) | + ((line_h2 >> 12) & 0x01c) | + ((line_h3 >> 10) & 0x020)); + if (x & 1) + cx |= (((line_l2 >> 8) & 0x0c0) | + ((line_l1 >> 6) & 0x300)) | (1UL << 10); + else + cx |= (((line_l2 >> 9) & 0x0c0) | + ((line_l1 >> 7) & 0x300)); + cx |= (y & 1) << 11; + + pix = arith_decode(se, cx); + if (se->result == JBG_MORE || se->result == JBG_MARKER) + goto leave; + } + + line_h1 = (line_h1 << 1) | pix; + line_h2 <<= 1; + line_h3 <<= 1; + + } while ((++x & 1) && x < hx); + line_l1 <<= 1; line_l2 <<= 1; line_l3 <<= 1; + } while ((x & 7) && x < hx); + *hp++ = line_h1; + } while ((x & 15) && x < hx); + ++lp1; + ++lp2; + } /* while */ + x = 0; + + *(hp - 1) <<= hbpl * 8 - hx; + if ((s->i & 1) == 0) { + /* low resolution pixels are used twice */ + lp1 -= lbpl; + lp2 -= lbpl; + } else + s->pseudo = 1; + + } /* for (i = ...) */ + + } + + leave: + + /* save a few local variables */ + s->line_h1 = line_h1; + s->line_h2 = line_h2; + s->line_h3 = line_h3; + s->line_l1 = line_l1; + s->line_l2 = line_l2; + s->line_l3 = line_l3; + s->x = x; + + return se->pscd_ptr - data; +} + + +/* + * Provide a new BIE fragment to the decoder. + * + * If cnt is not NULL, then *cnt will contain after the call the + * number of actually read bytes. If the data was not complete, then + * the return value will be JBG_EAGAIN and *cnt == len. In case this + * function has returned with JBG_EOK, then it has reached the end of + * a BIE but it can be called again with data from the next BIE if + * there exists one in order to get to a higher resolution layer. In + * case the return value was JBG_EOK_INTR then this function can be + * called again with the rest of the BIE, because parsing the BIE has + * been interrupted by a jbg_dec_maxsize() specification. In both + * cases the remaining len - *cnt bytes of the previous block will + * have to passed to this function again (if len > *cnt). In case of + * any other return value than JBG_EOK, JBG_EOK_INTR or JBG_EAGAIN, a + * serious problem has occured and the only function you should call + * is jbg_dec_free() in order to remove the mess (and probably + * jbg_strerror() in order to find out what to tell the user). + */ +int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, + size_t *cnt) +{ + int i, j, required_length; + unsigned long x, y; + unsigned long is[3], ie[3]; + extern char jbg_dptable[]; + size_t dummy_cnt; + + if (!cnt) cnt = &dummy_cnt; + *cnt = 0; + if (len < 1) return JBG_EAGAIN; + + /* read in 20-byte BIH */ + if (s->bie_len < 20) { + while (s->bie_len < 20 && *cnt < len) + s->buffer[s->bie_len++] = data[(*cnt)++]; + if (s->bie_len < 20) + return JBG_EAGAIN; + if (s->buffer[1] < s->buffer[0]) + return JBG_EINVAL; + /* test whether this looks like a valid JBIG header at all */ + if (s->buffer[3] != 0 || (s->buffer[18] & 0xf0) != 0 || + (s->buffer[19] & 0x80) != 0) + return JBG_EINVAL; + if (s->buffer[0] != s->d + 1) + return JBG_ENOCONT; + s->dl = s->buffer[0]; + s->d = s->buffer[1]; + if (s->dl == 0) + s->planes = s->buffer[2]; + else + if (s->planes != s->buffer[2]) + return JBG_ENOCONT; + x = (((long) s->buffer[ 4] << 24) | ((long) s->buffer[ 5] << 16) | + ((long) s->buffer[ 6] << 8) | (long) s->buffer[ 7]); + y = (((long) s->buffer[ 8] << 24) | ((long) s->buffer[ 9] << 16) | + ((long) s->buffer[10] << 8) | (long) s->buffer[11]); + if (s->dl != 0 && ((s->xd << (s->d - s->dl + 1)) != x && + (s->yd << (s->d - s->dl + 1)) != y)) + return JBG_ENOCONT; + s->xd = x; + s->yd = y; + s->l0 = (((long) s->buffer[12] << 24) | ((long) s->buffer[13] << 16) | + ((long) s->buffer[14] << 8) | (long) s->buffer[15]); + /* ITU-T T.85 trick not directly supported by decoder; for full + * T.85 compatibility with respect to all NEWLEN marker scenarios, + * preprocess BIE with jbg_newlen() before passing it to the decoder. */ + if (s->yd == 0xffffffff) + return JBG_EIMPL; + if (!s->planes || !s->xd || !s->yd || !s->l0) + return JBG_EINVAL; + /* prevent uint32 overflow: s->l0 * 2 ^ s->d < 2 ^ 32 */ + if (s->d > 31 || (s->d != 0 && s->l0 >= (1UL << (32 - s->d)))) + return JBG_EIMPL; + s->mx = s->buffer[16]; + if (s->mx > 127) + return JBG_EINVAL; + s->my = s->buffer[17]; +#if 0 + if (s->my > 0) + return JBG_EIMPL; +#endif + s->order = s->buffer[18]; + if (iindex[s->order & 7][0] < 0) + return JBG_EINVAL; + /* HITOLO and SEQ currently not yet implemented */ + if (s->dl != s->d && (s->order & JBG_HITOLO || s->order & JBG_SEQ)) + return JBG_EIMPL; + s->options = s->buffer[19]; + + /* calculate number of stripes that will be required */ + s->stripes = jbg_stripes(s->l0, s->yd, s->d); + + /* some initialization */ + s->ii[iindex[s->order & 7][STRIPE]] = 0; + s->ii[iindex[s->order & 7][LAYER]] = s->dl; + s->ii[iindex[s->order & 7][PLANE]] = 0; + if (s->dl == 0) { + s->s = (struct jbg_ardec_state **) + checked_malloc(s->planes, sizeof(struct jbg_ardec_state *)); + s->tx = (int **) checked_malloc(s->planes, sizeof(int *)); + s->ty = (int **) checked_malloc(s->planes, sizeof(int *)); + s->reset = (int **) checked_malloc(s->planes, sizeof(int *)); + s->lntp = (int **) checked_malloc(s->planes, sizeof(int *)); + s->lhp[0] = (unsigned char **) + checked_malloc(s->planes, sizeof(unsigned char *)); + s->lhp[1] = (unsigned char **) + checked_malloc(s->planes, sizeof(unsigned char *)); + for (i = 0; i < s->planes; i++) { + s->s[i] = (struct jbg_ardec_state *) + checked_malloc(s->d - s->dl + 1, sizeof(struct jbg_ardec_state)); + s->tx[i] = (int *) checked_malloc(s->d - s->dl + 1, sizeof(int)); + s->ty[i] = (int *) checked_malloc(s->d - s->dl + 1, sizeof(int)); + s->reset[i] = (int *) checked_malloc(s->d - s->dl + 1, sizeof(int)); + s->lntp[i] = (int *) checked_malloc(s->d - s->dl + 1, sizeof(int)); + s->lhp[ s->d & 1][i] = (unsigned char *) + checked_malloc(s->yd, jbg_ceil_half(s->xd, 3)); + s->lhp[(s->d-1) & 1][i] = (unsigned char *) + checked_malloc(jbg_ceil_half(s->yd, 1), jbg_ceil_half(s->xd, 1+3)); + } + } else { + for (i = 0; i < s->planes; i++) { + s->s[i] = (struct jbg_ardec_state *) + checked_realloc(s->s[i], s->d - s->dl + 1, + sizeof(struct jbg_ardec_state)); + s->tx[i] = (int *) checked_realloc(s->tx[i], + s->d - s->dl + 1, sizeof(int)); + s->ty[i] = (int *) checked_realloc(s->ty[i], + s->d - s->dl + 1, sizeof(int)); + s->reset[i] = (int *) checked_realloc(s->reset[i], + s->d - s->dl + 1, sizeof(int)); + s->lntp[i] = (int *) checked_realloc(s->lntp[i], + s->d - s->dl + 1, sizeof(int)); + s->lhp[ s->d & 1][i] = (unsigned char *) + checked_realloc(s->lhp[ s->d & 1][i], + s->yd, jbg_ceil_half(s->xd, 3)); + s->lhp[(s->d-1) & 1][i] = (unsigned char *) + checked_realloc(s->lhp[(s->d-1) & 1][i], + jbg_ceil_half(s->yd, 1), jbg_ceil_half(s->xd, 1+3)); + } + } + for (i = 0; i < s->planes; i++) + for (j = 0; j <= s->d - s->dl; j++) + arith_decode_init(s->s[i] + j, 0); + if (s->dl == 0 || (s->options & JBG_DPON && !(s->options & JBG_DPPRIV))) + s->dppriv = jbg_dptable; + s->comment_skip = 0; + s->buf_len = 0; + s->x = 0; + s->i = 0; + s->pseudo = 1; + s->at_moves = 0; + } + + /* read in DPTABLE */ + if (s->bie_len < 20 + 1728 && + (s->options & (JBG_DPON | JBG_DPPRIV | JBG_DPLAST)) == + (JBG_DPON | JBG_DPPRIV)) { + assert(s->bie_len >= 20); + while (s->bie_len < 20 + 1728 && *cnt < len) + s->buffer[s->bie_len++ - 20] = data[(*cnt)++]; + if (s->bie_len < 20 + 1728) + return JBG_EAGAIN; + if (!s->dppriv || s->dppriv == jbg_dptable) + s->dppriv = (char *) checked_malloc(1728, sizeof(char)); + jbg_dppriv2int(s->dppriv, s->buffer); + } + + /* + * BID processing loop + */ + + while (*cnt < len) { + + /* process floating marker segments */ + + /* skip COMMENT contents */ + if (s->comment_skip) { + if (s->comment_skip <= len - *cnt) { + *cnt += s->comment_skip; + s->comment_skip = 0; + } else { + s->comment_skip -= len - *cnt; + *cnt = len; + } + continue; + } + + /* load complete marker segments into s->buffer for processing */ + if (s->buf_len > 0) { + assert(s->buffer[0] == MARKER_ESC); + while (s->buf_len < 2 && *cnt < len) + s->buffer[s->buf_len++] = data[(*cnt)++]; + if (s->buf_len < 2) continue; + switch (s->buffer[1]) { + case MARKER_COMMENT: required_length = 6; break; + case MARKER_ATMOVE: required_length = 8; break; + case MARKER_NEWLEN: required_length = 6; break; + case MARKER_ABORT: + case MARKER_SDNORM: + case MARKER_SDRST: required_length = 2; break; + case MARKER_STUFF: + /* forward stuffed 0xff to arithmetic decoder */ + s->buf_len = 0; + decode_pscd(s, s->buffer, 2); + continue; + default: + return JBG_EMARKER; + } + while (s->buf_len < required_length && *cnt < len) + s->buffer[s->buf_len++] = data[(*cnt)++]; + if (s->buf_len < required_length) continue; + /* now the buffer is filled with exactly one marker segment */ + switch (s->buffer[1]) { + case MARKER_COMMENT: + s->comment_skip = + (((long) s->buffer[2] << 24) | ((long) s->buffer[3] << 16) | + ((long) s->buffer[4] << 8) | (long) s->buffer[5]); + break; + case MARKER_ATMOVE: + if (s->at_moves < JBG_ATMOVES_MAX) { + s->at_line[s->at_moves] = + (((long) s->buffer[2] << 24) | ((long) s->buffer[3] << 16) | + ((long) s->buffer[4] << 8) | (long) s->buffer[5]); + s->at_tx[s->at_moves] = (signed char) s->buffer[6]; + s->at_ty[s->at_moves] = s->buffer[7]; + if (s->at_tx[s->at_moves] < - (int) s->mx || + s->at_tx[s->at_moves] > (int) s->mx || + s->at_ty[s->at_moves] > (int) s->my || + (s->at_ty[s->at_moves] == 0 && s->at_tx[s->at_moves] < 0)) + return JBG_EINVAL; + if (s->at_ty[s->at_moves] != 0) + return JBG_EIMPL; + s->at_moves++; + } else + return JBG_EIMPL; + break; + case MARKER_NEWLEN: + y = (((long) s->buffer[2] << 24) | ((long) s->buffer[3] << 16) | + ((long) s->buffer[4] << 8) | (long) s->buffer[5]); + if (y > s->yd || !(s->options & JBG_VLENGTH)) + return JBG_EINVAL; + s->yd = y; + /* calculate again number of stripes that will be required */ + s->stripes = jbg_stripes(s->l0, s->yd, s->d); + break; + case MARKER_ABORT: + return JBG_EABORT; + + case MARKER_SDNORM: + case MARKER_SDRST: + /* decode final pixels based on trailing zero bytes */ + decode_pscd(s, s->buffer, 2); + + arith_decode_init(s->s[s->ii[iindex[s->order & 7][PLANE]]] + + s->ii[iindex[s->order & 7][LAYER]] - s->dl, + s->ii[iindex[s->order & 7][STRIPE]] != s->stripes - 1 + && s->buffer[1] != MARKER_SDRST); + + s->reset[s->ii[iindex[s->order & 7][PLANE]]] + [s->ii[iindex[s->order & 7][LAYER]] - s->dl] = + (s->buffer[1] == MARKER_SDRST); + + /* prepare for next SDE */ + s->x = 0; + s->i = 0; + s->pseudo = 1; + s->at_moves = 0; + + /* increment layer/stripe/plane loop variables */ + /* start and end value for each loop: */ + is[iindex[s->order & 7][STRIPE]] = 0; + ie[iindex[s->order & 7][STRIPE]] = s->stripes - 1; + is[iindex[s->order & 7][LAYER]] = s->dl; + ie[iindex[s->order & 7][LAYER]] = s->d; + is[iindex[s->order & 7][PLANE]] = 0; + ie[iindex[s->order & 7][PLANE]] = s->planes - 1; + i = 2; /* index to innermost loop */ + do { + j = 0; /* carry flag */ + if (++s->ii[i] > ie[i]) { + /* handling overflow of loop variable */ + j = 1; + if (i > 0) + s->ii[i] = is[i]; + } + } while (--i >= 0 && j); + + s->buf_len = 0; + + /* check whether this have been all SDEs */ + if (j) { +#ifdef DEBUG + fprintf(stderr, "This was the final SDE in this BIE, " + "%d bytes left.\n", len - *cnt); +#endif + s->bie_len = 0; + return JBG_EOK; + } + + /* check whether we have to abort because of xmax/ymax */ + if (iindex[s->order & 7][LAYER] == 0 && i < 0) { + /* LAYER is the outermost loop and we have just gone to next layer */ + if (jbg_ceil_half(s->xd, s->d - s->ii[0]) > s->xmax || + jbg_ceil_half(s->yd, s->d - s->ii[0]) > s->ymax) { + s->xmax = 4294967295UL; + s->ymax = 4294967295UL; + return JBG_EOK_INTR; + } + if (s->ii[0] > (unsigned long) s->dmax) { + s->dmax = 256; + return JBG_EOK_INTR; + } + } + + break; + } + s->buf_len = 0; + + } else if (data[*cnt] == MARKER_ESC) + s->buffer[s->buf_len++] = data[(*cnt)++]; + + else { + + /* we have found PSCD bytes */ + *cnt += decode_pscd(s, data + *cnt, len - *cnt); + if (*cnt < len && data[*cnt] != 0xff) { +#ifdef DEBUG + fprintf(stderr, "PSCD was longer than expected, unread bytes " + "%02x %02x %02x %02x ...\n", data[*cnt], data[*cnt+1], + data[*cnt+2], data[*cnt+3]); +#endif + return JBG_EINVAL; + } + + } + } /* of BID processing loop 'while (*cnt < len) ...' */ + + return JBG_EAGAIN; +} + + +/* + * After jbg_dec_in() returned JBG_EOK or JBG_EOK_INTR, you can call this + * function in order to find out the width of the image. + */ +long jbg_dec_getwidth(const struct jbg_dec_state *s) +{ + if (s->d < 0) + return -1; + if (iindex[s->order & 7][LAYER] == 0) { + if (s->ii[0] < 1) + return -1; + else + return jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1)); + } + + return s->xd; +} + + +/* + * After jbg_dec_in() returned JBG_EOK or JBG_EOK_INTR, you can call this + * function in order to find out the height of the image. + */ +long jbg_dec_getheight(const struct jbg_dec_state *s) +{ + if (s->d < 0) + return -1; + if (iindex[s->order & 7][LAYER] == 0) { + if (s->ii[0] < 1) + return -1; + else + return jbg_ceil_half(s->yd, s->d - (s->ii[0] - 1)); + } + + return s->yd; +} + + +/* + * After jbg_dec_in() returned JBG_EOK or JBG_EOK_INTR, you can call this + * function in order to get a pointer to the image. + */ +unsigned char *jbg_dec_getimage(const struct jbg_dec_state *s, int plane) +{ + if (s->d < 0) + return NULL; + if (iindex[s->order & 7][LAYER] == 0) { + if (s->ii[0] < 1) + return NULL; + else + return s->lhp[(s->ii[0] - 1) & 1][plane]; + } + + return s->lhp[s->d & 1][plane]; +} + + +/* + * After jbg_dec_in() returned JBG_EOK or JBG_EOK_INTR, you can call + * this function in order to find out the size in bytes of one + * bitplane of the image. + */ +long jbg_dec_getsize(const struct jbg_dec_state *s) +{ + if (s->d < 0) + return -1; + if (iindex[s->order & 7][LAYER] == 0) { + if (s->ii[0] < 1) + return -1; + else + return + jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1) + 3) * + jbg_ceil_half(s->yd, s->d - (s->ii[0] - 1)); + } + + return jbg_ceil_half(s->xd, 3) * s->yd; +} + + +/* + * After jbg_dec_in() returned JBG_EOK or JBG_EOK_INTR, you can call + * this function in order to find out the size of the image that you + * can retrieve with jbg_merge_planes(). + */ +long jbg_dec_getsize_merged(const struct jbg_dec_state *s) +{ + if (s->d < 0) + return -1; + if (iindex[s->order & 7][LAYER] == 0) { + if (s->ii[0] < 1) + return -1; + else + return + jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1)) * + jbg_ceil_half(s->yd, s->d - (s->ii[0] - 1)) * + ((s->planes + 7) / 8); + } + + return s->xd * s->yd * ((s->planes + 7) / 8); +} + + +/* + * The destructor function which releases any resources obtained by the + * other decoder functions. + */ +void jbg_dec_free(struct jbg_dec_state *s) +{ + int i; + extern char jbg_dptable[]; + + if (s->d < 0 || s->s == NULL) + return; + s->d = -2; + + for (i = 0; i < s->planes; i++) { + checked_free(s->s[i]); + checked_free(s->tx[i]); + checked_free(s->ty[i]); + checked_free(s->reset[i]); + checked_free(s->lntp[i]); + checked_free(s->lhp[0][i]); + checked_free(s->lhp[1][i]); + } + + checked_free(s->s); + checked_free(s->tx); + checked_free(s->ty); + checked_free(s->reset); + checked_free(s->lntp); + checked_free(s->lhp[0]); + checked_free(s->lhp[1]); + if (s->dppriv && s->dppriv != jbg_dptable) + checked_free(s->dppriv); + + s->s = NULL; + + return; +} + + +/* + * Split bigendian integer pixel field into separate bit planes. In the + * src array, every pixel is represented by a ((has_planes + 7) / 8) byte + * long word, most significant byte first. While has_planes describes + * the number of used bits per pixel in the source image, encode_plane + * is the number of most significant bits among those that we + * actually transfer to dest. + */ +void jbg_split_planes(unsigned long x, unsigned long y, int has_planes, + int encode_planes, + const unsigned char *src, unsigned char **dest, + int use_graycode) +{ + unsigned long bpl = jbg_ceil_half(x, 3); /* bytes per line in dest plane */ + unsigned long line, i; + unsigned k = 8; + int p; + unsigned prev; /* previous *src byte shifted by 8 bit to the left */ + register int bits, msb = has_planes - 1; + int bitno; + + /* sanity checks */ + if (encode_planes > has_planes) + encode_planes = has_planes; + use_graycode = use_graycode != 0 && encode_planes > 1; + + for (p = 0; p < encode_planes; p++) + memset(dest[p], 0, bpl * y); + + for (line = 0; line < y; line++) { /* lines loop */ + for (i = 0; i * 8 < x; i++) { /* dest bytes loop */ + for (k = 0; k < 8 && i * 8 + k < x; k++) { /* pixel loop */ + prev = 0; + for (p = 0; p < encode_planes; p++) { /* bit planes loop */ + /* calculate which bit in *src do we want */ + bitno = (msb - p) & 7; + /* put this bit with its left neighbor right adjusted into bits */ + bits = (prev | *src) >> bitno; + /* go to next *src byte, but keep old */ + if (bitno == 0) + prev = *src++ << 8; + /* make space for inserting new bit */ + dest[p][bpl * line + i] <<= 1; + /* insert bit, if requested apply Gray encoding */ + dest[p][bpl * line + i] |= (bits ^ (use_graycode & (bits>>1))) & 1; + /* + * Theorem: Let b(n),...,b(1),b(0) be the digits of a + * binary word and let g(n),...,g(1),g(0) be the digits of the + * corresponding Gray code word, then g(i) = b(i) xor b(i+1). + */ + } + /* skip unused *src bytes */ + for (;p < has_planes; p++) + if (((msb - p) & 7) == 0) + src++; + } + } + for (p = 0; p < encode_planes; p++) /* right padding loop */ + dest[p][bpl * (line + 1) - 1] <<= 8 - k; + } + + return; +} + +/* + * Merge the separate bit planes decoded by the JBIG decoder into an + * integer pixel field. This is essentially the counterpart to + * jbg_split_planes(). + */ +void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode, + void (*data_out)(unsigned char *start, size_t len, + void *file), void *file) +{ +#define BUFLEN 4096 + int bpp; + unsigned long bpl, line, i; + unsigned k = 8; + int p; + unsigned char buf[BUFLEN]; + unsigned char *bp = buf; + unsigned char **src; + unsigned long x, y; + unsigned v; + + /* sanity check */ + use_graycode = use_graycode != 0; + + x = jbg_dec_getwidth(s); + y = jbg_dec_getheight(s); + if (x <= 0 || y <= 0) + return; + bpp = (s->planes + 7) / 8; /* bytes per pixel in dest image */ + bpl = jbg_ceil_half(x, 3); /* bytes per line in src plane */ + + if (iindex[s->order & 7][LAYER] == 0) + if (s->ii[0] < 1) + return; + else + src = s->lhp[(s->ii[0] - 1) & 1]; + else + src = s->lhp[s->d & 1]; + + for (line = 0; line < y; line++) { /* lines loop */ + for (i = 0; i * 8 < x; i++) { /* src bytes loop */ + for (k = 0; k < 8 && i * 8 + k < x; k++) { /* pixel loop */ + v = 0; + for (p = 0; p < s->planes;) { /* dest bytes loop */ + do { + v = (v << 1) | + (((src[p][bpl * line + i] >> (7 - k)) & 1) ^ + (use_graycode & v)); + } while ((s->planes - ++p) & 7); + *bp++ = v; + if (bp - buf == BUFLEN) { + data_out(buf, BUFLEN, file); + bp = buf; + } + } + } + } + } + + if (bp - buf > 0) + data_out(buf, bp - buf, file); + + return; +} + + +/* + * Given a pointer p to the first byte of either a marker segment or a + * PSCD, as well as the length len of the remaining data, return + * either the pointer to the first byte of the next marker segment or + * PSCD, or p+len if this was the last one, or NULL if some error was + * encountered. + */ +unsigned char *jbg_next_pscdms(unsigned char *p, size_t len) +{ + unsigned char *pp; + unsigned long l; + + if (len < 2) + return NULL; + + if (p[0] != MARKER_ESC || p[1] == MARKER_STUFF) { + do { + while (p[0] == MARKER_ESC && p[1] == MARKER_STUFF) { + p += 2; + len -= 2; + if (len < 2) return NULL; + } + pp = (unsigned char *) memchr(p, MARKER_ESC, len - 1); + if (!pp) return NULL; + l = pp - p; + assert(l < len); + p += l; + len -= l; + } while (p[1] == MARKER_STUFF); + } else { + switch (p[1]) { + case MARKER_SDNORM: + case MARKER_SDRST: + case MARKER_ABORT: + return p + 2; + case MARKER_NEWLEN: + if (len < 6) return NULL; + return p + 6; + case MARKER_ATMOVE: + if (len < 8) return NULL; + return p + 8; + case MARKER_COMMENT: + if (len < 6) return NULL; + l = (((long) p[2] << 24) | ((long) p[3] << 16) | + ((long) p[4] << 8) | (long) p[5]); + if (len - 6 < l) return NULL; + return p + 6 + l; + default: + return NULL; + } + } + + return p; +} + + +/* + * Scan a complete BIE for a NEWLEN marker segment, then read the new + * YD value found in it and use it to overwrite the one in the BIE + * header. Use this procedure if a BIE initially declares an + * unreasonably high provisional YD value (e.g., 0xffffffff) or + * depends on the fact that section 6.2.6.2 of ITU-T T.82 says that a + * NEWLEN marker segment "could refer to a line in the immediately + * preceding stripe due to an unexpected termination of the image or + * the use of only such stripe". ITU-T.85 explicitely suggests the + * use of this for fax machines that start transmission before having + * encountered the end of the page. None of this is necessary for + * BIEs produced by JBIG-KIT, which normally does not use NEWLEN. + */ +int jbg_newlen(unsigned char *bie, size_t len) +{ + unsigned char *p = bie + 20; + int i; + + if (len < 20) + return JBG_EAGAIN; + if ((bie[19] & (JBG_DPON | JBG_DPPRIV | JBG_DPLAST)) + == (JBG_DPON | JBG_DPPRIV)) + p += 1728; /* skip DPTABLE */ + if (p >= bie + len) + return JBG_EAGAIN; + + while ((p = jbg_next_pscdms(p, len - (p - bie)))) { + if (p == bie + len) + return JBG_EOK; + else if (p[0] == MARKER_ESC) + switch (p[1]) { + case MARKER_NEWLEN: + /* overwrite YD in BIH with YD from NEWLEN */ + for (i = 0; i < 4; i++) { + bie[8+i] = p[2+i]; + } + return JBG_EOK; + case MARKER_ABORT: + return JBG_EABORT; + } + } + return JBG_EINVAL; +} diff --git a/kernel/kls_jbig/libjbig/jbig.h b/kernel/kls_jbig/libjbig/jbig.h new file mode 100644 index 0000000..1129ac0 --- /dev/null +++ b/kernel/kls_jbig/libjbig/jbig.h @@ -0,0 +1,270 @@ +/* + * Header file for the portable free JBIG compression library + * + * Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/ + * + * $Id: jbig.h,v 1.17 2004-06-11 15:18:21+01 mgk25 Exp $ + */ + +#ifndef JBG_H +#define JBG_H + +#include + +/* + * JBIG-KIT version number + */ + +#define JBG_VERSION "1.6" + +/* + * Buffer block for SDEs which are temporarily stored by encoder + */ + +#define JBG_BUFSIZE 4000 + +struct jbg_buf { + unsigned char d[JBG_BUFSIZE]; /* one block of a buffer list */ + int len; /* length of the data in this block */ + struct jbg_buf *next; /* pointer to next block */ + struct jbg_buf *previous; /* pointer to previous block * + * (unused in freelist) */ + struct jbg_buf *last; /* only used in list head: final block of list */ + struct jbg_buf **free_list; /* pointer to pointer to head of free list */ +}; + +/* + * Maximum number of ATMOVEs per stripe that decoder can handle + */ + +#define JBG_ATMOVES_MAX 64 + +/* + * Option and order flags + */ + +#define JBG_HITOLO 0x08 +#define JBG_SEQ 0x04 +#define JBG_ILEAVE 0x02 +#define JBG_SMID 0x01 + +#define JBG_LRLTWO 0x40 +#define JBG_VLENGTH 0x20 +#define JBG_TPDON 0x10 +#define JBG_TPBON 0x08 +#define JBG_DPON 0x04 +#define JBG_DPPRIV 0x02 +#define JBG_DPLAST 0x01 + +#define JBG_DELAY_AT 0x100 /* delay ATMOVE until the first line of the next + * stripe. Option available for compatibility + * with conformance test example in clause 7.2.*/ + + +/* + * Possible error code return values + */ + +#define JBG_EOK 0 +#define JBG_EOK_INTR 1 +#define JBG_EAGAIN 2 +#define JBG_ENOMEM 3 +#define JBG_EABORT 4 +#define JBG_EMARKER 5 +#define JBG_ENOCONT 6 +#define JBG_EINVAL 7 +#define JBG_EIMPL 8 + +/* + * Language code for error message strings (based on ISO 639 2-letter + * standard language name abbreviations). + */ + +#define JBG_EN 0 /* English */ +#define JBG_DE_8859_1 1 /* German in ISO Latin 1 character set */ +#define JBG_DE_UTF_8 2 /* German in Unicode UTF-8 encoding */ + +/* + * Status description of an arithmetic encoder + */ + +struct jbg_arenc_state { + unsigned char st[4096]; /* probability status for contexts, MSB = MPS */ + unsigned long c; /* C register, base of coding intervall, * + * layout as in Table 23 */ + unsigned long a; /* A register, normalized size of coding intervall */ + long sc; /* counter for buffered 0xff values which might overflow */ + int ct; /* bit shift counter, determines when next byte will be written */ + int buffer; /* buffer for most recent output byte != 0xff */ + void (*byte_out)(int, void *); /* function which receives all PSCD bytes */ + void *file; /* parameter passed to byte_out */ +}; + + +/* + * Status description of an arithmetic decoder + */ + +enum jbg_ardec_result { + JBG_OK, /* symbol has been successfully decoded */ + JBG_READY, /* no more bytes of this PSCD required, marker * + * encountered, probably more symbols available */ + JBG_MORE, /* more PSCD data bytes required to decode a symbol */ + JBG_MARKER /* more PSCD data bytes required, ignored final 0xff byte */ +}; + +struct jbg_ardec_state { + unsigned char st[4096]; /* probability status for contexts, MSB = MPS */ + unsigned long c; /* C register, base of coding intervall, * + * layout as in Table 25 */ + unsigned long a; /* A register, normalized size of coding intervall */ + int ct; /* bit shift counter, determines when next byte will be read */ + unsigned char *pscd_ptr; /* pointer to next PSCD data byte */ + unsigned char *pscd_end; /* pointer to byte after PSCD */ + enum jbg_ardec_result result; /* result of previous decode call */ + int startup; /* controls initial fill of s->c */ +}; + +/* + * Status of a JBIG encoder + */ + +struct jbg_enc_state { + int d; /* resolution layer of the input image */ + unsigned long xd, yd; /* size of the input image (resolution layer d) */ + unsigned long yd1; /* BIH announced height of image, use yd1 != yd to + emulate T.85-style NEWLEN height updates for tests */ + int planes; /* number of different bitmap planes */ + int dl; /* lowest resolution layer in the next BIE */ + int dh; /* highest resolution layer in the next BIE */ + unsigned long l0; /* number of lines per stripe at lowest * + * resolution layer 0 */ + unsigned long stripes; /* number of stripes required (determ. by l0) */ + unsigned char **lhp[2]; /* pointers to lower/higher resolution images */ + int *highres; /* index [plane] of highres image in lhp[] */ + int order; /* SDE ordering parameters */ + int options; /* encoding parameters */ + unsigned mx, my; /* maximum ATMOVE window size */ + int *tx; /* array [plane] with x-offset of adaptive template pixel */ + char *dppriv; /* optional private deterministic prediction table */ + char *res_tab; /* table for the resolution reduction algorithm */ + struct jbg_buf ****sde; /* array [stripe][layer][plane] pointers to * + * buffers for stored SDEs */ + struct jbg_arenc_state *s; /* array [planes] for arithm. encoder status */ + struct jbg_buf *free_list; /* list of currently unused SDE block buffers */ + void (*data_out)(unsigned char *start, size_t len, void *file); + /* data write callback */ + void *file; /* parameter passed to data_out() */ + char *tp; /* buffer for temp. values used by diff. typical prediction */ +}; + + +/* + * Status of a JBIG decoder + */ + +struct jbg_dec_state { + /* data from BIH */ + int d; /* resolution layer of the full image */ + int dl; /* first resolution layer in this BIE */ + unsigned long xd, yd; /* size of the full image (resolution layer d) */ + int planes; /* number of different bitmap planes */ + unsigned long l0; /* number of lines per stripe at lowest * + * resolution layer 0 */ + unsigned long stripes; /* number of stripes required (determ. by l0) */ + int order; /* SDE ordering parameters */ + int options; /* encoding parameters */ + int mx, my; /* maximum ATMOVE window size */ + char *dppriv; /* optional private deterministic prediction table */ + + /* loop variables */ + unsigned long ii[3]; /* current stripe, layer, plane (outer loop first) */ + + /* + * Pointers to array [planes] of lower/higher resolution images. + * lhp[d & 1] contains image of layer d. + */ + unsigned char **lhp[2]; + + /* status information */ + int **tx, **ty; /* array [plane][layer-dl] with x,y-offset of AT pixel */ + struct jbg_ardec_state **s; /* array [plane][layer-dl] for arithmetic * + * decoder status */ + int **reset; /* array [plane][layer-dl] remembers if previous stripe * + * in that plane/resolution ended with SDRST. */ + unsigned long bie_len; /* number of bytes read so far */ + unsigned char buffer[20]; /* used to store BIH or marker segments fragm. */ + int buf_len; /* number of bytes in buffer */ + unsigned long comment_skip; /* remaining bytes of a COMMENT segment */ + unsigned long x; /* x position of next pixel in current SDE */ + unsigned long i; /* line in current SDE (first line of each stripe is 0) */ + int at_moves; /* number of AT moves in the current stripe */ + unsigned long at_line[JBG_ATMOVES_MAX]; /* lines at which an * + * AT move will happen */ + int at_tx[JBG_ATMOVES_MAX], at_ty[JBG_ATMOVES_MAX]; /* ATMOVE offsets in * + * current stripe */ + unsigned long line_h1, line_h2, line_h3; /* variables of decode_pscd */ + unsigned long line_l1, line_l2, line_l3; + int pseudo; /* flag for TPBON/TPDON: next pixel is pseudo pixel */ + int **lntp; /* flag [plane][layer-dl] for TP: line is not typical */ + + unsigned long xmax, ymax; /* if possible abort before image gets * + * larger than this size */ + int dmax; /* abort after this layer */ +}; + + +/* some macros (too trivial for a function) */ + +#define jbg_dec_getplanes(s) ((s)->planes) + +#ifdef __cplusplus +extern "C" { +#endif + +/* function prototypes */ + +void jbg_enc_init(struct jbg_enc_state *s, unsigned long x, unsigned long y, + int planes, unsigned char **p, + void (*data_out)(unsigned char *start, size_t len, + void *file), + void *file); +int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long mwidth, + unsigned long mheight); +void jbg_enc_layers(struct jbg_enc_state *s, int d); +int jbg_enc_lrange(struct jbg_enc_state *s, int dl, int dh); +void jbg_enc_options(struct jbg_enc_state *s, int order, int options, + unsigned long l0, int mx, int my); +void jbg_enc_out(struct jbg_enc_state *s); +void jbg_enc_free(struct jbg_enc_state *s); + +void jbg_dec_init(struct jbg_dec_state *s); +void jbg_dec_maxsize(struct jbg_dec_state *s, unsigned long xmax, + unsigned long ymax); +int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, + size_t *cnt); +long jbg_dec_getwidth(const struct jbg_dec_state *s); +long jbg_dec_getheight(const struct jbg_dec_state *s); +unsigned char *jbg_dec_getimage(const struct jbg_dec_state *s, int plane); +long jbg_dec_getsize(const struct jbg_dec_state *s); +void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode, + void (*data_out)(unsigned char *start, size_t len, + void *file), void *file); +long jbg_dec_getsize_merged(const struct jbg_dec_state *s); +void jbg_dec_free(struct jbg_dec_state *s); + +const char *jbg_strerror(int errnum, int language); +void jbg_int2dppriv(unsigned char *dptable, const char *internal); +void jbg_dppriv2int(char *internal, const unsigned char *dptable); +unsigned long jbg_ceil_half(unsigned long x, int n); +void jbg_split_planes(unsigned long x, unsigned long y, int has_planes, + int encode_planes, + const unsigned char *src, unsigned char **dest, + int use_graycode); +int jbg_newlen(unsigned char *bie, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* JBG_H */ diff --git a/kernel/kls_jbig/libjbig/jbig_tab.c b/kernel/kls_jbig/libjbig/jbig_tab.c new file mode 100644 index 0000000..5518350 --- /dev/null +++ b/kernel/kls_jbig/libjbig/jbig_tab.c @@ -0,0 +1,428 @@ +/* + * Probability estimation tables for the arithmetic encoder/decoder + * given by ITU T.82 Table 24. + * + * $Id: jbig_tab.c,v 1.6 1998-04-05 18:36:19+01 mgk25 Rel $ + */ + +short jbg_lsz[113] = { + 0x5a1d, 0x2586, 0x1114, 0x080b, 0x03d8, 0x01da, 0x00e5, 0x006f, + 0x0036, 0x001a, 0x000d, 0x0006, 0x0003, 0x0001, 0x5a7f, 0x3f25, + 0x2cf2, 0x207c, 0x17b9, 0x1182, 0x0cef, 0x09a1, 0x072f, 0x055c, + 0x0406, 0x0303, 0x0240, 0x01b1, 0x0144, 0x00f5, 0x00b7, 0x008a, + 0x0068, 0x004e, 0x003b, 0x002c, 0x5ae1, 0x484c, 0x3a0d, 0x2ef1, + 0x261f, 0x1f33, 0x19a8, 0x1518, 0x1177, 0x0e74, 0x0bfb, 0x09f8, + 0x0861, 0x0706, 0x05cd, 0x04de, 0x040f, 0x0363, 0x02d4, 0x025c, + 0x01f8, 0x01a4, 0x0160, 0x0125, 0x00f6, 0x00cb, 0x00ab, 0x008f, + 0x5b12, 0x4d04, 0x412c, 0x37d8, 0x2fe8, 0x293c, 0x2379, 0x1edf, + 0x1aa9, 0x174e, 0x1424, 0x119c, 0x0f6b, 0x0d51, 0x0bb6, 0x0a40, + 0x5832, 0x4d1c, 0x438e, 0x3bdd, 0x34ee, 0x2eae, 0x299a, 0x2516, + 0x5570, 0x4ca9, 0x44d9, 0x3e22, 0x3824, 0x32b4, 0x2e17, 0x56a8, + 0x4f46, 0x47e5, 0x41cf, 0x3c3d, 0x375e, 0x5231, 0x4c0f, 0x4639, + 0x415e, 0x5627, 0x50e7, 0x4b85, 0x5597, 0x504f, 0x5a10, 0x5522, + 0x59eb +}; + +unsigned char jbg_nmps[113] = { + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 13, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 9, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 32, + 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 48, + 81, 82, 83, 84, 85, 86, 87, 71, + 89, 90, 91, 92, 93, 94, 86, 96, + 97, 98, 99, 100, 93, 102, 103, 104, + 99, 106, 107, 103, 109, 107, 111, 109, + 111 +}; + +/* + * least significant 7 bits (mask 0x7f) of jbg_nlps[] contain NLPS value, + * most significant bit (mask 0x80) contains SWTCH bit + */ +unsigned char jbg_nlps[113] = { + 129, 14, 16, 18, 20, 23, 25, 28, + 30, 33, 35, 9, 10, 12, 143, 36, + 38, 39, 40, 42, 43, 45, 46, 48, + 49, 51, 52, 54, 56, 57, 59, 60, + 62, 63, 32, 33, 165, 64, 65, 67, + 68, 69, 70, 72, 73, 74, 75, 77, + 78, 79, 48, 50, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 61, 61, + 193, 80, 81, 82, 83, 84, 86, 87, + 87, 72, 72, 74, 74, 75, 77, 77, + 208, 88, 89, 90, 91, 92, 93, 86, + 216, 95, 96, 97, 99, 99, 93, 223, + 101, 102, 103, 104, 99, 105, 106, 107, + 103, 233, 108, 109, 110, 111, 238, 112, + 240 +}; + +/* + * Resolution reduction table given by ITU-T T.82 Table 17 + */ + +char jbg_resred[4096] = { + 0,0,0,1,0,0,0,1,0,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,1,1,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, + 0,0,0,0,0,0,0,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,1,1,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, + 0,0,1,1,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, + 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,1,1,1,1, + 0,0,1,1,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,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1, + 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, + 0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1, + 0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1, + 1,1,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,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,1,1,1, + 0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,1,0,0,1,1,1,0,1,1, + 0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,1,0,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,1,1,0,1,1,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,1,0,0,1,1,0,1,1,0,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,0,0,0,1,0,1,0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1, + 1,0,0,1,0,0,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1, + 0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,1,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,1,1,1,1,1,0,1,1,1,0, + 0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,1,0,0,1,0,0,1,1,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1, + 0,0,0,1,0,0,0,1,0,1,1,0,1,0,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1, + 1,1,1,0,1,0,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1, + 1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,1, + 0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,1,1,0,1,0,1,1,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,1,0,1,0,0,1,0,0,1,1,0,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,0,0,0,1,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,1,1,1,1,0,1,1, + 1,0,0,1,0,0,1,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, + 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0, + 0,0,1,0,1,1,1,1,0,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0, + 0,0,0,0,1,0,0,1,0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,1,1,0,1,1,0,1,1,0,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,0,0,0,1,1,1,0,1,0,1,0,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1, + 0,0,1,0,0,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1, + 0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1,1,0,0,1,0,0,1,1, + 0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,1,0,1,0,1,0,1, + 0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1, + 0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,1,0,1,0,1,1,0,0,0,1,0,0,1,1, + 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,1,1,0,0,1,1, + 0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,1, + 0,0,1,0,0,1,1,1,0,0,0,0,1,0,0,1,0,0,0,1,1,1,1,0,1,0,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,1,1,0, + 0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,1,1,1,0,1,1,1, + 0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,1,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,1,1,1,0,0,1,1,1,0,1,1,0,0,1,1, + 0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1, + 0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,1,0,0,0,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,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,1,1,1,1, + 0,0,0,1,0,0,1,0,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,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1, + 0,0,1,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,1,1, + 0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1, + 0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1, + 0,1,1,1,1,1,1,1,1,1,1,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,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,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,1,1,0,1,1, + 0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,0,1,0,1,1,0,1,1,1,0,1,1,1, + 0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,0,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1, + 0,0,0,0,1,0,0,1,0,0,1,1,0,0,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1, + 1,0,1,0,1,0,0,1,1,0,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,0,1,1,0,1,1,1, + 0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,1,0,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,0,0,1,1,1,1,1,1,1,1,1, + 1,1,1,0,1,0,0,0,1,1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1, + 1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,1,1,0,1,1, + 0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,1,0,0,1,1,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,0,1,0,0,1,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,1,0,1,0,0,0,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1, + 1,0,0,0,1,0,0,0,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,1,1,1,0,1,1,0, + 0,0,1,1,1,1,1,1,0,0,0,0,1,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,1,1,1,1,1,1, + 0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1, + 0,0,1,0,1,0,1,1,0,0,1,0,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,0,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1, + 0,0,1,0,1,0,1,1,0,1,1,1,1,1,1,1,0,0,1,1,1,0,1,1,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1, + 0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1, + 0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,1,0,1,0,1,0,1, + 0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,1,0,0,1,1, + 0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,1, + 0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1, + 0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0, + 0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1, + 0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,1,0,0,1,1, + 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1, + 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0,1,0,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,1, + 0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,1,1,0,0,0,1,0,1,1,1,0,1,1,1 +}; + +/* + * Deterministic prediction tables given by ITU-T T.82 tables + * 19 to 22. The table below is organized differently, the + * index bits are permutated for higher efficiency. + */ + +char jbg_dptable[256 + 512 + 2048 + 4096] = { + /* phase 0: offset=0 */ + 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2, + 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,2,2,2,2,2,2,2, + 0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,2,0,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,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,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,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, + /* phase 1: offset=256 */ + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2, + 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,0,2,0,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2, + 0,2,2,2,2,1,2,1,2,2,2,2,1,1,1,1,2,0,2,0,2,2,2,2,0,2,0,2,2,2,2,2, + 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,0,2,2,2,2,2,2,2, + 0,2,0,2,2,2,2,2,2,2,2,2,2,0,2,0,2,2,0,0,2,2,2,2,2,0,0,2,2,2,2,2, + 0,2,2,2,2,1,2,1,2,2,2,2,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1, + 1,2,1,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,1,1,2,2,2,2,2,0,2,2,2,2,2,2, + 2,2,2,2,2,0,2,0,2,2,2,2,0,0,0,0,0,2,0,2,2,2,2,2,0,2,2,2,2,2,2,2, + 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,2,2,2,0,2,0,2,2,2,2,2, + 2,2,2,2,2,1,1,1,2,2,2,2,1,1,1,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,0,1,2,0,2,0,2,2,2,2,2,0,2,0,2,2,2,2,1, + 0,2,0,2,2,1,2,1,2,2,2,2,1,1,1,1,0,0,0,0,2,2,2,2,0,2,0,2,2,2,2,1, + 2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,0,0,0,2,2,2,2,2, + 2,2,2,2,2,1,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2,1,2,2,2,2,1, + 2,2,2,2,2,2,2,2,0,2,0,2,2,1,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2, + /* phase 2: offset=768 */ + 2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2,2,2,2,1,1,1,1, + 0,2,2,2,2,1,2,1,2,2,2,2,1,2,1,2,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1, + 2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,1,2,1,2,2,2,2,2,1,1,1, + 2,0,2,2,2,1,2,1,0,2,2,2,1,2,1,2,2,2,2,0,2,2,2,2,0,2,0,2,2,2,2,2, + 0,2,0,0,1,1,1,1,2,2,2,2,1,1,1,1,0,2,0,2,1,1,1,1,2,2,2,2,1,1,1,1, + 2,2,0,2,2,2,1,2,2,2,2,2,1,2,1,2,2,2,0,2,2,1,2,1,0,2,0,2,1,1,1,1, + 2,0,0,2,2,2,2,2,0,2,0,2,2,0,2,0,2,0,2,0,2,2,2,1,2,2,0,2,1,1,2,1, + 2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2,2,2,2,1,1,1,1, + 0,0,0,0,2,2,2,2,0,0,0,0,2,2,2,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,0,2,2,2,2,1,0,2,2,2,1,1,1,1,2,0,2,2,2,2,2,2,0,2,0,2,2,1,2,1, + 2,0,2,0,2,2,2,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2, + 0,2,2,2,1,2,1,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2, + 2,2,0,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,2,2,1,2,1,0,2,2,2,1,1,1,1, + 2,2,2,0,2,2,2,2,2,2,0,2,2,0,2,0,2,1,2,2,2,2,2,2,1,2,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,0,2,0,2,2,2,1, + 0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,1,1,1,2,2,2,2,1,1,1,1, + 2,2,2,1,2,2,2,2,2,2,1,2,0,0,0,0,2,2,0,2,2,1,2,2,2,2,2,2,1,1,1,1, + 2,0,0,0,2,2,2,2,0,2,2,2,2,2,2,0,2,2,2,0,2,2,2,2,2,0,0,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,0,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,1, + 0,2,0,2,2,1,1,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2, + 2,0,2,0,2,1,2,1,0,2,0,2,2,2,1,2,2,0,2,0,2,2,2,2,0,2,0,2,2,2,1,2, + 2,2,2,0,2,2,2,2,2,2,0,2,2,2,2,2,2,2,1,2,2,2,2,2,2,0,1,2,2,2,2,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1, + 0,2,2,2,1,2,1,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2, + 2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,1,2,1,0,2,2,2,1,1,1,1, + 2,0,2,0,2,1,2,2,0,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,1,2,2, + 2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,0,2,2,2,2,0,0,0,0,2,1,2,1, + 2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,1,2,0,0,2,2,2,1,2,2,2, + 0,0,2,0,2,2,2,2,0,2,0,2,2,0,2,0,1,1,1,2,2,2,2,2,2,2,2,2,2,1,1,1, + 2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,0,2,0,2,2,2,1, + 2,2,0,0,2,2,2,2,2,2,2,0,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,1,1,1,1,2,2,2,2,1,1,1,1, + 0,2,2,2,1,2,1,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2, + 2,0,0,2,2,2,2,2,0,2,0,2,2,2,2,2,1,0,1,2,2,2,2,1,0,2,2,2,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,0,2,2,0,2,0,2,1,2,2,2,2,2,2,2,2,0,2,2,1,2,2, + 0,2,0,0,1,1,1,1,0,2,2,2,1,1,1,1,2,2,2,2,2,2,2,2,2,0,2,2,1,2,1,1, + 2,2,0,2,2,1,2,2,2,2,2,2,1,2,2,2,2,0,2,2,2,2,2,2,0,2,0,2,1,2,1,1, + 2,0,2,0,2,2,2,2,0,2,0,2,2,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1, + 2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1, + 0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 0,2,2,2,2,0,2,0,2,2,2,2,0,0,0,0,2,2,2,2,2,1,1,2,2,2,2,2,1,2,2,2, + 2,0,2,2,2,1,2,1,0,2,2,2,2,2,1,2,2,0,2,0,2,2,2,2,0,2,0,2,2,1,2,2, + 0,2,0,0,2,2,2,2,1,2,2,2,2,2,2,0,2,1,2,2,2,2,2,2,1,2,2,2,2,2,2,2, + 0,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,1,0,2,2, + 0,0,0,2,2,1,1,1,2,2,2,2,1,2,2,2,2,0,2,0,2,2,2,1,2,2,2,2,1,2,1,2, + 0,0,0,0,2,2,2,2,2,2,0,2,2,1,2,2,2,1,2,1,2,2,2,2,1,2,1,2,0,2,2,2, + 2,0,2,0,2,2,2,2,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1, + 0,2,2,2,1,2,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,1,2,2,2,2,2,0,2,2,1,2,2,0,0,0,2,2,2,2,2,1,2,2,0,2,2,2,1,2,1,2, + 2,0,2,0,2,2,2,2,0,2,0,2,2,1,2,2,0,2,0,0,2,2,2,2,2,2,2,2,2,1,2,2, + 2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,0,2,0,2,2,2,1, + 1,2,0,2,2,1,2,1,2,2,2,2,1,2,2,2,2,0,2,0,2,2,2,2,2,0,2,2,1,1,1,1, + 0,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,2,1,2,1, + 2,2,0,0,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1, + 2,2,2,0,2,2,2,2,2,2,2,0,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,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2, + 2,0,2,0,2,2,2,2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,1,0,2,0,2,2,2,1,2, + 2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2, + 2,0,2,0,2,2,2,2,2,0,2,0,2,2,2,2,2,0,2,0,2,2,2,2,0,0,0,0,2,1,2,1, + 2,2,2,2,2,1,2,1,0,2,0,2,2,2,2,2,2,0,2,0,2,2,2,2,0,2,0,2,2,2,2,1, + 2,0,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,0, + 2,0,2,0,2,2,2,1,2,2,2,0,2,2,2,1,2,0,2,0,2,2,2,2,0,0,0,2,2,2,2,1, + 2,0,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2, + /* phase 3: offset=2816 */ + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,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,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1, + 0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,2,0,2,0,1,2,1,2,0,2,0,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,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,0,2,2,2,1,2,0,2,2,2,1,2,2,2,2,0,2,0,2,1,2,1,0,0,0,0,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,0,2,2,2,1,2, + 2,2,2,1,2,2,2,0,1,1,1,1,0,0,0,0,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,0,0,0,0,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1,0,0,0,0,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,1,2,1,2,0,2,0,2, + 2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1,2,0,2,0,2,1,2,1, + 2,0,0,0,2,1,1,1,0,0,0,0,1,1,1,1,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2, + 2,0,2,2,2,1,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,0,0,2,0,1,1,2,1, + 2,2,2,0,2,2,2,1,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,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,0,2,2,2,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,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1, + 0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,2,0,2,0,2,1,2,1,0,0,0,0,1,1,1,1, + 2,0,0,2,2,1,1,2,2,2,2,2,2,2,2,2,2,1,2,1,2,0,2,0,2,1,1,1,2,0,0,0, + 2,1,2,1,2,0,2,0,1,2,1,2,0,2,0,2,2,2,2,0,2,2,2,1,2,0,2,0,2,1,2,1, + 2,0,2,0,2,1,2,1,0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1, + 2,2,2,2,2,2,2,2,2,0,0,0,2,1,1,1,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2, + 0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2, + 2,0,0,0,2,1,1,1,0,0,0,0,1,1,1,1,2,0,2,0,2,1,2,1,0,0,2,0,1,1,2,1, + 2,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,0,0,0,2,1,1,1, + 2,2,2,1,2,2,2,0,2,1,1,1,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,1,2,1,2,0,2,0,1,2,1,2,0,2,0,2, + 2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1, + 2,2,2,2,2,2,2,2,2,0,2,2,2,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, + 0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,1,1,1,0,0,0,0,1,1,1,1, + 2,0,2,2,2,1,2,2,0,0,2,0,1,1,2,1,2,1,2,1,2,0,2,0,2,2,2,2,2,2,2,2, + 2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,0,0,0,0,1,1,1,1, + 2,0,0,0,2,1,1,1,0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,2,1,0,2,2,0,1,2, + 2,2,2,1,2,2,2,0,2,1,1,1,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1, + 2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,0,2,2,2,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,0,2,2,2,1, + 0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,2, + 2,1,2,1,2,0,2,0,1,2,1,1,0,2,0,0,0,0,2,1,1,1,2,0,0,0,0,0,1,1,1,1, + 2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,0,2,1,2,1,2,0,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,0,2,2,2,1,2,2,0,2,2,2,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,1,2,2,2,0,2,2,2,2,0,2,2,2,1,2,2,2,0,0,2,2,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,0,2,2,2,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,0,2,2,2,1,2,2,2,2,2,2,2,2,2, + 0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2, + 2,0,2,0,2,1,2,1,0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,0,0,0,0,1,1,1,1, + 2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,0,0,0,2,1,1,1, + 2,2,2,0,2,2,2,1,0,2,2,2,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,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2, + 2,0,2,2,2,1,2,2,2,0,2,0,2,1,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1, + 2,1,2,1,2,0,2,0,1,2,1,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,1,2,1,2,0,2,0,1,2,1,1,0,2,0,0,2,0,2,2,2,1,2,2,0,2,1,2,1,2,0,2, + 2,2,2,1,2,2,2,0,2,2,1,2,2,2,0,2,2,1,2,2,2,0,2,2,2,2,0,2,2,2,1,2, + 0,0,2,0,1,1,2,1,0,0,1,0,1,1,0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,0,2,2,2,1,1,2,2,2,0,2,2,2,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1, + 2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1, + 2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,0,0,2,2,1,1,2,2,2,0,2,2,2,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,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,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2, + 0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2, + 2,0,0,0,2,1,1,1,0,0,0,0,1,1,1,1,2,2,2,1,2,2,2,0,2,1,2,1,2,0,2,0, + 2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,2,0,2,0,0,1,2,1,1,2,0,0,0,2,1,1,1, + 2,2,2,2,2,2,2,2,2,1,1,1,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,0,2,2,2,1,2,2,0,2,2,2,1,2,2,1,2,1,2,0,2,0,2,0,2,2,2,1,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,1,1,1,2,0,0,0, + 2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,0,2,0,0,1,2,1,1, + 2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,0,2,2,2,1,2,2,2, + 2,1,2,1,2,0,2,0,2,1,2,2,2,0,2,2,2,2,2,0,2,2,2,1,2,0,2,0,2,1,2,1, + 2,0,2,0,2,1,2,1,0,2,0,2,1,2,1,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2, + 2,2,2,2,2,2,2,2,0,2,0,2,1,2,1,2,2,2,2,2,2,2,2,2,0,1,0,0,1,0,1,1, + 2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,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,2,2,2,2,2,2,2,2,2,2,2,2,2, + 0,2,2,2,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, + 0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,2,2,1,2,2,2,0,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,0,1,2,2,1,0,2,0,2,2,2,1,2,2,2, + 2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,2,2,0,2,2,2,1,2,2,0,2,2,2,1,2, + 2,0,2,0,2,1,2,1,0,2,0,2,1,2,1,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2, + 0,2,0,0,1,2,1,1,2,0,0,0,2,1,1,1,2,2,2,2,2,2,2,2,1,0,1,2,0,1,0,2, + 2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,1,2,2,2,0,2,2,1,1,2,2,0,0,2,2, + 0,2,2,2,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,1,2,1,2,0,2,0,2,1,2,2,2,0,2,2,2,0,2,2,2,1,2,2,0,2,2,2,1,2,2,2, + 0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,1,2,2,2,0,2,2,2, + 2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1,2, + 0,0,0,0,1,1,1,1,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,2,0,2,0,2,2,0,2,2,2,1,2, + 2,0,2,0,2,1,2,1,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,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,0,2,2,2,1,2,2,2,2,2,2,2,2,2, + 0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,1,2,2,2,0,1,1,2,1,0,0,2,0,2,0,2,2,2,1,2,2,0,2,2,2,1,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2,2,2,0,2,2,2,1,2, + 2,0,2,0,2,1,2,1,0,2,0,2,1,2,1,2,2,2,2,2,2,2,2,2,2,1,2,2,2,0,2,2, + 0,2,0,0,1,2,1,1,0,2,0,2,1,2,1,2,2,2,2,2,2,2,2,2,0,0,0,2,1,1,1,2, + 2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1, + 2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,0,0,2,1,1,1,2,0,0,2,2,2,1,2,2,2, + 2,1,2,1,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,0,1,2,1,1, + 0,0,2,2,1,1,2,2,0,2,1,2,1,2,0,2,2,1,2,1,2,0,2,0,1,2,1,2,0,2,0,2, + 2,2,2,2,2,2,2,2,1,2,1,2,0,2,0,2,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1, + 2,2,0,0,2,2,1,1,2,2,0,0,2,2,1,1,2,2,2,2,2,2,2,2,2,2,0,0,2,2,1,1, + 2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,0,0,1,2,1,1, + 2,2,2,0,2,2,2,1,2,2,2,0,2,2,2,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,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,1,1,1,2,0,0,0,2, + 2,2,2,2,2,2,2,2,1,1,1,2,0,0,0,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2, + 2,0,2,0,2,1,2,1,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,0,0,0,2,1,1,1, + 2,0,2,2,2,1,2,2,0,2,2,2,1,2,2,2,2,0,2,0,2,1,2,1,2,2,2,2,2,2,2,2, + 2,0,2,0,2,1,2,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,2,2,2,2,2, + 2,0,2,0,2,1,2,1,2,1,2,0,2,0,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,0,2,0,2,1,2,1,1,2,1,2,0,2,0,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,1,2,1,2,0,2,0,2,2,1,2,1,2,0,2,0,2,2,2,2,2,2,2,2, + 2,0,2,1,2,1,2,0,0,2,1,2,1,2,0,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1, + 2,0,2,0,2,1,2,1,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,0,2,0,2,1,2,1, + 2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,0,2,2,2,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,1,2,1,2,0,2,0,1,1,1,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1, + 2,0,2,0,2,1,2,1,2,2,2,0,2,2,2,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,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +}; diff --git a/kernel/kls_jpeg/Makefile.am b/kernel/kls_jpeg/Makefile.am new file mode 100644 index 0000000..7717e5e --- /dev/null +++ b/kernel/kls_jpeg/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_jpeg.la + +libkls_jpeg_la_SOURCES = fmt_codec_jpeg.cpp fmt_codec_jpeg_defs.h + +libkls_jpeg_la_LDFLAGS = ${SQ_RELEASE} + +libkls_jpeg_la_LIBADD = ${SQ_LOCAL_RPATH} -ljpeg \ No newline at end of file diff --git a/kernel/kls_jpeg/fmt_codec_jpeg.cpp b/kernel/kls_jpeg/fmt_codec_jpeg.cpp new file mode 100644 index 0000000..60fe8e8 --- /dev/null +++ b/kernel/kls_jpeg/fmt_codec_jpeg.cpp @@ -0,0 +1,308 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_jpeg_defs.h" +#include "fmt_codec_jpeg.h" + +#include "../xpm/codec_jpeg.xpm" + +/* + * + * JPEG (Joint Photographic Experts Group) refers to a + * standards organization, a method of file compression, and sometimes a + * file format. In fact, the JPEG specification + * itself does not define a common file interchange + * format to store and transport JPEG data between + * computer platforms and operating systems. The JPEG + * File Interchange Format (JFIF) is a development of + * C-Cube Microsystems for the purpose of storing + * JPEG-encoded data. JFIF is + * designed to allow files containing JPEG-encoded + * data streams to be exchanged between otherwise incompatible systems + * and applications. + * + */ + +METHODDEF(void) my_error_exit(j_common_ptr cinfo) +{ + my_error_ptr myerr; + + myerr = (my_error_ptr) cinfo->err; + + (*cinfo->err->output_message) (cinfo); + + longjmp(myerr->setjmp_buffer, 1); +} + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "1.3.4.1"; + o->name = "JPEG compressed"; + o->filter = "*.jpg *.jpeg *.jpe "; + o->config = ""; + o->mime = "\x00FF\x00D8\x00FF"; + o->mimetype = "image/jpeg"; + o->pixmap = codec_jpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + zerror = false; + + fptr = fopen(file.c_str(), "rb"); + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; + + if(setjmp(jerr.setjmp_buffer)) + { + zerror = true; + return SQE_R_BADFILE; + } + + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo, fptr); + jpeg_save_markers(&cinfo, JPEG_COM, 0xffff); + jpeg_read_header(&cinfo, TRUE); + + if(cinfo.jpeg_color_space == JCS_GRAYSCALE) + { + cinfo.out_color_space = JCS_RGB; + cinfo.desired_number_of_colors = 256; + cinfo.quantize_colors = FALSE; + cinfo.two_pass_quantize = FALSE; + } + + jpeg_start_decompress(&cinfo); + + image.w = cinfo.output_width; + image.h = cinfo.output_height; + + buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, cinfo.output_width * cinfo.output_components, 1); + + std::string type; + + switch(cinfo.jpeg_color_space) + { + case JCS_GRAYSCALE: type = "Grayscale"; image.bpp = 8; break; + case JCS_RGB: type = "RGB"; image.bpp = 24; break; + case JCS_YCbCr: type = "YUV"; image.bpp = 24; break; + case JCS_CMYK: type = "CMYK"; image.bpp = 32; break; + case JCS_YCCK: type = "YCCK"; image.bpp = 32; break; + + default: + type = "Unknown"; + } + + image.compression = "JPEG"; + image.colorspace = type; + + jpeg_saved_marker_ptr it = cinfo.marker_list; + + while(it) + { + if(it->marker == JPEG_COM) + { + fmt_metaentry mt; + + mt.group = "Comment"; + s8 data[it->data_length+1]; + memcpy(data, it->data, it->data_length); + data[it->data_length] = '\0'; + mt.data = data; + + addmeta(mt); + + break; + } + + it = it->next; + } + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + if(zerror || setjmp(jerr.setjmp_buffer)) + { + zerror = true; + return SQE_R_BADFILE; + } + + (void)jpeg_read_scanlines(&cinfo, buffer, 1); + + for(s32 i = 0;i < im->w;i++) + memcpy(scan+i, buffer[0] + i*3, 3); + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + jpeg_abort_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionInternal; + opt->compression_min = 0; + opt->compression_max = 100; + opt->compression_def = 25; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + m_fptr = fopen(file.c_str(), "wb"); + + if(!m_fptr) + return SQE_W_NOFILE; + + m_cinfo.err = jpeg_std_error(&m_jerr); + + jpeg_create_compress(&m_cinfo); + + jpeg_stdio_dest(&m_cinfo, m_fptr); + + m_cinfo.image_width = image.w; + m_cinfo.image_height = image.h; + m_cinfo.input_components = 3; + m_cinfo.in_color_space = JCS_RGB; + + jpeg_set_defaults(&m_cinfo); + + jpeg_set_quality(&m_cinfo, 100-opt.compression_level, true); + + jpeg_start_compress(&m_cinfo, true); + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + return SQE_OK; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + RGB sr[writeimage.w]; + + for(s32 s = 0;s < writeimage.w;s++) + { + memcpy(sr+s, scan+s, sizeof(RGB)); + } + + row_pointer = (JSAMPLE *)sr; + + (void)jpeg_write_scanlines(&m_cinfo, &row_pointer, 1); + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + jpeg_finish_compress(&m_cinfo); + + fclose(m_fptr); + + jpeg_destroy_compress(&m_cinfo); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("jpeg"); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_jpeg/fmt_codec_jpeg_defs.h b/kernel/kls_jpeg/fmt_codec_jpeg_defs.h new file mode 100644 index 0000000..89f1edc --- /dev/null +++ b/kernel/kls_jpeg/fmt_codec_jpeg_defs.h @@ -0,0 +1,42 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_jpg +#define KSQUIRREL_READ_IMAGE_jpg + +// thanks Trolltech's QT +extern "C" { +#define XMD_H // shut JPEGlib up +#include +#ifdef const +# undef const // remove crazy C hackery in jconfig.h +#endif +} + +struct my_error_mgr +{ + struct jpeg_error_mgr pub; + jmp_buf setjmp_buffer; +}; + +typedef struct my_error_mgr * my_error_ptr; + +#endif diff --git a/kernel/kls_jpeg2000/Makefile.am b/kernel/kls_jpeg2000/Makefile.am new file mode 100644 index 0000000..7fc2b3d --- /dev/null +++ b/kernel/kls_jpeg2000/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_jpeg2000.la + +libkls_jpeg2000_la_SOURCES = fmt_codec_jpeg2000.cpp fmt_codec_jpeg2000_defs.h + +libkls_jpeg2000_la_LDFLAGS = ${SQ_RELEASE} + +libkls_jpeg2000_la_LIBADD = ${SQ_LOCAL_RPATH} -ljasper \ No newline at end of file diff --git a/kernel/kls_jpeg2000/fmt_codec_jpeg2000.cpp b/kernel/kls_jpeg2000/fmt_codec_jpeg2000.cpp new file mode 100644 index 0000000..c4fecf0 --- /dev/null +++ b/kernel/kls_jpeg2000/fmt_codec_jpeg2000.cpp @@ -0,0 +1,277 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" + +#undef PACKAGE +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION +#undef VERSION + +#include + +#include "fmt_codec_jpeg2000_defs.h" +#include "fmt_codec_jpeg2000.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "ksquirrel-libs/error.h" + +#include "../xpm/codec_jpeg2000.xpm" + +/* + * + * JPEG 2000 standard supports lossy and lossless compression of + * single-component (e.g., grayscale) and multicomponent (e.g., color) + * imagery. + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{ + jas_init(); +} + +fmt_codec::~fmt_codec() +{ + jas_cleanup(); +} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.4.0"; + o->name = "JPEG 2000"; + o->filter = "*.jp2 *.j2k "; + + // mime is "....\152\120\040\040", + // but some jp2 files don't have this mime header (why ?) + // => o->mime is empty + o->mime = ""; + o->mimetype = "image/jp2"; + o->config = ""; + o->pixmap = codec_jpeg2000; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + gs.image = 0; + gs.altimage = 0; + gs.data[0] = 0; + gs.data[1] = 0; + gs.data[2] = 0; + + in = jas_stream_fopen(file.c_str(), "rb"); + + if(!in) + return SQE_R_NOFILE; + + currentImage = -1; + read_error = false; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + gs.image = jas_image_decode(in, -1, 0); + + jas_stream_close(in); + + if(!gs.image) + return SQE_R_NOMEMORY; + + s32 family = jas_clrspc_fam(jas_image_clrspc(gs.image)); + + if(!convert_colorspace()) + return SQE_R_BADFILE; + + jas_image_destroy(gs.image); + gs.image = gs.altimage; + gs.altimage = 0; + + image.w = jas_image_width(gs.image); + image.h = jas_image_height(gs.image); + + switch(family) + { + case JAS_CLRSPC_FAM_RGB: + image.colorspace = "RGB"; + image.bpp = 24; + break; + + case JAS_CLRSPC_FAM_YCBCR: + image.colorspace = "YCbCr"; + image.bpp = 24; + break; + + case JAS_CLRSPC_FAM_GRAY: + image.colorspace = "Grayscale"; + image.bpp = 8; + break; + + case JAS_CLRSPC_FAM_LAB: + image.colorspace = "LAB"; + image.bpp = 24; + break; + + default: + image.colorspace = "Unknown"; + image.bpp = 0; + } + + image.compression = "JPEG2000"; + + if((gs.cmptlut[0] = jas_image_getcmptbytype(gs.image, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R))) < 0 || + (gs.cmptlut[1] = jas_image_getcmptbytype(gs.image, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G))) < 0 || + (gs.cmptlut[2] = jas_image_getcmptbytype(gs.image, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B))) < 0) + + return SQE_R_NOMEMORY; + + const s32 *cmptlut = gs.cmptlut; + + // check that all components have the same size. + const s32 width = jas_image_cmptwidth(gs.image, cmptlut[0]); + const s32 height = jas_image_cmptheight(gs.image, cmptlut[0]); + + for(s32 i = 1; i < 3; ++i) + { + if(jas_image_cmptwidth(gs.image, cmptlut[i]) != width || + jas_image_cmptheight(gs.image, cmptlut[i]) != height) + + return SQE_R_BADFILE; + } + + for(s32 i = 0;i < 3;i++) + { + if(!(gs.data[i] = jas_matrix_create(1, image.w))) + return SQE_R_BADFILE; + } + + finfo.image.push_back(image); + + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + fmt_image *im = image(currentImage); + jas_seqent_t v; + + fmt_utils::fillAlpha(scan, im->w); + + line++; + + u8 *data = (u8 *)scan; + + for(s32 cmptno = 0; cmptno < 3; ++cmptno) + { + if(jas_image_readcmpt(gs.image, gs.cmptlut[cmptno], 0, line, im->w, 1, gs.data[cmptno])) + return SQE_R_BADFILE; + + gs.d[cmptno] = jas_matrix_getref(gs.data[cmptno], 0, 0); + } + + for(s32 x = 0; x < im->w;++x) + { + for(int k = 0; k < 3; ++k) + { + v = *gs.d[k]; + + if(v < 0) + v = 0; + else if(v > 255) + v = 255; + + *data = v; + data++; + + ++gs.d[k]; + } + + data++; + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + for(s32 cmptno = 0; cmptno < 3; ++cmptno) + { + if (gs.data[cmptno]) + jas_matrix_destroy(gs.data[cmptno]); + } + + if(gs.image) jas_image_destroy(gs.image); + if(gs.altimage) jas_image_destroy(gs.altimage); + + finfo.meta.clear(); + finfo.image.clear(); +} + +// helper method +bool fmt_codec::convert_colorspace() +{ + jas_cmprof_t *outprof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB); + + if(!outprof) + return false; + + gs.altimage = jas_image_chclrspc(gs.image, outprof, JAS_CMXFORM_INTENT_PER); + + if(!gs.altimage) + return false; + + jas_cmprof_destroy(outprof); + + return true; +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_jpeg2000/fmt_codec_jpeg2000_defs.h b/kernel/kls_jpeg2000/fmt_codec_jpeg2000_defs.h new file mode 100644 index 0000000..0fb6150 --- /dev/null +++ b/kernel/kls_jpeg2000/fmt_codec_jpeg2000_defs.h @@ -0,0 +1,28 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_jpeg2000 +#define KSQUIRREL_CODEC_DEFS_jpeg2000 + +const float DEFAULT_RATE = 0.10; +const unsigned MAXCMPTS = 256; + +#endif diff --git a/kernel/kls_koala/Makefile.am b/kernel/kls_koala/Makefile.am new file mode 100644 index 0000000..468bb0a --- /dev/null +++ b/kernel/kls_koala/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_koala.la + +libkls_koala_la_SOURCES = fmt_codec_koala.cpp fmt_codec_koala_defs.h + +libkls_koala_la_LDFLAGS = ${SQ_RELEASE} + +libkls_koala_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_koala/fmt_codec_koala.cpp b/kernel/kls_koala/fmt_codec_koala.cpp new file mode 100644 index 0000000..2c91e48 --- /dev/null +++ b/kernel/kls_koala/fmt_codec_koala.cpp @@ -0,0 +1,207 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_koala_defs.h" +#include "fmt_codec_koala.h" + +#include "ksquirrel-libs/error.h" + +#include "../xpm/codec_koala.xpm" + +// Code partially taken from FreeImage3 + +/* + * + * Commodore 64 Koala + * + */ + +const RGB c64pal[16] = +{ + RGB( 0, 0, 0 ), // Black + RGB( 255, 255, 255 ), // White + RGB( 170, 17, 17 ), // Red + RGB( 12, 204, 204 ), // Cyan + RGB( 221, 51, 221 ), // Purple + RGB( 0, 187, 0 ), // Green + RGB( 0, 0, 204 ), // Blue + RGB( 255, 255, 140 ), // Yellow + RGB( 204, 119, 34 ), // Orange + RGB( 136, 68, 0 ), // Brown + RGB( 255, 153, 136 ), // Light red + RGB( 92, 92, 92 ), // Gray 1 + RGB( 170, 170, 170 ), // Gray 2 + RGB( 140, 255, 178 ), // Light green + RGB( 39, 148, 255 ), // Light blue + RGB( 196, 196, 196 ) // Gray 3 +}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.2.2"; + o->name = "Commodore 64 Koala"; + o->filter = "*.koa *.kla "; + o->config = ""; + o->mime = "\x0000\x0060"; + o->mimetype = "image/x-koala"; + o->pixmap = codec_koala; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + read_error = false; + + finfo.animated = false; + + pixel_mask[0] = 0xc0; + pixel_mask[1] = 0x30; + pixel_mask[2] = 0x0c; + pixel_mask[3] = 0x03; + + pixel_displ[0] = 6; + pixel_displ[1] = 4; + pixel_displ[2] = 2; + pixel_displ[3] = 0; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + u8 load[2]; + + if(!frs.readK(load, sizeof(load))) + return SQE_R_BADFILE; + + if(load[0] != 0x00 || load[1] != 0x60) + { + ((u8 *)&koala)[0] = load[0]; + ((u8 *)&koala)[1] = load[1]; + + if(!frs.readK((u8 *)&koala + 2, 10001 - 2)) + return SQE_R_BADFILE; + } + else + { + if(!frs.readK((u8 *)&koala, 10001)) + return SQE_R_BADFILE; + } + + foundcolor = 0; + + image.w = KOALA_WIDTH; + image.h = KOALA_HEIGHT; + image.bpp = 8; + image.compression = "-"; + image.colorspace = fmt_utils::colorSpaceByBpp(8); + + finfo.image.push_back(image); + + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + line++; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + for(s32 x = 0;x < KOALA_WIDTH / 2;x++) + { + index = (x / 4) * 8 + (line % 8) + (line / 8) * KOALA_WIDTH; + colorindex = (x / 4) + (line / 8) * 40; + pixel = (koala.image[index] & pixel_mask[x % 4]) >> pixel_displ[x % 4]; + + // Retrieve RGB values + switch(pixel) + { + case 0: // Background + foundcolor = koala.background; + break; + + case 1: // Color 1 + foundcolor = koala.color1[colorindex] >> 4; + break; + + case 2: // Color 2 + foundcolor = koala.color1[colorindex] & 0xf; + break; + + case 3: // Color 3 + foundcolor = koala.color2[colorindex] & 0xf; + break; + } + + memcpy(scan+x*2, c64pal+foundcolor, sizeof(RGB)); + memcpy(scan+x*2+1, c64pal+foundcolor, sizeof(RGB)); + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_koala/fmt_codec_koala_defs.h b/kernel/kls_koala/fmt_codec_koala_defs.h new file mode 100644 index 0000000..c655f29 --- /dev/null +++ b/kernel/kls_koala/fmt_codec_koala_defs.h @@ -0,0 +1,39 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_koala +#define KSQUIRREL_CODEC_DEFS_koala + +// Koala has constant width and height (like FLIC) + +#define KOALA_WIDTH 320 +#define KOALA_HEIGHT 200 + +typedef struct +{ + u8 image[8000]; // pixmap image + u8 color1[1000]; // first colormap (color 1 and 2) + u8 color2[1000]; // second colormap (color 3) + u8 background; // background color + +} koala_t; + +#endif diff --git a/kernel/kls_leaf/Makefile.am b/kernel/kls_leaf/Makefile.am new file mode 100644 index 0000000..f71925f --- /dev/null +++ b/kernel/kls_leaf/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I../include + +bin_SCRIPTS = ksquirrel-libs-leaf2ppm + +pkglib_LTLIBRARIES = libkls_leaf.la + +libkls_leaf_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_leaf_la_LDFLAGS = ${SQ_RELEASE} + +libkls_leaf_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DCODEC_NETPBM -DCODEC_LEAF -DNETPBM_S=\"${bindir}/ksquirrel-libs-leaf2ppm\" + +EXTRA_DIST = ksquirrel-libs-leaf2ppm.in \ No newline at end of file diff --git a/kernel/kls_leaf/fmt_codec_pnm.cpp b/kernel/kls_leaf/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_leaf/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_leaf/fmt_codec_pnm_defs.h b/kernel/kls_leaf/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_leaf/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_leaf/ksquirrel-libs-leaf2ppm.in b/kernel/kls_leaf/ksquirrel-libs-leaf2ppm.in new file mode 100644 index 0000000..3c77877 --- /dev/null +++ b/kernel/kls_leaf/ksquirrel-libs-leaf2ppm.in @@ -0,0 +1,3 @@ +#!/bin/sh + +@LEAFTOPPM@ "$1" > "$2" \ No newline at end of file diff --git a/kernel/kls_lif/Makefile.am b/kernel/kls_lif/Makefile.am new file mode 100644 index 0000000..8375d24 --- /dev/null +++ b/kernel/kls_lif/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_lif.la + +libkls_lif_la_SOURCES = fmt_codec_lif.cpp fmt_codec_lif_defs.h + +libkls_lif_la_LDFLAGS = ${SQ_RELEASE} + +libkls_lif_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_lif/fmt_codec_lif.cpp b/kernel/kls_lif/fmt_codec_lif.cpp new file mode 100644 index 0000000..edc87b8 --- /dev/null +++ b/kernel/kls_lif/fmt_codec_lif.cpp @@ -0,0 +1,155 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_lif_defs.h" +#include "fmt_codec_lif.h" + +#include "ksquirrel-libs/error.h" + +#include "../xpm/codec_lif.xpm" + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.1.2"; + o->name = "Homeworld LIF"; + o->filter = "*.lif "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-lif"; + o->pixmap = codec_lif; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + read_error = false; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + if(!frs.readK(&lif, sizeof(lif_header))) return SQE_R_BADFILE; +/* + lif.version = fmt_utils::konvertLong(lif.version); + lif.flags = fmt_utils::konvertLong(lif.flags); + lif.width = fmt_utils::konvertLong(lif.width); + lif.height = fmt_utils::konvertLong(lif.height); + lif.palOffset = fmt_utils::konvertLong(lif.palOffset); + + + if(lif.version != LIF_VERSION || lif.flags != LIF_FLAGS) + return SQE_R_BADFILE; +*/ + + if(strcmp(lif.id, LIF_ID)) + return SQE_R_BADFILE; + + image.w = lif.width; + image.h = lif.height; + + fstream::pos_type pos = frs.tellg(); + + frs.seekg(lif.width * lif.height, ios::beg); + + if(!frs.readK(pal, sizeof(pal))) + return SQE_R_BADFILE; + + frs.seekg(pos); + + image.compression = "-"; + image.colorspace = fmt_utils::colorSpaceByBpp(8); + image.bpp = 8; + image.hasalpha = (bool)(lif.flags & 0x08); + + bytes = image.hasalpha ? sizeof(RGBA) : sizeof(RGB); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + u8 c; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + for(s32 i = 0;i < im->w;i++) + { + if(!frs.readK(&c, sizeof(u8))) return SQE_R_BADFILE; + + c++; + + memcpy(scan+i, pal+c, bytes); + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_lif/fmt_codec_lif_defs.h b/kernel/kls_lif/fmt_codec_lif_defs.h new file mode 100644 index 0000000..cb0fd1c --- /dev/null +++ b/kernel/kls_lif/fmt_codec_lif_defs.h @@ -0,0 +1,41 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_lif +#define KSQUIRREL_CODEC_DEFS_lif + +#define LIF_VERSION 260 +#define LIF_FLAGS 50 +#define LIF_ID "Willy 7" + +struct lif_header +{ + s8 id[8]; // "Willy 7" + s32 version; // Version Number (260) + s32 flags; // Usually 50 + s32 width; + s32 height; + u32 paletteCRC; // CRC of palettes for fast comparison. + u32 imageCRC; // CRC of the image. + +}PACKED; + +#endif diff --git a/kernel/kls_ljpeg/Makefile.am b/kernel/kls_ljpeg/Makefile.am new file mode 100644 index 0000000..e2f720d --- /dev/null +++ b/kernel/kls_ljpeg/Makefile.am @@ -0,0 +1,17 @@ +SUBDIRS = ljpeg2ppm + +INCLUDES = -I../include + +bin_SCRIPTS = ksquirrel-libs-ljpeg2ppm-s + +pkglib_LTLIBRARIES = libkls_ljpeg.la + +libkls_ljpeg_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_ljpeg_la_LDFLAGS = ${SQ_RELEASE} + +libkls_ljpeg_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DCODEC_LJPEG -DLJPEG2PPM_S=\"${bindir}/ksquirrel-libs-ljpeg2ppm-s\" -DLJPEG2PPM=\"${bindir}/ksquirrel-libs-ljpeg2ppm\" + +EXTRA_DIST = ksquirrel-libs-ljpeg2ppm-s.in diff --git a/kernel/kls_ljpeg/fmt_codec_pnm.cpp b/kernel/kls_ljpeg/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_ljpeg/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_ljpeg/fmt_codec_pnm_defs.h b/kernel/kls_ljpeg/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_ljpeg/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_ljpeg/ksquirrel-libs-ljpeg2ppm-s.in b/kernel/kls_ljpeg/ksquirrel-libs-ljpeg2ppm-s.in new file mode 100644 index 0000000..74c3038 --- /dev/null +++ b/kernel/kls_ljpeg/ksquirrel-libs-ljpeg2ppm-s.in @@ -0,0 +1,18 @@ +#!/bin/sh + +kls_ljpeg_i="" +kls_ljpeg_o="" +kls_ljpeg_bin="" + +while [ "$1" ] ; do + + case "$1" in + "--input") kls_ljpeg_i="$2" shift ;; + "--output") kls_ljpeg_o="$2" shift ;; + "--binary") kls_ljpeg_bin="$2" shift ;; + esac + +shift +done + +$kls_ljpeg_bin "$kls_ljpeg_i" > "$kls_ljpeg_o" \ No newline at end of file diff --git a/kernel/kls_ljpeg/ljpeg2ppm/Copyright b/kernel/kls_ljpeg/ljpeg2ppm/Copyright new file mode 100644 index 0000000..5fae625 --- /dev/null +++ b/kernel/kls_ljpeg/ljpeg2ppm/Copyright @@ -0,0 +1,79 @@ +Copyright (c) 1993 Cornell University, Kongji Huang +All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for research purposes, without fee, and without written +agreement is hereby granted, provided that the above copyright notice +and the following two paragraphs appear in all copies of this +software. + +IN NO EVENT SHALL THE CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE +UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +THE CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE +PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF +CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, +ENHANCEMENTS, OR MODIFICATIONS. + +--------------------------------------------------------------------------- + +Copyright (c) 1993 The Regents of the University of California, Brian +C. Smith All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose, without fee, and without written +agreement is hereby granted, provided that the above copyright notice +and the following two paragraphs appear in all copies of this +software. + +IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF +THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE +PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF +CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, +ENHANCEMENTS, OR MODIFICATIONS. + +--------------------------------------------------------------------------- +IJG Copyright + +The authors make NO WARRANTY or representation, either express or +implied, with respect to this software, its quality, accuracy, +merchantability, or fitness for a particular purpose. This software is +provided "AS IS", and you, its user, assume the entire risk as to its +quality and accuracy. + +This software is copyright (C) 1991, 1992, Thomas G. Lane. All Rights +Reserved except as specified below. + +Permission is hereby granted to use, copy, modify, and distribute this +software (or portions thereof) for any purpose, without fee, subject to +these conditions: (1) If any part of the source code for this software +is distributed, then this README file must be included, with this +copyright and no-warranty notice unaltered; and any additions, +deletions, or changes to the original files must be clearly indicated +in accompanying documentation. (2) If only executable code is +distributed, then the accompanying documentation must state that "this +software is based in part on the work of the Independent JPEG Group". +(3) Permission for use of this software is granted only if the user +accepts full responsibility for any undesirable consequences; the +authors accept NO LIABILITY for damages of any kind. + +Permission is NOT granted for the use of any IJG author's name or +company name in advertising or publicity relating to this software or +products derived from it. This software may be referred to only as +"the Independent JPEG Group's software". + +We specifically permit and encourage the use of this software as the +basis of commercial products, provided that all warranty or liability +claims are assumed by the product vendor. diff --git a/kernel/kls_ljpeg/ljpeg2ppm/Makefile.am b/kernel/kls_ljpeg/ljpeg2ppm/Makefile.am new file mode 100644 index 0000000..8d9632e --- /dev/null +++ b/kernel/kls_ljpeg/ljpeg2ppm/Makefile.am @@ -0,0 +1,5 @@ +#INCLUDES = -I../include + +bin_PROGRAMS = ksquirrel-libs-ljpeg2ppm + +ksquirrel_libs_ljpeg2ppm_SOURCES = huffd.c io.h jpeg.h ljpgtopnm.c mcu.c mcu.h predictor.c predictor.h proto.h read.c util.c diff --git a/kernel/kls_ljpeg/ljpeg2ppm/huffd.c b/kernel/kls_ljpeg/ljpeg2ppm/huffd.c new file mode 100644 index 0000000..da5d2e9 --- /dev/null +++ b/kernel/kls_ljpeg/ljpeg2ppm/huffd.c @@ -0,0 +1,665 @@ +/* + * huffd.c -- + * + * Code for JPEG lossless decoding. Large parts are grabbed from the IJG + * software, so: + * + * Copyright (C) 1991, 1992, Thomas G. Lane. + * Part of the Independent JPEG Group's software. + * See the file Copyright for more details. + * + * Copyright (c) 1993 Brian C. Smith, The Regents of the University + * of California + * All rights reserved. + * + * Copyright (c) 1994 Kongji Huang and Brian C. Smith. + * Cornell University + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL + * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include +#include +#include +#include +#include "jpeg.h" +#include "mcu.h" +#include "io.h" +#include "proto.h" +#include "predictor.h" + +#define RST0 0xD0 /* RST0 marker code */ + +static long getBuffer; /* current bit-extraction buffer */ +static int bitsLeft; /* # of unused bits in it */ + +/* + * The following variables keep track of the input buffer + * for the JPEG data, which is read by ReadJpegData. + */ +Uchar inputBuffer[JPEG_BUF_SIZE]; /* Input buffer for JPEG data */ +int numInputBytes; /* The total number of bytes in inputBuffer */ +int maxInputBytes; /* Size of inputBuffer */ +int inputBufferOffset; /* Offset of current byte */ + +/* + * Code for extracting the next N bits from the input stream. + * (N never exceeds 15 for JPEG data.) + * This needs to go as fast as possible! + * + * We read source bytes into getBuffer and dole out bits as needed. + * If getBuffer already contains enough bits, they are fetched in-line + * by the macros get_bits() and get_bit(). When there aren't enough bits, + * FillBitBuffer is called; it will attempt to fill getBuffer to the + * "high water mark", then extract the desired number of bits. The idea, + * of course, is to minimize the function-call overhead cost of entering + * FillBitBuffer. + * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width + * of getBuffer to be used. (On machines with wider words, an even larger + * buffer could be used.) + */ + +#define BITS_PER_LONG (8*sizeof(long)) +#define MIN_GET_BITS (BITS_PER_LONG-7) /* max value for long getBuffer */ + +/* + * bmask[n] is mask for n rightmost bits + */ +static int bmask[] = {0x0000, + 0x0001, 0x0003, 0x0007, 0x000F, + 0x001F, 0x003F, 0x007F, 0x00FF, + 0x01FF, 0x03FF, 0x07FF, 0x0FFF, + 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF}; + +/* + *-------------------------------------------------------------- + * + * FillBitBuffer -- + * + * Load up the bit buffer with at least nbits + * Process any stuffed bytes at this time. + * + * Results: + * None + * + * Side effects: + * The bitwise global variables are updated. + * + *-------------------------------------------------------------- + */ +static void +FillBitBuffer (nbits) + int nbits; +{ + int c, c2; + + while (bitsLeft < MIN_GET_BITS) { + c = GetJpegChar (); + + /* + * If it's 0xFF, check and discard stuffed zero byte + */ + if (c == 0xFF) { + c2 = GetJpegChar (); + + if (c2 != 0) { + + /* + * Oops, it's actually a marker indicating end of + * compressed data. Better put it back for use later. + */ + UnGetJpegChar (c2); + UnGetJpegChar (c); + + /* + * There should be enough bits still left in the data + * segment; if so, just break out of the while loop. + */ + if (bitsLeft >= nbits) + break; + + /* + * Uh-oh. Corrupted data: stuff zeroes into the data + * stream, since this sometimes occurs when we are on the + * last show_bits(8) during decoding of the Huffman + * segment. + */ + c = 0; + } + } + /* + * OK, load c into getBuffer + */ + getBuffer = (getBuffer << 8) | c; + bitsLeft += 8; + } +} + +/* Macros to make things go at some speed! */ +/* NB: parameter to get_bits should be simple variable, not expression */ + +#define show_bits(nbits,rv) { \ + if (bitsLeft < nbits) FillBitBuffer(nbits); \ + rv = (getBuffer >> (bitsLeft-(nbits))) & bmask[nbits]; \ +} + +#define show_bits8(rv) { \ + if (bitsLeft < 8) FillBitBuffer(8); \ + rv = (getBuffer >> (bitsLeft-8)) & 0xff; \ +} + +#define flush_bits(nbits) { \ + bitsLeft -= (nbits); \ +} + +#define get_bits(nbits,rv) { \ + if (bitsLeft < nbits) FillBitBuffer(nbits); \ + rv = ((getBuffer >> (bitsLeft -= (nbits)))) & bmask[nbits]; \ +} + +#define get_bit(rv) { \ + if (!bitsLeft) FillBitBuffer(1); \ + rv = (getBuffer >> (--bitsLeft)) & 1; \ +} + +#ifdef DEBUG +/* + *-------------------------------------------------------------- + * + * PmPutRow -- + * + * Output one row of pixels stored in RowBuf. + * + * Results: + * None + * + * Side effects: + * One row of pixels are write to file pointed by outFile. + * + *-------------------------------------------------------------- + */ +static void +PmPutRow(RowBuf,numComp,numCol,Pt) + MCU *RowBuf; + int numCol,Pt; +{ + register int col,v; + + /* + * Mulitply 2^Pt before output. Pt is the point + * transform parameter. + */ + if (numComp==1) { /*pgm*/ + for (col = 0; col < numCol; col++) { + v=RowBuf[col][0]<numbits[code]) { \ + flush_bits(htbl->numbits[code]); \ + rv=htbl->value[code]; \ + } else { \ + flush_bits(8); \ + l = 8; \ + while (code > htbl->maxcode[l]) { \ + get_bit(temp); \ + code = (code << 1) | temp; \ + l++; \ + } \ + \ + /* \ + * With garbage input we may reach the sentinel value l = 17. \ + */ \ + \ + if (l > 16) { \ + fprintf (stderr, "Corrupt JPEG data: bad Huffman code"); \ + rv = 0; /* fake a zero as the safest result */ \ + } else { \ + rv = htbl->huffval[htbl->valptr[l] + \ + ((int)(code - htbl->mincode[l]))]; \ + } \ + } \ +} + +/* + *-------------------------------------------------------------- + * + * HuffExtend -- + * + * Code and table for Figure F.12: extend sign bit + * + * Results: + * The extended value. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +static int extendTest[16] = /* entry n is 2**(n-1) */ +{0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000}; + +static int extendOffset[16] = /* entry n is (-1 << n) + 1 */ +{0, ((-1) << 1) + 1, ((-1) << 2) + 1, ((-1) << 3) + 1, ((-1) << 4) + 1, + ((-1) << 5) + 1, ((-1) << 6) + 1, ((-1) << 7) + 1, ((-1) << 8) + 1, + ((-1) << 9) + 1, ((-1) << 10) + 1, ((-1) << 11) + 1, ((-1) << 12) + 1, + ((-1) << 13) + 1, ((-1) << 14) + 1, ((-1) << 15) + 1}; + +#define HuffExtend(x,s) { \ + if ((x) < extendTest[s]) { \ + (x) += extendOffset[s]; \ + } \ +} + +/* + *-------------------------------------------------------------- + * + * HuffDecoderInit -- + * + * Initialize for a Huffman-compressed scan. + * This is invoked after reading the SOS marker. + * + * Results: + * None + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +void +HuffDecoderInit (dcPtr) + DecompressInfo *dcPtr; +{ + short ci; + JpegComponentInfo *compptr; + + /* + * Initialize static variables + */ + bitsLeft = 0; + + for (ci = 0; ci < dcPtr->compsInScan; ci++) { + compptr = dcPtr->curCompInfo[ci]; + /* + * Make sure requested tables are present + */ + if (dcPtr->dcHuffTblPtrs[compptr->dcTblNo] == NULL) { + fprintf (stderr, "Error: Use of undefined Huffman table\n"); + exit (1); + } + + /* + * Compute derived values for Huffman tables. + * We may do this more than once for same table, but it's not a + * big deal + */ + FixHuffTbl (dcPtr->dcHuffTblPtrs[compptr->dcTblNo]); + } + + /* + * Initialize restart stuff + */ + dcPtr->restartInRows = (dcPtr->restartInterval)/(dcPtr->imageWidth); + dcPtr->restartRowsToGo = dcPtr->restartInRows; + dcPtr->nextRestartNum = 0; +} + +/* + *-------------------------------------------------------------- + * + * ProcessRestart -- + * + * Check for a restart marker & resynchronize decoder. + * + * Results: + * None. + * + * Side effects: + * BitStream is parsed, bit buffer is reset, etc. + * + *-------------------------------------------------------------- + */ +static void +ProcessRestart (dcPtr) + DecompressInfo *dcPtr; +{ + int c, nbytes; + short ci; + + /* + * Throw away any unused bits remaining in bit buffer + */ + nbytes = bitsLeft / 8; + bitsLeft = 0; + + /* + * Scan for next JPEG marker + */ + do { + do { /* skip any non-FF bytes */ + nbytes++; + c = GetJpegChar (); + } while (c != 0xFF); + do { /* skip any duplicate FFs */ + /* + * we don't increment nbytes here since extra FFs are legal + */ + c = GetJpegChar (); + } while (c == 0xFF); + } while (c == 0); /* repeat if it was a stuffed FF/00 */ + + if (c != (RST0 + dcPtr->nextRestartNum)) { + + /* + * Uh-oh, the restart markers have been messed up too. + * Just bail out. + */ + fprintf (stderr, "Error: Corrupt JPEG data. Exiting...\n"); + exit(-1); + } + + /* + * Update restart state + */ + dcPtr->restartRowsToGo = dcPtr->restartInRows; + dcPtr->nextRestartNum = (dcPtr->nextRestartNum + 1) & 7; +} + +/* + *-------------------------------------------------------------- + * + * DecodeFirstRow -- + * + * Decode the first raster line of samples at the start of + * the scan and at the beginning of each restart interval. + * This includes modifying the component value so the real + * value, not the difference is returned. + * + * Results: + * None. + * + * Side effects: + * Bitstream is parsed. + * + *-------------------------------------------------------------- + */ +void DecodeFirstRow(dcPtr,curRowBuf) + DecompressInfo *dcPtr; + MCU *curRowBuf; +{ + register short curComp,ci; + register int s,col,compsInScan,numCOL; + register JpegComponentInfo *compptr; + int Pr,Pt,d; + HuffmanTable *dctbl; + + Pr=dcPtr->dataPrecision; + Pt=dcPtr->Pt; + compsInScan=dcPtr->compsInScan; + numCOL=dcPtr->imageWidth; + + /* + * the start of the scan or at the beginning of restart interval. + */ + for (curComp = 0; curComp < compsInScan; curComp++) { + ci = dcPtr->MCUmembership[curComp]; + compptr = dcPtr->curCompInfo[ci]; + dctbl = dcPtr->dcHuffTblPtrs[compptr->dcTblNo]; + + /* + * Section F.2.2.1: decode the difference + */ + HuffDecode (dctbl,s); + if (s) { + get_bits(s,d); + HuffExtend(d,s); + } else { + d = 0; + } + + /* + * Add the predictor to the difference. + */ + curRowBuf[0][curComp]=d+(1<<(Pr-Pt-1)); + } + + /* + * the rest of the first row + */ + for (col=1; colMCUmembership[curComp]; + compptr = dcPtr->curCompInfo[ci]; + dctbl = dcPtr->dcHuffTblPtrs[compptr->dcTblNo]; + + /* + * Section F.2.2.1: decode the difference + */ + HuffDecode (dctbl,s); + if (s) { + get_bits(s,d); + HuffExtend(d,s); + } else { + d = 0; + } + + /* + * Add the predictor to the difference. + */ + curRowBuf[col][curComp]=d+curRowBuf[col-1][curComp]; + } + } + + if (dcPtr->restartInRows) { + (dcPtr->restartRowsToGo)--; + } +} + +/* + *-------------------------------------------------------------- + * + * DecodeImage -- + * + * Decode the input stream. This includes modifying + * the component value so the real value, not the + * difference is returned. + * + * Results: + * None. + * + * Side effects: + * Bitstream is parsed. + * + *-------------------------------------------------------------- + */ +void +DecodeImage(dcPtr) + DecompressInfo *dcPtr; +{ + register int s,d,col,row; + register short curComp, ci; + HuffmanTable *dctbl; + JpegComponentInfo *compptr; + int predictor; + int numCOL,numROW,compsInScan; + MCU *prevRowBuf,*curRowBuf; + int imagewidth,Pt,psv; + + numCOL=imagewidth=dcPtr->imageWidth; + numROW=dcPtr->imageHeight; + compsInScan=dcPtr->compsInScan; + Pt=dcPtr->Pt; + psv=dcPtr->Ss; + prevRowBuf=mcuROW2; + curRowBuf=mcuROW1; + + /* + * Decode the first row of image. Output the row and + * turn this row into a previous row for later predictor + * calculation. + */ + DecodeFirstRow(dcPtr,curRowBuf); + PmPutRow(curRowBuf,compsInScan,numCOL,Pt); + swap(MCU *,prevRowBuf,curRowBuf); + + for (row=1; rowrestartInRows) { + if (dcPtr->restartRowsToGo == 0) { + ProcessRestart (dcPtr); + + /* + * Reset predictors at restart. + */ + DecodeFirstRow(dcPtr,curRowBuf); + PmPutRow(curRowBuf,compsInScan,numCOL,Pt); + swap(MCU *,prevRowBuf,curRowBuf); + continue; + } + dcPtr->restartRowsToGo--; + } + + /* + * The upper neighbors are predictors for the first column. + */ + for (curComp = 0; curComp < compsInScan; curComp++) { + ci = dcPtr->MCUmembership[curComp]; + compptr = dcPtr->curCompInfo[ci]; + dctbl = dcPtr->dcHuffTblPtrs[compptr->dcTblNo]; + + /* + * Section F.2.2.1: decode the difference + */ + HuffDecode (dctbl,s); + if (s) { + get_bits(s,d); + HuffExtend(d,s); + } else { + d = 0; + } + + curRowBuf[0][curComp]=d+prevRowBuf[0][curComp]; + } + + /* + * For the rest of the column on this row, predictor + * calculations are base on PSV. + */ + for (col=1; colMCUmembership[curComp]; + compptr = dcPtr->curCompInfo[ci]; + dctbl = dcPtr->dcHuffTblPtrs[compptr->dcTblNo]; + + /* + * Section F.2.2.1: decode the difference + */ + HuffDecode (dctbl,s); + if (s) { + get_bits(s,d); + HuffExtend(d,s); + } else { + d = 0; + } + QuickPredict(col,curComp,curRowBuf,prevRowBuf, + psv,&predictor); + + curRowBuf[col][curComp]=d+predictor; + } + } + PmPutRow(curRowBuf,compsInScan,numCOL,Pt); + swap(MCU *,prevRowBuf,curRowBuf); + } +} diff --git a/kernel/kls_ljpeg/ljpeg2ppm/io.h b/kernel/kls_ljpeg/ljpeg2ppm/io.h new file mode 100644 index 0000000..65d9636 --- /dev/null +++ b/kernel/kls_ljpeg/ljpeg2ppm/io.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 1991, 1992, Thomas G. Lane. + * Part of the Independent JPEG Group's software. + * See the file Copyright for more details. + * + * Copyright (c) 1993 Brian C. Smith, The Regents of the University + * of California + * All rights reserved. + * + * Copyright (c) 1994 Kongji Huang and Brian C. Smith. + * Cornell University + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL + * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef _IO +#define _IO + +/* + * Size of the input and output buffer + */ +#define JPEG_BUF_SIZE 4096 + +/* + * The following variables keep track of the input and output + * buffer for the JPEG data. + */ +extern char outputBuffer[JPEG_BUF_SIZE]; /* output buffer */ +extern int numOutputBytes; /* bytes in the output buffer */ +extern Uchar inputBuffer[JPEG_BUF_SIZE]; /* Input buffer for JPEG data */ +extern int numInputBytes; /* bytes in inputBuffer */ +extern int maxInputBytes; /* Size of inputBuffer */ +extern int inputBufferOffset; /* Offset of current byte */ + +/* + * the output file pointer. + */ +extern FILE *outFile; + +/* + *-------------------------------------------------------------- + * + * EmitByte -- + * + * Write a single byte out to the output buffer, and + * flush if it's full. + * + * Results: + * None. + * + * Side effects: + * The outp[ut buffer may get flushed. + * + *-------------------------------------------------------------- + */ +#define EmitByte(val) { \ + if (numOutputBytes >= JPEG_BUF_SIZE) { \ + FlushBytes(); \ + } \ + outputBuffer[numOutputBytes++] = (char)(val); \ +} + +/* + *-------------------------------------------------------------- + * + * GetJpegChar, UnGetJpegChar -- + * + * Macros to get the next character from the input stream. + * + * Results: + * GetJpegChar returns the next character in the stream, or EOF + * UnGetJpegChar returns nothing. + * + * Side effects: + * A byte is consumed or put back into the inputBuffer. + * + *-------------------------------------------------------------- + */ +#define GetJpegChar() \ + ((inputBufferOffset < numInputBytes)? \ + inputBuffer[inputBufferOffset++]: \ + (numInputBytes = 2+ReadJpegData(inputBuffer+2,JPEG_BUF_SIZE-2), \ + inputBufferOffset = 2, \ + ((inputBufferOffset < numInputBytes)? \ + inputBuffer[inputBufferOffset++]: \ + EOF))) + +#define UnGetJpegChar(ch) (inputBuffer[--inputBufferOffset]=(ch)) + +#endif /* _IO */ diff --git a/kernel/kls_ljpeg/ljpeg2ppm/jpeg.h b/kernel/kls_ljpeg/ljpeg2ppm/jpeg.h new file mode 100644 index 0000000..44a41cb --- /dev/null +++ b/kernel/kls_ljpeg/ljpeg2ppm/jpeg.h @@ -0,0 +1,249 @@ +/* + * jpeg.h -- + * + * Basic jpeg data structure definitions. + * + * + * Copyright (C) 1991, 1992, Thomas G. Lane. + * Part of the Independent JPEG Group's software. + * See the file Copyright for more details. + * + * Copyright (c) 1993 Brian C. Smith, The Regents of the University + * of California + * All rights reserved. + * + * Copyright (c) 1994 Kongji Huang and Brian C. Smith. + * Cornell University + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL + * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef _JPEG +#define _JPEG + +typedef unsigned char Uchar; +typedef unsigned short Ushort; +typedef unsigned int Uint; + +/* + * The following structure stores basic information about one component. + */ +typedef struct JpegComponentInfo { + /* + * These values are fixed over the whole image. + * They are read from the SOF marker. + */ + short componentId; /* identifier for this component (0..255) */ + short componentIndex; /* its index in SOF or cPtr->compInfo[] */ + + /* + * Downsampling is not normally used in lossless JPEG, although + * it is permitted by the JPEG standard (DIS). We set all sampling + * factors to 1 in this program. + */ + short hSampFactor; /* horizontal sampling factor */ + short vSampFactor; /* vertical sampling factor */ + + /* + * Huffman table selector (0..3). The value may vary + * between scans. It is read from the SOS marker. + */ + short dcTblNo; +} JpegComponentInfo; + + +/* + * One of the following structures is created for each huffman coding + * table. We use the same structure for encoding and decoding, so there + * may be some extra fields for encoding that aren't used in the decoding + * and vice-versa. + */ +typedef struct HuffmanTable { + /* + * These two fields directly represent the contents of a JPEG DHT + * marker + */ + Uchar bits[17]; + Uchar huffval[256]; + + /* + * This field is used only during compression. It's initialized + * FALSE when the table is created, and set TRUE when it's been + * output to the file. + */ + int sentTable; + + /* + * The remaining fields are computed from the above to allow more + * efficient coding and decoding. These fields should be considered + * private to the Huffman compression & decompression modules. + */ + Ushort ehufco[256]; + char ehufsi[256]; + + Ushort mincode[17]; + int maxcode[18]; + short valptr[17]; + int numbits[256]; + int value[256]; +} HuffmanTable; + +/* + * One of the following structures is used to pass around the + * compression information. + */ +typedef struct CompressInfo { + /* + * Image width, height, and image data precision (bits/sample) + */ + int imageWidth; + int imageHeight; + int dataPrecision; + + /* + * compInfo[i] describes component that appears i'th in SOF + * numComponents is the # of color components in JPEG image. + */ + JpegComponentInfo *compInfo; + short numComponents; + + /* + * *curCompInfo[i] describes component that appears i'th in SOS. + * compsInScan is the # of color components in current scan. + */ + JpegComponentInfo *curCompInfo[4]; + short compsInScan; + + /* + * MCUmembership[i] indexes the i'th component of MCU into the + * curCompInfo array. + */ + short MCUmembership[10]; + + /* + * Pointers to Huffman coding tables, or NULL if not defined. + */ + HuffmanTable *dcHuffTblPtrs[4]; + + /* + * prediction seletion value (PSV) and point transform parameter (Pt) + */ + int Ss; + int Pt; + + /* + * In lossless JPEG, restart interval shall be an integer + * multiple of the number of MCU in a MCU row. + */ + int restartInRows; /*if > 0, MCU rows per restart interval; 0 = no restart*/ + + /* + * These fields are private data for the entropy encoder + */ + int restartRowsToGo; /* MCUs rows left in this restart interval */ + short nextRestartNum; /* # of next RSTn marker (0..7) */ +} CompressInfo; + +/* + * One of the following structures is used to pass around the + * decompression information. + */ +typedef struct DecompressInfo { + /* + * Image width, height, and image data precision (bits/sample) + * These fields are set by ReadFileHeader or ReadScanHeader + */ + int imageWidth; + int imageHeight; + int dataPrecision; + + /* + * compInfo[i] describes component that appears i'th in SOF + * numComponents is the # of color components in JPEG image. + */ + JpegComponentInfo *compInfo; + short numComponents; + + /* + * *curCompInfo[i] describes component that appears i'th in SOS. + * compsInScan is the # of color components in current scan. + */ + JpegComponentInfo *curCompInfo[4]; + short compsInScan; + + /* + * MCUmembership[i] indexes the i'th component of MCU into the + * curCompInfo array. + */ + short MCUmembership[10]; + + /* + * ptrs to Huffman coding tables, or NULL if not defined + */ + HuffmanTable *dcHuffTblPtrs[4]; + + /* + * prediction seletion value (PSV) and point transform parameter (Pt) + */ + int Ss; + int Pt; + + /* + * In lossless JPEG, restart interval shall be an integer + * multiple of the number of MCU in a MCU row. + */ + int restartInterval;/* MCUs per restart interval, 0 = no restart */ + int restartInRows; /*if > 0, MCU rows per restart interval; 0 = no restart*/ + + /* + * these fields are private data for the entropy decoder + */ + int restartRowsToGo; /* MCUs rows left in this restart interval */ + short nextRestartNum; /* # of next RSTn marker (0..7) */ +} DecompressInfo; + +/* + *-------------------------------------------------------------- + * + * swap -- + * + * Swap the contents stored in a and b. + * "type" is the variable type of a and b. + * + * Results: + * The values in a and b are swapped. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +#define swap(type,a,b) {type c; c=(a); (a)=(b); (b)=c;} + +#define MEMSET(s,c,n) memset((void *)(s),(int)(c),(int)(n)) +#define MEMCPY(s1,s2,n) memcpy((void *)(s1),(void *)(s2),(int)(n)) + +/* + * Lossless JPEG specifies data precision to be from 2 to 16 bits/sample. + */ +#define MinPrecisionBits 2 +#define MaxPrecisionBits 16 +#define MinPrecisionValue 2 +#define MaxPrecisionValue 65535 + +#endif /* _JPEG */ diff --git a/kernel/kls_ljpeg/ljpeg2ppm/ljpgtopnm.c b/kernel/kls_ljpeg/ljpeg2ppm/ljpgtopnm.c new file mode 100644 index 0000000..c975892 --- /dev/null +++ b/kernel/kls_ljpeg/ljpeg2ppm/ljpgtopnm.c @@ -0,0 +1,263 @@ +/* + * ljpgtopnm.c -- + * + * This is the main routine for the lossless JPEG decoder. Large + * parts are stolen from the IJG code, so: + * + * Copyright (C) 1991, 1992, Thomas G. Lane. + * Part of the Independent JPEG Group's software. + * See the file Copyright for more details. + * + * Copyright (c) 1993 Brian C. Smith, The Regents of the University + * of California + * All rights reserved. + * + * Copyright (c) 1994 Kongji Huang and Brian C. Smith. + * Cornell University + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL + * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include +#include +#include +#include +#include "jpeg.h" +#include "mcu.h" +#include "proto.h" + +/* + * input and output file pointers + */ +FILE *inFile, *outFile; +void FreeArray2D(char **); + +void WritePmHeader(DecompressInfo dcInfo); + +/* + *-------------------------------------------------------------- + * + * ReadJpegData -- + * + * This is an interface routine to the JPEG library. The + * JPEG library calls this routine to "get more data" + * + * Results: + * Number of bytes actually returned. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +int +ReadJpegData (buffer, numBytes) + char *buffer; /* Place to put new data */ + int numBytes; /* Number of bytes to put */ +{ + return fread(buffer, 1, numBytes, inFile); +} + +/* + *-------------------------------------------------------------- + * + * WritePmHeader -- + * + * Output Portable Pixmap (PPM) or Portable + * Graymap (PGM) image header. + * + * Results: + * None. + * + * Side effects: + * The PPM or PGM header is written to file + * pointed by outFile. + * + *-------------------------------------------------------------- + */ +void +WritePmHeader(dcInfo) +DecompressInfo dcInfo; +{ + switch(dcInfo.numComponents) { + case 1: /* pgm */ + if (dcInfo.dataPrecision==8) { + fprintf(outFile,"P5\n%d %d\n255\n", + dcInfo.imageWidth,dcInfo.imageHeight); + } else { + fprintf(outFile,"P5\n%d %d\n%d\n", + dcInfo.imageWidth,dcInfo.imageHeight, + ((1<1) { + fprintf(stderr,"%s\n",usage); + exit(-1); + } + NumOfFile++; + } + else { /* precess a option */ + arg++; + switch (*arg) { + case 'h': + /* help flag */ + fprintf(stderr,"Decode a lossless JPEG image into "); + fprintf(stderr,"a PPM or PGM image.\n"); + fprintf(stderr,"Usage:\n"); + fprintf(stderr,"%s\n",usage); + fprintf(stderr,"Default input: stdin\n"); + fprintf(stderr,"Default output: stdout\n"); + fprintf(stderr,"-h help\n"); + fprintf(stderr,"-v verbose\n"); + exit(1); + break; + case 'v': + /* verbose flag */ + *verbose=1; + break; + default: + fprintf(stderr,"%s\n",usage); + exit(-1); + } + } + } +} + +int +main(argc, argv) + int argc; + char **argv; +{ + DecompressInfo dcInfo; + int verbose; + + /* + * Process command line parameters. + */ + MEMSET(&dcInfo, 0, sizeof(dcInfo)); + ArgParser(argc,argv,&verbose,&inFile,&outFile); + + /* + * Read the JPEG File header, up to scan header, and initialize all + * the variables in the decompression information structure. + */ + ReadFileHeader (&dcInfo); + + /* + * Loop through each scan in image. ReadScanHeader returns + * 0 once it consumes and EOI marker. + */ + if (!ReadScanHeader (&dcInfo)) { + fprintf (stderr, "Empty JPEG file\n"); + exit (1); + } + + /* + * Output image parameter if verbose flag is on. + */ + if (verbose) { + fprintf(stderr,"sample precision=%d\n",dcInfo.dataPrecision); + fprintf(stderr,"image height=%d\n",dcInfo.imageHeight); + fprintf(stderr,"image width=%d\n",dcInfo.imageWidth); + fprintf(stderr,"component=%d\n",dcInfo.numComponents); + } + + /* + * Write PPM or PGM image header. Decode the image bits + * stream. Clean up everything when finished decoding. + */ + WritePmHeader(dcInfo); + DecoderStructInit(&dcInfo); + HuffDecoderInit(&dcInfo); + DecodeImage(&dcInfo); + FreeArray2D(mcuROW1); + FreeArray2D(mcuROW2); + + if (ReadScanHeader (&dcInfo)) { + fprintf (stderr, "Warning: multiple scans detected in JPEG file\n"); + fprintf (stderr, " not currently supported\n"); + fprintf (stderr, " ignoring extra scans\n"); + } + + return 0; +} diff --git a/kernel/kls_ljpeg/ljpeg2ppm/mcu.c b/kernel/kls_ljpeg/ljpeg2ppm/mcu.c new file mode 100644 index 0000000..bb1f0b3 --- /dev/null +++ b/kernel/kls_ljpeg/ljpeg2ppm/mcu.c @@ -0,0 +1,125 @@ +/* + * mcu.c -- + * + * Support for MCU allocation, deallocation, and printing. + * + * Copyright (c) 1993 Brian C. Smith, The Regents of the University + * of California + * All rights reserved. + * + * Copyright (c) 1994 Kongji Huang and Brian C. Smith. + * Cornell University + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL + * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include +#include +#include +#include +#include "jpeg.h" +#include "mcu.h" +#include "proto.h" + +MCU *mcuTable; /* the global mcu table that buffers the source image */ +MCU *mcuROW1, *mcuROW2; /* point to two rows of MCU in encoding & decoding */ +int numMCU; /* number of MCUs in mcuTable */ +/* + *-------------------------------------------------------------- + * + * MakeMCU, InitMcuTable -- + * + * InitMcuTable does a big malloc to get the amount of memory + * we'll need for storing MCU's, once we know the size of our + * input and output images. + * MakeMCU returns an MCU for input parsing. + * + * Results: + * A new MCU + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +void +InitMcuTable(lnumMCU,compsInScan) + int lnumMCU; + int compsInScan; +{ + int i, mcuSize; + char *buffer; + + /* + * Compute size of on MCU (in bytes). Round up so it's on a + * boundary for any alignment. In this code, we assume this + * is a whole multiple of sizeof(double). + */ + mcuSize = compsInScan * sizeof(ComponentType); + mcuSize = JroundUp(mcuSize,sizeof(double)); + + /* + * Allocate the MCU table, and a buffer which will contain all + * the data. Then carve up the buffer by hand. Note that + * mcuTable[0] points to the buffer, in case we want to free + * it up later. + */ + mcuTable = (MCU *)malloc(lnumMCU * sizeof(MCU)); + if (mcuTable==NULL) + fprintf(stderr,"Not enough memory for mcuTable\n"); + buffer = (char *)malloc(lnumMCU * mcuSize); + if (buffer==NULL) + fprintf(stderr,"Not enough memory for buffer\n"); + for (i=0; i +#include "mcu.h" + +#ifdef DEBUG +/* + *-------------------------------------------------------------- + * + * Predict -- + * + * Calculate the predictor for pixel[row][col][curComp], + * i.e. curRowBuf[col][curComp]. It handles the all special + * cases at image edges, such as first row and first column + * of a scan. + * + * Results: + * predictor is passed out. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +void +Predict(row,col,curComp,curRowBuf,prevRowBuf,Pr,Pt,psv,predictor) + int row,col; /* position of the pixel to be predicted */ + int curComp; /* the pixel's component that is predicting */ + MCU *curRowBuf,*prevRowBuf; /* current and previous row of image */ + int Pr; /* data precision */ + int Pt; /* point transformation */ + int psv; /* predictor selection value */ + int *predictor; /* preditor value (output) */ +{ + register int left,upper,diag,leftcol; + + leftcol=col-1; + if (row==0) { + + /* + * The predictor of first pixel is (1<<(Pr-Pt-1), and the + * predictors for rest of first row are left neighbors. + */ + if (col==0) { + *predictor = (1<<(Pr-Pt-1)); + } + else { + *predictor = curRowBuf[leftcol][curComp]; + } + } + else { + + /* + * The predictors of first column are upper neighbors. + * All other preditors are calculated according to psv. + */ + upper=prevRowBuf[col][curComp]; + if (col==0) + *predictor = upper; + else { + left=curRowBuf[leftcol][curComp]; + diag=prevRowBuf[leftcol][curComp]; + switch (psv) { + case 0: + *predictor = 0; + break; + case 1: + *predictor = left; + break; + case 2: + *predictor = upper; + break; + case 3: + *predictor = diag; + break; + case 4: + *predictor = left+upper-diag; + break; + case 5: + *predictor = left+((upper-diag)>>1); + break; + case 6: + *predictor = upper+((left-diag)>>1); + break; + case 7: + *predictor = (left+upper)>>1; + break; + default: + fprintf(stderr,"Warning: Undefined PSV\n"); + *predictor = 0; + } + } + } +} + +/* + *-------------------------------------------------------------- + * + * QuickPredict -- + * + * Calculate the predictor for sample curRowBuf[col][curComp]. + * It does not handle the special cases at image edges, such + * as first row and first column of a scan. We put the special + * case checkings outside so that the computations in main + * loop can be simpler. This has enhenced the performance + * significantly. + * + * Results: + * predictor is passed out. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +void +QuickPredict(col,curComp,curRowBuf,prevRowBuf,psv,predictor) + int col; /* column # of the pixel to be predicted */ + int curComp; /* the pixel's component that is predicting */ + MCU *curRowBuf,*prevRowBuf; /* current and previous row of image */ + int psv; /* predictor selection value */ + int *predictor; /* preditor value (output) */ +{ + register int left,upper,diag,leftcol; + + leftcol=col-1; + upper=prevRowBuf[col][curComp]; + left=curRowBuf[leftcol][curComp]; + diag=prevRowBuf[leftcol][curComp]; + + /* + * All predictor are calculated according to psv. + */ + switch (psv) { + case 0: + *predictor = 0; + break; + case 1: + *predictor = left; + break; + case 2: + *predictor = upper; + break; + case 3: + *predictor = diag; + break; + case 4: + *predictor = left+upper-diag; + break; + case 5: + *predictor = left+((upper-diag)>>1); + break; + case 6: + *predictor = upper+((left-diag)>>1); + break; + case 7: + *predictor = (left+upper)>>1; + break; + default: + fprintf(stderr,"Warning: Undefined PSV\n"); + *predictor = 0; + } +} +#endif /*DEBUG*/ diff --git a/kernel/kls_ljpeg/ljpeg2ppm/predictor.h b/kernel/kls_ljpeg/ljpeg2ppm/predictor.h new file mode 100644 index 0000000..a27b34e --- /dev/null +++ b/kernel/kls_ljpeg/ljpeg2ppm/predictor.h @@ -0,0 +1,176 @@ +/* + * predictor.h -- + * + * Code for predictor calculation. Its function version, predictor.c, + * is used in debugging compilation. + * + * Copyright (c) 1994 Kongji Huang and Brian C. Smith. + * Cornell University + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL + * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef _PREDICTOR +#define _PREDICTOR + +#ifndef DEBUG + +/* + *-------------------------------------------------------------- + * + * Predict -- + * + * Calculate the predictor for pixel[row][col][curComp], + * i.e. curRowBuf[col][curComp]. It handles the all special + * cases at image edges, such as first row and first column + * of a scan. + * + * Results: + * predictor is passed out. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +#define Predict(row,col,curComp,curRowBuf,prevRowBuf,Pr,Pt,psv,predictor)\ +{ register int left,upper,diag,leftcol; \ + \ + leftcol=col-1; \ + if (row==0) { \ + \ + /* \ + * The predictor of first pixel is (1<<(Pr-Pt-1), and the \ + * predictors for rest of first row are left neighbors. \ + */ \ + if (col==0) { \ + *predictor = (1<<(Pr-Pt-1)); \ + } \ + else { \ + *predictor = curRowBuf[leftcol][curComp]; \ + } \ + } \ + else { \ + \ + /* \ + * The predictors of first column are upper neighbors. \ + * All other preditors are calculated according to psv. \ + */ \ + upper=prevRowBuf[col][curComp]; \ + if (col==0) \ + *predictor = upper; \ + else { \ + left=curRowBuf[leftcol][curComp]; \ + diag=prevRowBuf[leftcol][curComp]; \ + switch (psv) { \ + case 0: \ + *predictor = 0; \ + break; \ + case 1: \ + *predictor = left; \ + break; \ + case 2: \ + *predictor = upper; \ + break; \ + case 3: \ + *predictor = diag; \ + break; \ + case 4: \ + *predictor = left+upper-diag; \ + break; \ + case 5: \ + *predictor = left+((upper-diag)>>1); \ + break; \ + case 6: \ + *predictor = upper+((left-diag)>>1); \ + break; \ + case 7: \ + *predictor = (left+upper)>>1; \ + break; \ + default: \ + fprintf(stderr,"Warning: Undefined PSV\n"); \ + *predictor = 0; \ + } \ + } \ + } \ +} + +/* + *-------------------------------------------------------------- + * + * QuickPredict -- + * + * Calculate the predictor for sample curRowBuf[col][curComp]. + * It does not handle the special cases at image edges, such + * as first row and first column of a scan. We put the special + * case checkings outside so that the computations in main + * loop can be simpler. This has enhenced the performance + * significantly. + * + * Results: + * predictor is passed out. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +#define QuickPredict(col,curComp,curRowBuf,prevRowBuf,psv,predictor){ \ + register int left,upper,diag,leftcol; \ + \ + leftcol=col-1; \ + upper=prevRowBuf[col][curComp]; \ + left=curRowBuf[leftcol][curComp]; \ + diag=prevRowBuf[leftcol][curComp]; \ + \ + /* \ + * All predictor are calculated according to psv. \ + */ \ + switch (psv) { \ + case 0: \ + *predictor = 0; \ + break; \ + case 1: \ + *predictor = left; \ + break; \ + case 2: \ + *predictor = upper; \ + break; \ + case 3: \ + *predictor = diag; \ + break; \ + case 4: \ + *predictor = left+upper-diag; \ + break; \ + case 5: \ + *predictor = left+((upper-diag)>>1); \ + break; \ + case 6: \ + *predictor = upper+((left-diag)>>1); \ + break; \ + case 7: \ + *predictor = (left+upper)>>1; \ + break; \ + default: \ + fprintf(stderr,"Warning: Undefined PSV\n"); \ + *predictor = 0; \ + } \ +} + +#endif /* DEBUG */ +#endif /* _PREDICTOR */ diff --git a/kernel/kls_ljpeg/ljpeg2ppm/proto.h b/kernel/kls_ljpeg/ljpeg2ppm/proto.h new file mode 100644 index 0000000..1188bae --- /dev/null +++ b/kernel/kls_ljpeg/ljpeg2ppm/proto.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 1991, 1992, Thomas G. Lane. + * Part of the Independent JPEG Group's software. + * See the file Copyright for more details. + * + * Copyright (c) 1993 Brian C. Smith, The Regents of the University + * of California + * All rights reserved. + * + * Copyright (c) 1994 Kongji Huang and Brian C. Smith. + * Cornell University + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL + * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef _PROTO +#define _PROTO + +#ifdef __STDC__ +# define P(s) s +#else +# define P(s) () +#endif + + +/* huffc.c */ +void FlushBytes P((void )); +void HuffEncoderInit P((CompressInfo *cPtr )); +void HuffEncode P((CompressInfo *cPtr)); +void HuffEncoderTerm P((void )); + +/* huffd.c */ +void HuffDecoderInit P((DecompressInfo *dcPtr )); +void DecodeImage P((DecompressInfo *dcPtr )); + +/* pnmtoljpg.c ljpgtopnm.c */ +int ReadJpegData P((char *buffer , int numBytes )); +int WriteJpegData P((char *buffer , int numBytes)); +int main P((int argc , char **argv )); + +/* read.c */ +void ReadFileHeader P((DecompressInfo *dcPtr )); +int ReadScanHeader P((DecompressInfo *dcPtr )); + +/* write.c */ +void WriteFileTrailer P((CompressInfo *cPtr )); +void WriteScanHeader P((CompressInfo *cPtr )); +void WriteFileHeader P((CompressInfo *cPtr )); + +/* util.c */ +int JroundUp P((int a , int b )); +void DecoderStructInit P((DecompressInfo *dcPtr )); + + /* mcu.c */ +void InitMcuTable P((int numMCU , int blocksInMCU )); +void PrintMCU P((int blocksInMCU , MCU mcu )); + +#undef P + +#endif /* _PROTO */ diff --git a/kernel/kls_ljpeg/ljpeg2ppm/read.c b/kernel/kls_ljpeg/ljpeg2ppm/read.c new file mode 100644 index 0000000..e4855fd --- /dev/null +++ b/kernel/kls_ljpeg/ljpeg2ppm/read.c @@ -0,0 +1,665 @@ +/* + * read.c -- + * + * Code for reading and processing JPEG markers. Large parts are grabbed + * from the IJG software, so: + * + * Copyright (C) 1991, 1992, Thomas G. Lane. + * Part of the Independent JPEG Group's software. + * See the file Copyright for more details. + * + * Copyright (c) 1993 Brian C. Smith, The Regents of the University + * of California + * All rights reserved. + * + * Copyright (c) 1994 Kongji Huang and Brian C. Smith. + * Cornell University + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL + * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include +#include +#include +#include +#include "jpeg.h" +#include "mcu.h" +#include "io.h" +#include "proto.h" + +/* + * Enumerate all the JPEG marker codes + */ +typedef enum { + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JpegMarker; + +/* + *-------------------------------------------------------------- + * + * Get2bytes -- + * + * Get a 2-byte unsigned integer (e.g., a marker parameter length + * field) + * + * Results: + * Next two byte of input as an integer. + * + * Side effects: + * Bitstream is parsed. + * + *-------------------------------------------------------------- + */ +static Uint +Get2bytes (dcPtr) + DecompressInfo *dcPtr; +{ + int a; + + a = GetJpegChar(); + + return (a << 8) + GetJpegChar(); +} + +/* + *-------------------------------------------------------------- + * + * SkipVariable -- + * + * Skip over an unknown or uninteresting variable-length marker + * + * Results: + * None. + * + * Side effects: + * Bitstream is parsed over marker. + * + * + *-------------------------------------------------------------- + */ +static void +SkipVariable (dcPtr) + DecompressInfo *dcPtr; +{ + int length; + + length = Get2bytes (dcPtr) - 2; + + while (length--) { + GetJpegChar(); + } +} + +/* + *-------------------------------------------------------------- + * + * GetDht -- + * + * Process a DHT marker + * + * Results: + * None + * + * Side effects: + * A huffman table is read. + * Exits on error. + * + *-------------------------------------------------------------- + */ +static void +GetDht (dcPtr) + DecompressInfo *dcPtr; +{ + int length; + Uchar bits[17]; + Uchar huffval[256]; + int i, index, count; + HuffmanTable **htblptr; + + length = Get2bytes (dcPtr) - 2; + + while (length) { + index = GetJpegChar(); + + bits[0] = 0; + count = 0; + for (i = 1; i <= 16; i++) { + bits[i] = GetJpegChar(); + count += bits[i]; + } + + if (count > 256) { + fprintf (stderr, "Bogus DHT counts"); + exit (1); + } + + for (i = 0; i < count; i++) + huffval[i] = GetJpegChar(); + + length -= 1 + 16 + count; + + if (index & 0x10) { /* AC table definition */ + fprintf(stderr,"Huffman table for lossless JPEG is not defined.\n"); + } else { /* DC table definition */ + htblptr = &dcPtr->dcHuffTblPtrs[index]; + } + + if (index < 0 || index >= 4) { + fprintf (stderr, "Bogus DHT index %d", index); + exit (1); + } + + if (*htblptr == NULL) { + *htblptr = (HuffmanTable *) malloc (sizeof (HuffmanTable)); + if (*htblptr==NULL) { + fprintf(stderr,"Can't malloc HuffmanTable\n"); + exit(-1); + } + } + + MEMCPY((*htblptr)->bits, bits, sizeof ((*htblptr)->bits)); + MEMCPY((*htblptr)->huffval, huffval, sizeof ((*htblptr)->huffval)); + } +} + +/* + *-------------------------------------------------------------- + * + * GetDri -- + * + * Process a DRI marker + * + * Results: + * None + * + * Side effects: + * Exits on error. + * Bitstream is parsed. + * + *-------------------------------------------------------------- + */ +static void +GetDri (dcPtr) + DecompressInfo *dcPtr; +{ + if (Get2bytes (dcPtr) != 4) { + fprintf (stderr, "Bogus length in DRI"); + exit (1); + } + + dcPtr->restartInterval = (Ushort) Get2bytes (dcPtr); +} + +/* + *-------------------------------------------------------------- + * + * GetApp0 -- + * + * Process an APP0 marker. + * + * Results: + * None + * + * Side effects: + * Bitstream is parsed + * + *-------------------------------------------------------------- + */ +static void +GetApp0 (dcPtr) + DecompressInfo *dcPtr; +{ + int length; + + length = Get2bytes (dcPtr) - 2; + while (length-- > 0) /* skip any remaining data */ + (void)GetJpegChar(); +} + +/* + *-------------------------------------------------------------- + * + * GetSof -- + * + * Process a SOFn marker + * + * Results: + * None. + * + * Side effects: + * Bitstream is parsed + * Exits on error + * dcPtr structure is filled in + * + *-------------------------------------------------------------- + */ +static void +GetSof (dcPtr, code) + DecompressInfo *dcPtr; + int code; +{ + int length; + short ci; + int c; + JpegComponentInfo *compptr; + + length = Get2bytes (dcPtr); + + dcPtr->dataPrecision = GetJpegChar(); + dcPtr->imageHeight = Get2bytes (dcPtr); + dcPtr->imageWidth = Get2bytes (dcPtr); + dcPtr->numComponents = GetJpegChar(); + + /* + * We don't support files in which the image height is initially + * specified as 0 and is later redefined by DNL. As long as we + * have to check that, might as well have a general sanity check. + */ + if ((dcPtr->imageHeight <= 0 ) || + (dcPtr->imageWidth <= 0) || + (dcPtr->numComponents <= 0)) { + fprintf (stderr, "Empty JPEG image (DNL not supported)"); + exit(1); + } + + if ((dcPtr->dataPrecisiondataPrecision>MaxPrecisionBits)) { + fprintf (stderr, "Unsupported JPEG data precision"); + exit(1); + } + + if (length != (dcPtr->numComponents * 3 + 8)) { + fprintf (stderr, "Bogus SOF length"); + exit (1); + } + + dcPtr->compInfo = (JpegComponentInfo *) malloc + (dcPtr->numComponents * sizeof (JpegComponentInfo)); + + for (ci = 0; ci < dcPtr->numComponents; ci++) { + compptr = &dcPtr->compInfo[ci]; + compptr->componentIndex = ci; + compptr->componentId = GetJpegChar(); + c = GetJpegChar(); + compptr->hSampFactor = (c >> 4) & 15; + compptr->vSampFactor = (c) & 15; + (void) GetJpegChar(); /* skip Tq */ + } +} + +/* + *-------------------------------------------------------------- + * + * GetSos -- + * + * Process a SOS marker + * + * Results: + * None. + * + * Side effects: + * Bitstream is parsed. + * Exits on error. + * + *-------------------------------------------------------------- + */ +static void +GetSos (dcPtr) + DecompressInfo *dcPtr; +{ + int length; + int i, ci, n, c, cc; + JpegComponentInfo *compptr; + + length = Get2bytes (dcPtr); + + /* + * Get the number of image components. + */ + n = GetJpegChar(); + dcPtr->compsInScan = n; + length -= 3; + + if (length != (n * 2 + 3) || n < 1 || n > 4) { + fprintf (stderr, "Bogus SOS length"); + exit (1); + } + + + for (i = 0; i < n; i++) { + cc = GetJpegChar(); + c = GetJpegChar(); + length -= 2; + + for (ci = 0; ci < dcPtr->numComponents; ci++) + if (cc == dcPtr->compInfo[ci].componentId) { + break; + } + + if (ci >= dcPtr->numComponents) { + fprintf (stderr, "Invalid component number in SOS"); + exit (1); + } + + compptr = &dcPtr->compInfo[ci]; + dcPtr->curCompInfo[i] = compptr; + compptr->dcTblNo = (c >> 4) & 15; + } + + /* + * Get the PSV, skip Se, and get the point transform parameter. + */ + dcPtr->Ss = GetJpegChar(); + (void)GetJpegChar(); + c = GetJpegChar(); + dcPtr->Pt = c & 0x0F; +} + +/* + *-------------------------------------------------------------- + * + * GetSoi -- + * + * Process an SOI marker + * + * Results: + * None. + * + * Side effects: + * Bitstream is parsed. + * Exits on error. + * + *-------------------------------------------------------------- + */ +static void +GetSoi (dcPtr) + DecompressInfo *dcPtr; +{ + + /* + * Reset all parameters that are defined to be reset by SOI + */ + dcPtr->restartInterval = 0; +} + +/* + *-------------------------------------------------------------- + * + * NextMarker -- + * + * Find the next JPEG marker Note that the output might not + * be a valid marker code but it will never be 0 or FF + * + * Results: + * The marker found. + * + * Side effects: + * Bitstream is parsed. + * + *-------------------------------------------------------------- + */ +static int +NextMarker (dcPtr) + DecompressInfo *dcPtr; +{ + int c, nbytes; + + nbytes = 0; + do { + /* + * skip any non-FF bytes + */ + do { + nbytes++; + c = GetJpegChar(); + } while (c != 0xFF); + /* + * skip any duplicate FFs without incrementing nbytes, since + * extra FFs are legal + */ + do { + c = GetJpegChar(); + } while (c == 0xFF); + } while (c == 0); /* repeat if it was a stuffed FF/00 */ + + return c; +} + +/* + *-------------------------------------------------------------- + * + * ProcessTables -- + * + * Scan and process JPEG markers that can appear in any order + * Return when an SOI, EOI, SOFn, or SOS is found + * + * Results: + * The marker found. + * + * Side effects: + * Bitstream is parsed. + * + *-------------------------------------------------------------- + */ +static JpegMarker +ProcessTables (dcPtr) + DecompressInfo *dcPtr; +{ + int c; + + while (1) { + c = NextMarker (dcPtr); + + switch (c) { + case M_SOF0: + case M_SOF1: + case M_SOF2: + case M_SOF3: + case M_SOF5: + case M_SOF6: + case M_SOF7: + case M_JPG: + case M_SOF9: + case M_SOF10: + case M_SOF11: + case M_SOF13: + case M_SOF14: + case M_SOF15: + case M_SOI: + case M_EOI: + case M_SOS: + return ((JpegMarker)c); + + case M_DHT: + GetDht (dcPtr); + break; + + case M_DQT: + fprintf(stderr,"Not a lossless JPEG file.\n"); + break; + + case M_DRI: + GetDri (dcPtr); + break; + + case M_APP0: + GetApp0 (dcPtr); + break; + + case M_RST0: /* these are all parameterless */ + case M_RST1: + case M_RST2: + case M_RST3: + case M_RST4: + case M_RST5: + case M_RST6: + case M_RST7: + case M_TEM: + fprintf (stderr, "Warning: unexpected marker 0x%02x", c); + break; + + default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, + * or RESn */ + SkipVariable (dcPtr); + break; + } + } +} + +/* + *-------------------------------------------------------------- + * + * ReadFileHeader -- + * + * Initialize and read the file header (everything through + * the SOF marker). + * + * Results: + * None + * + * Side effects: + * Exit on error. + * + *-------------------------------------------------------------- + */ +void +ReadFileHeader (dcPtr) + DecompressInfo *dcPtr; +{ + int c, c2; + + /* + * Demand an SOI marker at the start of the file --- otherwise it's + * probably not a JPEG file at all. + */ + c = GetJpegChar(); + c2 = GetJpegChar(); + if ((c != 0xFF) || (c2 != M_SOI)) { + fprintf (stderr, "Not a JPEG file\n"); + exit (1); + } + + GetSoi (dcPtr); /* OK, process SOI */ + + /* + * Process markers until SOF + */ + c = ProcessTables (dcPtr); + + switch (c) { + case M_SOF0: + case M_SOF1: + case M_SOF3: + GetSof (dcPtr, c); + break; + + default: + fprintf (stderr, "Unsupported SOF marker type 0x%02x", c); + break; + } +} + +/* + *-------------------------------------------------------------- + * + * ReadScanHeader -- + * + * Read the start of a scan (everything through the SOS marker). + * + * Results: + * 1 if find SOS, 0 if find EOI + * + * Side effects: + * Bitstream is parsed, may exit on errors. + * + *-------------------------------------------------------------- + */ +int +ReadScanHeader (dcPtr) + DecompressInfo *dcPtr; +{ + int c; + + /* + * Process markers until SOS or EOI + */ + c = ProcessTables (dcPtr); + + switch (c) { + case M_SOS: + GetSos (dcPtr); + return 1; + + case M_EOI: + return 0; + + default: + fprintf (stderr, "Unexpected marker 0x%02x", c); + break; + } + return 0; +} diff --git a/kernel/kls_ljpeg/ljpeg2ppm/util.c b/kernel/kls_ljpeg/ljpeg2ppm/util.c new file mode 100644 index 0000000..d5e99cb --- /dev/null +++ b/kernel/kls_ljpeg/ljpeg2ppm/util.c @@ -0,0 +1,297 @@ +/* + * util.c -- + * + * Various utility routines used in the jpeg encoder/decoder. Large parts + * are stolen from the IJG code, so: + * + * Copyright (C) 1991, 1992, Thomas G. Lane. + * Part of the Independent JPEG Group's software. + * See the file Copyright for more details. + * + * Copyright (c) 1993 Brian C. Smith, The Regents of the University + * of California + * All rights reserved. + * + * Copyright (c) 1994 Kongji Huang and Brian C. Smith. + * Cornell University + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL + * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include +#include +#include +#include +#include "jpeg.h" +#include "mcu.h" +#include "proto.h" + +void FreeArray2D(char **); +void FixHuffTbl(HuffmanTable *); + +unsigned int bitMask[] = { 0xffffffff, 0x7fffffff, 0x3fffffff, 0x1fffffff, + 0x0fffffff, 0x07ffffff, 0x03ffffff, 0x01ffffff, + 0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff, + 0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff, + 0x0000ffff, 0x00007fff, 0x00003fff, 0x00001fff, + 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff, + 0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f, + 0x0000000f, 0x00000007, 0x00000003, 0x00000001}; +/* + *-------------------------------------------------------------- + * + * JroundUp -- + * + * Compute a rounded up to next multiple of b; a >= 0, b > 0 + * + * Results: + * Rounded up value. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +int +JroundUp (a, b) + int a, b; +{ + a += b - 1; + return a - (a % b); +} + +/* + *-------------------------------------------------------------- + * + * DecoderStructInit -- + * + * Initalize the rest of the fields in the decompression + * structure. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +void +DecoderStructInit (dcPtr) + DecompressInfo *dcPtr; + +{ + short ci,i; + JpegComponentInfo *compPtr; + char *buf1,*buf2; + int mcuSize; + + /* + * Check sampling factor validity. + */ + for (ci = 0; ci < dcPtr->numComponents; ci++) { + compPtr = &dcPtr->compInfo[ci]; + if ((compPtr->hSampFactor != 1) || (compPtr->vSampFactor != 1)) { + fprintf (stderr, "Error: Downsampling is not supported.\n"); + exit(-1); + } + } + + /* + * Prepare array describing MCU composition + */ + if (dcPtr->compsInScan == 1) { + dcPtr->MCUmembership[0] = 0; + } else { + short lci; + + if (dcPtr->compsInScan > 4) { + fprintf (stderr, "Too many components for interleaved scan"); + exit (1); + } + + for (lci = 0; lci < dcPtr->compsInScan; lci++) { + dcPtr->MCUmembership[lci] = lci; + } + } + + /* + * Initialize mucROW1 and mcuROW2 which buffer two rows of + * pixels for predictor calculation. + */ + + if ((mcuROW1 = (MCU *)malloc(dcPtr->imageWidth*sizeof(MCU)))==NULL) { + fprintf(stderr,"Not enough memory for mcuROW1\n"); + } + if ((mcuROW2 = (MCU *)malloc(dcPtr->imageWidth*sizeof(MCU)))==NULL) { + fprintf(stderr,"Not enough memory for mcuROW2\n"); + } + + mcuSize=dcPtr->compsInScan * sizeof(ComponentType); + if ((buf1 = (char *)malloc(dcPtr->imageWidth*mcuSize))==NULL) { + fprintf(stderr,"Not enough memory for buf1\n"); + } + if ((buf2 = (char *)malloc(dcPtr->imageWidth*mcuSize))==NULL) { + fprintf(stderr,"Not enough memory for buf2\n"); + } + + for (i=0;iimageWidth;i++) { + mcuROW1[i]=(MCU)(buf1+i*mcuSize); + mcuROW2[i]=(MCU)(buf2+i*mcuSize); + } +} + +/* + *-------------------------------------------------------------- + * + * FixHuffTbl -- + * + * Compute derived values for a Huffman table one the DHT marker + * has been processed. This generates both the encoding and + * decoding tables. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +void +FixHuffTbl (htbl) + HuffmanTable *htbl; +{ + int p, i, l, lastp, si; + char huffsize[257]; + Ushort huffcode[257]; + Ushort code; + int size; + int value, ll, ul; + + /* + * Figure C.1: make table of Huffman code length for each symbol + * Note that this is in code-length order. + */ + p = 0; + for (l = 1; l <= 16; l++) { + for (i = 1; i <= (int)htbl->bits[l]; i++) + huffsize[p++] = (char)l; + } + huffsize[p] = 0; + lastp = p; + + + /* + * Figure C.2: generate the codes themselves + * Note that this is in code-length order. + */ + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int)huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + code <<= 1; + si++; + } + + /* + * Figure C.3: generate encoding tables + * These are code and size indexed by symbol value + * Set any codeless symbols to have code length 0; this allows + * EmitBits to detect any attempt to emit such symbols. + */ + MEMSET(htbl->ehufsi, 0, sizeof(htbl->ehufsi)); + + for (p = 0; p < lastp; p++) { + htbl->ehufco[htbl->huffval[p]] = huffcode[p]; + htbl->ehufsi[htbl->huffval[p]] = huffsize[p]; + } + + /* + * Figure F.15: generate decoding tables + */ + p = 0; + for (l = 1; l <= 16; l++) { + if (htbl->bits[l]) { + htbl->valptr[l] = p; + htbl->mincode[l] = huffcode[p]; + p += htbl->bits[l]; + htbl->maxcode[l] = huffcode[p - 1]; + } else { + htbl->maxcode[l] = -1; + } + } + + /* + * We put in this value to ensure HuffDecode terminates. + */ + htbl->maxcode[17] = 0xFFFFFL; + + /* + * Build the numbits, value lookup tables. + * These table allow us to gather 8 bits from the bits stream, + * and immediately lookup the size and value of the huffman codes. + * If size is zero, it means that more than 8 bits are in the huffman + * code (this happens about 3-4% of the time). + */ + bzero (htbl->numbits, sizeof(htbl->numbits)); + for (p=0; phuffval[p]; + code = huffcode[p]; + ll = code << (8-size); + if (size < 8) { + ul = ll | bitMask[24+size]; + } else { + ul = ll; + } + for (i=ll; i<=ul; i++) { + htbl->numbits[i] = size; + htbl->value[i] = value; + } + } + } +} + +/* + *-------------------------------------------------------------- + * + * FreeArray2D -- + * + * Free the memory of a 2-D array pointed by arrayPtr. + * + * Results: + * None. + * + * Side effects: + * The memory pointed by arrayPtr is freed. + * + *-------------------------------------------------------------- + */ +void +FreeArray2D(arrayPtr) + char **arrayPtr; +{ + free(arrayPtr[0]); + free(arrayPtr); +} diff --git a/kernel/kls_mac/Makefile.am b/kernel/kls_mac/Makefile.am new file mode 100644 index 0000000..7dedca4 --- /dev/null +++ b/kernel/kls_mac/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I../include + +bin_SCRIPTS = ksquirrel-libs-mac2ppm + +pkglib_LTLIBRARIES = libkls_mac.la + +libkls_mac_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_mac_la_LDFLAGS = ${SQ_RELEASE} + +libkls_mac_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DCODEC_NETPBM -DCODEC_MAC -DNETPBM_S=\"${bindir}/ksquirrel-libs-mac2ppm\" + +EXTRA_DIST = ksquirrel-libs-mac2ppm.in \ No newline at end of file diff --git a/kernel/kls_mac/fmt_codec_pnm.cpp b/kernel/kls_mac/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_mac/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_mac/fmt_codec_pnm_defs.h b/kernel/kls_mac/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_mac/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_mac/ksquirrel-libs-mac2ppm.in b/kernel/kls_mac/ksquirrel-libs-mac2ppm.in new file mode 100644 index 0000000..9032a9f --- /dev/null +++ b/kernel/kls_mac/ksquirrel-libs-mac2ppm.in @@ -0,0 +1,3 @@ +#!/bin/sh + +@MACTOPBM@ "$1" > "$2" \ No newline at end of file diff --git a/kernel/kls_mdl/Makefile.am b/kernel/kls_mdl/Makefile.am new file mode 100644 index 0000000..8ac900c --- /dev/null +++ b/kernel/kls_mdl/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_mdl.la + +libkls_mdl_la_SOURCES = fmt_codec_mdl.cpp fmt_codec_mdl_defs.h + +libkls_mdl_la_LDFLAGS = ${SQ_RELEASE} + +libkls_mdl_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_mdl/fmt_codec_mdl.cpp b/kernel/kls_mdl/fmt_codec_mdl.cpp new file mode 100644 index 0000000..9a063c3 --- /dev/null +++ b/kernel/kls_mdl/fmt_codec_mdl.cpp @@ -0,0 +1,171 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_mdl_defs.h" +#include "fmt_codec_mdl.h" + +#include "ksquirrel-libs/error.h" + +#include "../xpm/codec_mdl.xpm" + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.2.0"; + o->name = "HalfLife model"; + o->filter = "*.mdl "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mdl"; + o->pixmap = codec_mdl; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + read_error = false; + + finfo.animated = false; + + s32 id, ver; + + if(!frs.readK(&id, sizeof(s32))) return SQE_R_BADFILE; + if(!frs.readK(&ver, sizeof(s32))) return SQE_R_BADFILE; + + if(id != 0x54534449 || ver != 10) + return SQE_R_BADFILE; + + frs.seekg(172, ios::cur); + + if(!frs.readK(&numtex, sizeof(s32))) return SQE_R_BADFILE; + if(!frs.readK(&texoff, sizeof(s32))) return SQE_R_BADFILE; + if(!frs.readK(&texdataoff, sizeof(s32))) return SQE_R_BADFILE; + + if(!numtex || !texoff || !texdataoff) + return SQE_R_BADFILE; + + frs.seekg(texoff, ios::beg); + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage == numtex) + return SQE_NOTOK; + + fmt_image image; + + if(currentImage) + frs.seekg(opos); + + if(!frs.readK(tex.name, sizeof(tex.name))) return SQE_R_BADFILE; + if(!frs.readK(&tex.flags, sizeof(s32))) return SQE_R_BADFILE; + if(!frs.readK(&tex.width, sizeof(s32))) return SQE_R_BADFILE; + if(!frs.readK(&tex.height, sizeof(s32))) return SQE_R_BADFILE; + if(!frs.readK(&tex.offset, sizeof(s32))) return SQE_R_BADFILE; + + opos = frs.tellg(); + + if(!tex.offset) + return SQE_R_BADFILE; + + frs.seekg(tex.offset, ios::beg); + + if(!frs.good()) + return SQE_R_BADFILE; + + image.w = tex.width; + image.h = tex.height; + + fstream::pos_type pos = frs.tellg(); + + frs.seekg(tex.width * tex.height, ios::cur); + + if(!frs.readK(pal, sizeof(RGB) * 256)) return SQE_R_BADFILE; + + frs.seekg(pos); + + image.compression = "-"; + image.colorspace = fmt_utils::colorSpaceByBpp(8); + image.bpp = 8; + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + u8 index; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + for(s32 x = 0;x < im->w;x++) + { + if(!frs.readK(&index, sizeof(u8))) return SQE_R_BADFILE; + + memcpy(scan+x, pal+index, sizeof(RGB)); + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_mdl/fmt_codec_mdl_defs.h b/kernel/kls_mdl/fmt_codec_mdl_defs.h new file mode 100644 index 0000000..5ca4a71 --- /dev/null +++ b/kernel/kls_mdl/fmt_codec_mdl_defs.h @@ -0,0 +1,35 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_mdl +#define KSQUIRREL_CODEC_DEFS_mdl + +typedef struct tagTEX_HEAD +{ + s8 name[64]; + s32 flags; + s32 width; + s32 height; + s32 offset; + +} TEX_HEAD; + +#endif diff --git a/kernel/kls_mng/Makefile.am b/kernel/kls_mng/Makefile.am new file mode 100644 index 0000000..b94cbcd --- /dev/null +++ b/kernel/kls_mng/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_mng.la + +libkls_mng_la_SOURCES = fmt_codec_mng.cpp fmt_codec_mng_defs.h + +libkls_mng_la_LDFLAGS = ${SQ_RELEASE} + +libkls_mng_la_LIBADD = ${SQ_LOCAL_RPATH} -lmng \ No newline at end of file diff --git a/kernel/kls_mng/fmt_codec_mng.cpp b/kernel/kls_mng/fmt_codec_mng.cpp new file mode 100644 index 0000000..3d72f76 --- /dev/null +++ b/kernel/kls_mng/fmt_codec_mng.cpp @@ -0,0 +1,372 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include + +#include "fmt_codec_mng_defs.h" +#include "fmt_codec_mng.h" + +#include "ksquirrel-libs/error.h" + +#include "../xpm/codec_mng.xpm" + +/* structure for keeping track of our mng stream inside the callbacks */ +struct mngstuff +{ + FILE *file; /* pointer to the file we're decoding */ + std::string filename; /* pointer to the file's path/name */ + fmt_codec *codec; +}; + +/* + * + * MNG (Multiple-image Network Graphics) is the animation extension of the popular PNG image-format. + * PNG (Portable Network Graphics) is an extensible file format for the lossless, portable, + * well-compressed storage of raster images. + * + * MNG has advanced animation features which make it very useful as a full replacement + * for GIF animations. These features allow animations that are impossible with GIF or + * result in much smaller files as GIF. + * + * As MNG builds on the same structure as PNG, it is robust, extensible and free of + * patents. It retains the same clever file integrity checks as in PNG. + * + * MNG also embraces the lossy JPEG image-format in a sub-format named JNG, which + * allows for alpha-transparency and color-correction on highly compressed (photographic) images. + * + */ + +/* ******************************************************************** */ +/* callbacks from mngplay.c (C) Ralph Giles */ +/* ******************************************************************** */ + +/* memory allocation; data must be zeroed */ +mng_ptr mymngalloc(mng_size_t size) +{ + // libmng requires calloc... + return (mng_ptr)calloc(1, size); +} + +/* memory deallocation */ +void mymngfree(mng_ptr p, mng_size_t /*size*/) +{ + free(p); +} + +mng_bool mymngopenstream(mng_handle mng) +{ + mngstuff *mymng; + + /* look up our stream struct */ + mymng = (mngstuff*)mng_get_userdata(mng); + + /* open the file */ + mymng->file = fopen(mymng->filename.c_str(), "rb"); + + if(mymng->file == NULL) + return MNG_FALSE; + + return MNG_TRUE; +} + +mng_bool mymngprocesstext(mng_handle mng, mng_uint8 /*iType*/, mng_pchar zKeyword, mng_pchar zText, + mng_pchar /*zLanguage*/, mng_pchar /*zTranslation*/) +{ + mngstuff *mymng; + + /* look up our stream struct */ + mymng = (mngstuff *)mng_get_userdata(mng); + + if(zKeyword && zText) + { + fmt_metaentry mt; + + mt.group = zKeyword; + mt.data = zText; + + mymng->codec->addmeta(mt); + } + + return MNG_TRUE; +} + +mng_bool mymngclosestream(mng_handle mng) +{ + mngstuff *mymng; + + /* look up our stream struct */ + mymng = (mngstuff *)mng_get_userdata(mng); + + /* close the file */ + fclose(mymng->file); + mymng->file = NULL;/* for safety */ + + mymng->filename.clear(); + + return MNG_TRUE; +} + +/* feed data to the decoder */ +mng_bool mymngreadstream(mng_handle mng, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread) +{ + mngstuff *mymng; + + /* look up our stream struct */ + mymng = (mngstuff *)mng_get_userdata(mng); + + /* read the requested amount of data from the file */ + *bytesread = fread(buffer, 1, size, mymng->file); + + return MNG_TRUE; +} + +/* the header's been read. set up the display stuff */ +mng_bool mymngprocessheader(mng_handle mng, mng_uint32 width, mng_uint32 height) +{ + mngstuff *mymng; + + mymng = (mngstuff *)mng_get_userdata(mng); + + mymng->codec->priv.w = width; + + mymng->codec->priv.frame = new RGBA [width * height]; + + return (!mymng->codec->priv.frame) ? MNG_FALSE : MNG_TRUE; +} + +/* return a row pointer for the decoder to fill */ +mng_ptr mymnggetcanvasline(mng_handle mng, mng_uint32 line) +{ + mngstuff *mymng; + mng_ptr row; + + mymng = (mngstuff *)mng_get_userdata(mng); + + row = mymng->codec->priv.frame + line * mymng->codec->priv.w; + + return row; +} + +/* timer */ +mng_uint32 mymnggetticks(mng_handle /*mng*/) +{ + return 0; +} + +mng_bool mymngrefresh(mng_handle /*mng*/, mng_uint32 /*x*/, mng_uint32 /*y*/, mng_uint32 /*w*/, mng_uint32 /*h*/) +{ + return MNG_TRUE; +} + +/* interframe delay callback */ +mng_bool mymngsettimer(mng_handle mng, mng_uint32 msecs) +{ + mngstuff *mymng; + + mymng = (mngstuff *)mng_get_userdata(mng); + + mymng->codec->priv.ms = (msecs == 1) ? 100 : msecs; + + return MNG_TRUE; +} + +/* ******************************************************************** */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.3.4"; + o->name = "Multiple Network Graphics"; + +#ifdef MNG_INCLUDE_JNG + o->filter = "*.mng *.jng "; + o->mimetype = "video/x-mng;image/x-jng"; +#else + o->filter = "*.mng "; + o->mimetype = "video/x-mng"; +#endif + + o->config = ""; + o->mime = ""; + o->pixmap = codec_mng; + o->readable = true; + o->canbemultiple = true; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + frs.close(); + + currentImage = -1; + read_error = false; + + finfo.animated = false; + + // allocate our stream data structure + mymng = new mngstuff; + + if(!mymng) + return SQE_R_NOMEMORY; + + mymng->filename = file; + mymng->codec = this; + priv.frame = 0; + priv.ms = 10; + + /* set up the mng decoder for our stream */ + mng = mng_initialize(mymng, mymngalloc, mymngfree, MNG_NULL); + + if (mng == MNG_NULL) + return SQE_R_NOMEMORY; + + /* set the callbacks */ + mng_setcb_openstream(mng, ::mymngopenstream); + mng_setcb_closestream(mng, ::mymngclosestream); + mng_setcb_readdata(mng, ::mymngreadstream); + mng_setcb_gettickcount(mng, ::mymnggetticks); + mng_setcb_settimer(mng, ::mymngsettimer); + mng_setcb_processheader(mng, ::mymngprocessheader); + mng_setcb_getcanvasline(mng, ::mymnggetcanvasline); + mng_setcb_refresh(mng, ::mymngrefresh); + mng_setcb_processtext(mng, ::mymngprocesstext); + mng_set_suspensionmode(mng, MNG_TRUE); + mng_set_canvasstyle(mng, MNG_CANVAS_RGBA8); + + total = 0; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if((total && currentImage == total) || (!total && currentImage)) + return SQE_NOTOK; + + int myretcode; + + if(!currentImage) + { + myretcode = mng_read(mng); + + if(myretcode != MNG_NOERROR) + return SQE_R_BADFILE; + + total = mng_get_totallayers(mng); + + if(total > 1) total--; + + myretcode = mng_display(mng); + + if(myretcode != MNG_NOERROR && myretcode != MNG_NEEDTIMERWAIT) + return SQE_R_BADFILE; + } + else + { + myretcode = mng_display_resume(mng); + + if(myretcode != MNG_NOERROR && myretcode != MNG_NEEDTIMERWAIT) + return SQE_R_BADFILE; + + finfo.animated = true; + } + + fmt_image image; + + image.w = mng_get_imagewidth(mng); + image.h = mng_get_imageheight(mng); + image.bpp = 32; + image.compression = (mng_get_imagetype(mng) == MNG_IMAGETYPE_PNG) ? "Deflate method 8, 32K window" : "JPEG"; + image.hasalpha = true; + + int cc = mng_get_colortype(mng); + + switch(cc) + { + case MNG_COLORTYPE_GRAY: image.colorspace = "Grayscale"; break; + case MNG_COLORTYPE_RGB: image.colorspace = "RGB"; break; + case MNG_COLORTYPE_INDEXED: image.colorspace = "Indexed"; break; + case MNG_COLORTYPE_GRAYA: image.colorspace = "Grayscale with alpha"; break; + case MNG_COLORTYPE_RGBA: image.colorspace = "RGBA"; break; + + default: image.colorspace = "Unknown"; + } + + image.delay = priv.ms; + + finfo.image.push_back(image); + + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + line++; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + memcpy(scan, priv.frame+im->w*line, im->w*sizeof(RGBA)); + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + finfo.meta.clear(); + finfo.image.clear(); + + mng_cleanup(&mng); + + delete [] priv.frame; + priv.frame = 0; +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_mng/fmt_codec_mng_defs.h b/kernel/kls_mng/fmt_codec_mng_defs.h new file mode 100644 index 0000000..653b8ff --- /dev/null +++ b/kernel/kls_mng/fmt_codec_mng_defs.h @@ -0,0 +1,27 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_mng +#define KSQUIRREL_CODEC_DEFS_mng + +// define constants here + +#endif diff --git a/kernel/kls_msp/Makefile.am b/kernel/kls_msp/Makefile.am new file mode 100644 index 0000000..27ce122 --- /dev/null +++ b/kernel/kls_msp/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_msp.la + +libkls_msp_la_SOURCES = fmt_codec_msp.cpp fmt_codec_msp_defs.h + +libkls_msp_la_LDFLAGS = ${SQ_RELEASE} + +libkls_msp_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_msp/fmt_codec_msp.cpp b/kernel/kls_msp/fmt_codec_msp.cpp new file mode 100644 index 0000000..30b09ca --- /dev/null +++ b/kernel/kls_msp/fmt_codec_msp.cpp @@ -0,0 +1,228 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" + +#include "fmt_codec_msp_defs.h" +#include "fmt_codec_msp.h" + +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "../xpm/codec_msp.xpm" + +static const RGB palmono[2] = { RGB(255,255,255), RGB(0,0,0) }; + +/* + * + * The Microsoft Paint (MSP) image file format is used exclusively for storing + * black-and-white images. The vast majority of MSP files contain line drawings + * and clip art. MSP is used most often by Microsoft Windows applications, but + * may be used by MS-DOS-based programs as well. The Microsoft Paint format is + * apparently being replaced by the more versatile Microsoft Windows BMP format; + * it contains information specifically for use in the Microsoft Windows operating + * environment. For information on the Windows-specific use of the header information, + * refer to the Microsoft Paint format specification available from Microsoft. + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.1.0"; + o->name = "Microsoft Paint"; + o->filter = "*.msp "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-msp"; + o->pixmap = codec_msp; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + read_error = false; + + finfo.animated = false; + bytes = NULL; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + if(!frs.readK(&msp, sizeof(msp_header))) + return SQE_R_BADFILE; + + if(msp.key1 == MAGIC_OLD_1 || msp.key2 == MAGIC_OLD_2) + version = 1; + else if(msp.key1 == MAGIC_1 || msp.key2 == MAGIC_2) + version = 2; + else + return SQE_R_BADFILE; + + bytes = new u8 [msp.width]; + + if(!bytes) + return SQE_R_NOMEMORY; + + if(version == 2) + { + u16 map_entry; + + frs.seekg(32, ios::beg); + + for(s32 i = 0;i < msp.height;i++) + { + if(!frs.readK(&map_entry, sizeof(u16))) + return SQE_R_BADFILE; + + scanmap.push_back(map_entry); + } + } + + image.w = msp.width; + image.h = msp.height; + image.bpp = 1; + image.compression = (version == 2) ? "RLE" : "-"; + image.colorspace = fmt_utils::colorSpaceByBpp(1); + + finfo.image.push_back(image); + + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + RGBA rgba; + s32 i = 0, k = 0; + u8 c, count, value; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + line++; + + const u16 sz = scanmap[line]; + + memset(bytes, 0, im->w); + + while(i < sz) + { + if(!frs.readK(&c, sizeof(u8))) + return SQE_R_BADFILE; + + i++; + + if(!c) + { + if(!frs.readK(&count, sizeof(u8))) return SQE_R_BADFILE; + if(!frs.readK(&value, sizeof(u8))) return SQE_R_BADFILE; + + i += 2; + + if(count) + { + for(s32 s = 0;s < (s32)count;s++) + bytes[k+s] = value; + + k += count; + } + } + else + { + if(!frs.readK(bytes+k, sizeof(u8) * c)) return SQE_R_BADFILE; + + i++; + k += c; + } + } + + s32 aa = 320; + for(s32 k = 0;k <= line;k++) + aa += scanmap[k]; + + s32 ind = 0; + + for(i = 0;i < sz;i++) + { + fmt_utils::expandMono1Byte(bytes[i], byte); + + for(s32 j = 0;j < 8 || ind < im->w;j++) + { + memcpy(scan+ind, palmono+byte[i], sizeof(RGB)); + ind++; + } + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); + + scanmap.clear(); + + delete [] bytes; + bytes = NULL; +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_msp/fmt_codec_msp_defs.h b/kernel/kls_msp/fmt_codec_msp_defs.h new file mode 100644 index 0000000..ded5cbe --- /dev/null +++ b/kernel/kls_msp/fmt_codec_msp_defs.h @@ -0,0 +1,49 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_msp +#define KSQUIRREL_CODEC_DEFS_msp + +#define MAGIC_OLD_1 0x6144 +#define MAGIC_OLD_2 0x4D6E +#define MAGIC_1 0x694C +#define MAGIC_2 0x536E + +struct msp_header +{ + u16 key1; /* Magic number */ + u16 key2; /* Magic number */ + u16 width; /* Width of the bitmap in pixels */ + u16 height; /* Height of the bitmap in pixels */ + u16 XARBitmap; /* X Aspect ratio of the bitmap */ + u16 YARBitmap; /* Y Aspect ratio of the bitmap */ + u16 XARPrinter; /* X Aspect ratio of the printer */ + u16 YARPrinter; /* Y Aspect ratio of the printer */ + u16 printerWidth; /* Width of the printer in pixels */ + u16 printerHeight; /* Height of the printer in pixels */ + u16 XAspectCorr; /* X aspect correction (unused) */ + u16 YAspectCorr; /* Y aspect correction (unused) */ + u16 checksum; /* Checksum of previous 24 bytes */ + u16 padding[3]; /* Unused padding */ + +}PACKED; + +#endif diff --git a/kernel/kls_mtv/Makefile.am b/kernel/kls_mtv/Makefile.am new file mode 100644 index 0000000..fe70b54 --- /dev/null +++ b/kernel/kls_mtv/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_mtv.la + +libkls_mtv_la_SOURCES = fmt_codec_mtv.cpp fmt_codec_mtv_defs.h + +libkls_mtv_la_LDFLAGS = ${SQ_RELEASE} + +libkls_mtv_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_mtv/fmt_codec_mtv.cpp b/kernel/kls_mtv/fmt_codec_mtv.cpp new file mode 100644 index 0000000..83bfbe3 --- /dev/null +++ b/kernel/kls_mtv/fmt_codec_mtv.cpp @@ -0,0 +1,196 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_mtv_defs.h" +#include "fmt_codec_mtv.h" + +#include "ksquirrel-libs/error.h" + +#include "../xpm/codec_mtv.xpm" + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.1.1"; + o->name = "MTV Ray tracer"; + o->filter = "*.mtv "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mtv"; + o->pixmap = codec_mtv; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + read_error = false; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + + if(!frs.getS(str, sizeof(str))) + return SQE_R_BADFILE; + + std::stringstream ss(str); + + ss >> image.w; + ss >> image.h; + + image.compression = "-"; + image.colorspace = fmt_utils::colorSpaceByBpp(24); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + for(s32 i = 0;i < im->w;i++) + { + if(!frs.readK(&rgb, sizeof(RGB))) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->passes = 1; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + s8 s[80]; + + snprintf(s, sizeof(s), "%d %d\n", writeimage.w, writeimage.h); + + if(!fws.writeK(s, strlen(s))) return SQE_W_ERROR; + + return SQE_OK; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("mtv"); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_mtv/fmt_codec_mtv_defs.h b/kernel/kls_mtv/fmt_codec_mtv_defs.h new file mode 100644 index 0000000..4268742 --- /dev/null +++ b/kernel/kls_mtv/fmt_codec_mtv_defs.h @@ -0,0 +1,27 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_mtv +#define KSQUIRREL_CODEC_DEFS_mtv + +// define constants here + +#endif diff --git a/kernel/kls_neo/Makefile.am b/kernel/kls_neo/Makefile.am new file mode 100644 index 0000000..ceae15b --- /dev/null +++ b/kernel/kls_neo/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I../include + +bin_SCRIPTS = ksquirrel-libs-neo2ppm + +pkglib_LTLIBRARIES = libkls_neo.la + +libkls_neo_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_neo_la_LDFLAGS = ${SQ_RELEASE} + +libkls_neo_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DCODEC_NETPBM -DCODEC_NEO -DNETPBM_S=\"${bindir}/ksquirrel-libs-neo2ppm\" + +EXTRA_DIST = ksquirrel-libs-neo2ppm.in \ No newline at end of file diff --git a/kernel/kls_neo/fmt_codec_pnm.cpp b/kernel/kls_neo/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_neo/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_neo/fmt_codec_pnm_defs.h b/kernel/kls_neo/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_neo/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_neo/ksquirrel-libs-neo2ppm.in b/kernel/kls_neo/ksquirrel-libs-neo2ppm.in new file mode 100644 index 0000000..6287b9b --- /dev/null +++ b/kernel/kls_neo/ksquirrel-libs-neo2ppm.in @@ -0,0 +1,3 @@ +#!/bin/sh + +@NEOTOPPM@ "$1" > "$2" \ No newline at end of file diff --git a/kernel/kls_openexr/Makefile.am b/kernel/kls_openexr/Makefile.am new file mode 100644 index 0000000..debce0e --- /dev/null +++ b/kernel/kls_openexr/Makefile.am @@ -0,0 +1,11 @@ +CXXFLAGS = @CXXFLAGS@ -fexceptions + +INCLUDES = -I../include @SQ_EXR_CFLAGS@ + +pkglib_LTLIBRARIES = libkls_openexr.la + +libkls_openexr_la_SOURCES = fmt_codec_openexr.cpp fmt_codec_openexr_defs.h + +libkls_openexr_la_LDFLAGS = ${SQ_RELEASE} + +libkls_openexr_la_LIBADD = @SQ_EXR_LDFLAGS@ ${SQ_LOCAL_RPATH} \ No newline at end of file diff --git a/kernel/kls_openexr/fmt_codec_openexr.cpp b/kernel/kls_openexr/fmt_codec_openexr.cpp new file mode 100644 index 0000000..58a9586 --- /dev/null +++ b/kernel/kls_openexr/fmt_codec_openexr.cpp @@ -0,0 +1,303 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fmt_codec_openexr_defs.h" +#include "fmt_codec_openexr.h" + +#include "ksquirrel-libs/error.h" + +#include "../xpm/codec_openexr.xpm" + +RGBA RgbaToRGBA(struct Rgba); + +/* + * + * A high-dynamic-range image format from Industrial Light & Magic + * for use in digital visual effects production. + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.2.1"; + o->name = "OpenEXR"; + o->filter = "*.exr "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-exr"; + o->pixmap = codec_openexr; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &fl) +{ + frs.open(fl.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + frs.close(); + + currentImage = -1; + read_error = false; + + pixels = 0; + file = fl; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s32 width, height; + + RgbaInputFile *in = NULL; + + pixels = new Array2D; + + try + { + in = new RgbaInputFile(file.c_str()); + + Imath::Box2i dw = in->dataWindow(); + + width = dw.max.x - dw.min.x + 1; + height = dw.max.y - dw.min.y + 1; + + pixels->resizeErase(height, width); + + in->setFrameBuffer(&(*pixels)[0][0] - dw.min.x - dw.min.y * width, 1, width); + + in->readPixels(dw.min.y, dw.max.y); + } + catch(const exception &e) + { + cerr << e.what() << endl; + + delete in; + + return SQE_R_BADFILE; + } + + switch(in->compression()) + { + case Imf::NO_COMPRESSION: + image.compression = "-"; + break; + + case Imf::RLE_COMPRESSION: + image.compression = "RLE"; + break; + + case Imf::ZIPS_COMPRESSION: + image.compression = "ZIPS"; + break; + + case Imf::ZIP_COMPRESSION: + image.compression = "ZIP"; + break; + + case Imf::PIZ_COMPRESSION: + image.compression = "PIZ"; + break; + + case Imf::PXR24_COMPRESSION: + image.compression = "PXR24"; + break; + + case Imf::NUM_COMPRESSION_METHODS: + image.compression = "Different methods"; + break; + + default: + image.compression = "Unknown"; + } + + image.colorspace = "RGBA"; + image.bpp = 32; + image.w = width; + image.h = height; + + finfo.image.push_back(image); + + line = -1; + + delete in; + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGBA rgba; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + line++; + + for(s32 x = 0; x < im->w; x++) + { + rgba = RgbaToRGBA((*pixels)[line][x]); + memcpy(scan+x, &rgba, sizeof(RGBA)); + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + finfo.meta.clear(); + finfo.image.clear(); + + delete pixels; + pixels = 0; +} + +/* + * This function is taken from exr plugin for KImageIO, kdelibs-3.4.0: + * + * KImageIO Routines to read (and perhaps in the future, write) images + * in the high dynamic range EXR format. + * Copyright (c) 2003, Brad Hards + * + * This library is distributed under the conditions of the GNU LGPL. + * + * $Id: exr.cpp,v 1.4 2004/11/22 03:48:27 mueller Exp $ + */ + +/* + * utility function + * + * this does a conversion from the ILM Half (equal to Nvidia Half) + * format into the normal 32 bit pixel format. Process is from the + * ILM code. + * + */ + +RGBA RgbaToRGBA(struct Rgba imagePixel) +{ + float r,g,b,a; + + // 1) Compensate for fogging by subtracting defog + // from the raw pixel values. + // Response: We work with defog of 0.0, so this is a no-op + + // 2) Multiply the defogged pixel values by + // 2^(exposure + 2.47393). + // Response: We work with exposure of 0.0. + // (2^2.47393) is 5.55555 + r = imagePixel.r * 5.55555; + g = imagePixel.g * 5.55555; + b = imagePixel.b * 5.55555; + a = imagePixel.a * 5.55555; + + // 3) Values, which are now 1.0, are called "middle gray". + // If defog and exposure are both set to 0.0, then + // middle gray corresponds to a raw pixel value of 0.18. + // In step 6, middle gray values will be mapped to an + // intensity 3.5 f-stops below the display's maximum + // intensity. + // Response: no apparent content. + + // 4) Apply a knee function. The knee function has two + // parameters, kneeLow and kneeHigh. Pixel values + // below 2^kneeLow are not changed by the knee + // function. Pixel values above kneeLow are lowered + // according to a logarithmic curve, such that the + // value 2^kneeHigh is mapped to 2^3.5 (in step 6, + // this value will be mapped to the the display's + // maximum intensity). + // Response: kneeLow = 0.0 (2^0.0 => 1); kneeHigh = 5.0 (2^5 =>32) + if (r > 1.0) + r = 1.0 + Imath::Math::log ((r-1.0) * 0.184874 + 1) / 0.184874; + if (g > 1.0) + g = 1.0 + Imath::Math::log ((g-1.0) * 0.184874 + 1) / 0.184874; + if (b > 1.0) + b = 1.0 + Imath::Math::log ((b-1.0) * 0.184874 + 1) / 0.184874; + if (a > 1.0) + a = 1.0 + Imath::Math::log ((a-1.0) * 0.184874 + 1) / 0.184874; +// +// 5) Gamma-correct the pixel values, assuming that the +// screen's gamma is 0.4545 (or 1/2.2). + r = Imath::Math::pow (r, 0.4545); + g = Imath::Math::pow (g, 0.4545); + b = Imath::Math::pow (b, 0.4545); + a = Imath::Math::pow (a, 0.4545); + +// 6) Scale the values such that pixels middle gray +// pixels are mapped to 84.66 (or 3.5 f-stops below +// the display's maximum intensity). +// +// 7) Clamp the values to [0, 255]. + return RGBA( s8 (Imath::clamp ( r * 84.66f, 0.f, 255.f ) ), + s8 (Imath::clamp ( g * 84.66f, 0.f, 255.f ) ), + s8 (Imath::clamp ( b * 84.66f, 0.f, 255.f ) ), + s8 (Imath::clamp ( a * 84.66f, 0.f, 255.f ) ) ); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_openexr/fmt_codec_openexr_defs.h b/kernel/kls_openexr/fmt_codec_openexr_defs.h new file mode 100644 index 0000000..7b52b11 --- /dev/null +++ b/kernel/kls_openexr/fmt_codec_openexr_defs.h @@ -0,0 +1,27 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_openexr +#define KSQUIRREL_CODEC_DEFS_openexr + +// define constants here + +#endif diff --git a/kernel/kls_pcx/Makefile.am b/kernel/kls_pcx/Makefile.am new file mode 100644 index 0000000..5aaa5f3 --- /dev/null +++ b/kernel/kls_pcx/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_pcx.la + +libkls_pcx_la_SOURCES = fmt_codec_pcx.cpp fmt_codec_pcx_defs.h + +libkls_pcx_la_LDFLAGS = ${SQ_RELEASE} + +libkls_pcx_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_pcx/fmt_codec_pcx.cpp b/kernel/kls_pcx/fmt_codec_pcx.cpp new file mode 100644 index 0000000..4a8710f --- /dev/null +++ b/kernel/kls_pcx/fmt_codec_pcx.cpp @@ -0,0 +1,256 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pcx_defs.h" +#include "fmt_codec_pcx.h" + +#include "../xpm/codec_pcx.xpm" + +/* + * + * PCX is one of the most widely used storage + * formats. It originated with ZSoft's MS-DOS-based + * PC Paintbrush, and because of this, + * PCX is sometimes referred to as the + * PC Paintbrush format. ZSoft entered into an + * OEM arrangement with Microsoft, which allowed + * Microsoft to bundle PC Paintbrush with various + * products, including a version called Microsoft Paintbrush for Windows; + * this product was distributed with every copy of Microsoft Windows + * sold. This distribution established the importance of + * PCX, not only on Intel-based + * MS-DOS platforms, but industry-wide. + * + */ + +bool getrow(ifstreamK &s, u8*, int); + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.8.1"; + o->name = "ZSoft PCX"; + o->filter = "*.pcx "; + o->config = ""; + o->mime = "\x000A[\x0002\x0003\x0004\x0005]"; + o->mimetype = "image/x-pcx"; + o->pixmap = codec_pcx; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + pal_entr = 0; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + if(!frs.readK(&pfh, sizeof(PCX_HEADER))) return SQE_R_BADFILE; + + if(pfh.ID != 10 || pfh.Encoding != 1) + return SQE_R_BADFILE; + + image.w = pfh.Xmax - pfh.Xmin + 1; + image.h = pfh.Ymax - pfh.Ymin + 1; + image.bpp = pfh.bpp * pfh.NPlanes; + pal_entr = 0; + + if(pfh.bpp == 1) + { + pal_entr = 2; + + memset(pal, 0, sizeof(RGB)); + memset(pal+1, 255, sizeof(RGB)); + + } + else if(pfh.bpp <= 4) + { + pal_entr = 16; + + memcpy(pal, pfh.Palette, 48); + } + else if(pfh.bpp == 8 && pfh.NPlanes == 1) + { + pal_entr = 256; + + frs.seekg(-769, ios::end); + + s8 test; + if(!frs.readK(&test, 1)) return SQE_R_BADFILE; + + if(test != PCX_COLORMAP_SIGNATURE && test != PCX_COLORMAP_SIGNATURE_NEW) + return SQE_R_BADFILE; + + if(!frs.readK(pal, 768)) return SQE_R_BADFILE; + } + + frs.seekg(128, ios::beg); + + TotalBytesLine = pfh.NPlanes * pfh.BytesPerLine; + + image.compression = "-"; + image.colorspace = ((pal_entr) ? "Color indexed":"RGB"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + u16 i, j; + u8 channel[4][finfo.image[currentImage].w]; + u8 indexes[finfo.image[currentImage].w]; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + for(i = 0;i < 4;i++) + memset(channel[i], 255, im->w); + + switch(im->bpp) + { + case 1: + { + } + break; + + case 4: + { + } + break; + + case 8: + if(!getrow(frs, indexes, pfh.BytesPerLine)) + return SQE_R_BADFILE; + + for(i = 0;i < im->w;i++) + memcpy(scan+i, pal+indexes[i], sizeof(RGB)); + break; + + case 16: + { + } + break; + + case 24: + { + for(j = 0;j < pfh.NPlanes;j++) + { + if(!getrow(frs, channel[j], pfh.BytesPerLine)) + return SQE_R_BADFILE; + } + + for(i = 0;i < im->w;i++) + { + scan[i].r = channel[0][i]; + scan[i].g = channel[1][i]; + scan[i].b = channel[2][i]; + } + } + break; + + default:; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +/* helper function */ +bool getrow(ifstreamK &f, u8 *pcxrow, s32 bytesperline) +{ + static s32 repetitionsLeft = 0; + static u8 c; + s32 bytesGenerated; + + bytesGenerated = 0; + while(bytesGenerated < bytesperline) + { + if(repetitionsLeft > 0) + { + pcxrow[bytesGenerated++] = c; + --repetitionsLeft; + } + else + { + if(!f.readK(&c, 1)) return false; + + if(c <= 192) + pcxrow[bytesGenerated++] = c; + else + { + repetitionsLeft = c&63; + if(!f.readK(&c, 1)) return false; + } + } + } + + return true; +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_pcx/fmt_codec_pcx_defs.h b/kernel/kls_pcx/fmt_codec_pcx_defs.h new file mode 100644 index 0000000..ba45b21 --- /dev/null +++ b/kernel/kls_pcx/fmt_codec_pcx_defs.h @@ -0,0 +1,48 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pcx +#define KSQUIRREL_READ_IMAGE_pcx + +#define PCX_COLORMAP_SIGNATURE (0x0c) +#define PCX_COLORMAP_SIGNATURE_NEW (0x0a) + +struct PCX_HEADER +{ + u8 ID; + u8 Version; + u8 Encoding; + u8 bpp; + u16 Xmin,Ymin,Xmax,Ymax; + u16 VDpi; + u16 HDpi; + u8 Palette[48]; + u8 Reserved; + u8 NPlanes; + u16 BytesPerLine; + u16 PaletteInfo; + u16 HScreenSize; + u16 VScreenSize; + u8 Filler[54]; /* Header should be 128 byte length */ + +}PACKED; + +#endif diff --git a/kernel/kls_pi1/Makefile.am b/kernel/kls_pi1/Makefile.am new file mode 100644 index 0000000..f4c6513 --- /dev/null +++ b/kernel/kls_pi1/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I../include + +bin_SCRIPTS = ksquirrel-libs-pi12ppm + +pkglib_LTLIBRARIES = libkls_pi1.la + +libkls_pi1_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_pi1_la_LDFLAGS = ${SQ_RELEASE} + +libkls_pi1_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DCODEC_NETPBM -DCODEC_PI1 -DNETPBM_S=\"${bindir}/ksquirrel-libs-pi12ppm\" + +EXTRA_DIST = ksquirrel-libs-pi12ppm.in \ No newline at end of file diff --git a/kernel/kls_pi1/fmt_codec_pnm.cpp b/kernel/kls_pi1/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_pi1/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_pi1/fmt_codec_pnm_defs.h b/kernel/kls_pi1/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_pi1/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_pi1/ksquirrel-libs-pi12ppm.in b/kernel/kls_pi1/ksquirrel-libs-pi12ppm.in new file mode 100644 index 0000000..8d123f2 --- /dev/null +++ b/kernel/kls_pi1/ksquirrel-libs-pi12ppm.in @@ -0,0 +1,3 @@ +#!/bin/sh + +@PI1TOPPM@ "$1" > "$2" \ No newline at end of file diff --git a/kernel/kls_pi3/Makefile.am b/kernel/kls_pi3/Makefile.am new file mode 100644 index 0000000..abd5bb4 --- /dev/null +++ b/kernel/kls_pi3/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I../include + +bin_SCRIPTS = ksquirrel-libs-pi32ppm + +pkglib_LTLIBRARIES = libkls_pi3.la + +libkls_pi3_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_pi3_la_LDFLAGS = ${SQ_RELEASE} + +libkls_pi3_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DCODEC_NETPBM -DCODEC_PI3 -DNETPBM_S=\"${bindir}/ksquirrel-libs-pi32ppm\" + +EXTRA_DIST = ksquirrel-libs-pi32ppm.in \ No newline at end of file diff --git a/kernel/kls_pi3/fmt_codec_pnm.cpp b/kernel/kls_pi3/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_pi3/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_pi3/fmt_codec_pnm_defs.h b/kernel/kls_pi3/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_pi3/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_pi3/ksquirrel-libs-pi32ppm.in b/kernel/kls_pi3/ksquirrel-libs-pi32ppm.in new file mode 100644 index 0000000..c79d0b6 --- /dev/null +++ b/kernel/kls_pi3/ksquirrel-libs-pi32ppm.in @@ -0,0 +1,3 @@ +#!/bin/sh + +@PI3TOPPM@ "$1" > "$2" \ No newline at end of file diff --git a/kernel/kls_pict/Makefile.am b/kernel/kls_pict/Makefile.am new file mode 100644 index 0000000..a5732e7 --- /dev/null +++ b/kernel/kls_pict/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I../include + +bin_SCRIPTS = ksquirrel-libs-pict2ppm + +pkglib_LTLIBRARIES = libkls_pict.la + +libkls_pict_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_pict_la_LDFLAGS = ${SQ_RELEASE} + +libkls_pict_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DCODEC_NETPBM -DCODEC_PICT -DNETPBM_S=\"${bindir}/ksquirrel-libs-pict2ppm\" + +EXTRA_DIST = ksquirrel-libs-pict2ppm.in \ No newline at end of file diff --git a/kernel/kls_pict/fmt_codec_pnm.cpp b/kernel/kls_pict/fmt_codec_pnm.cpp new file mode 100644 index 0000000..00edbfb --- /dev/null +++ b/kernel/kls_pict/fmt_codec_pnm.cpp @@ -0,0 +1,1469 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_pict/fmt_codec_pnm_defs.h b/kernel/kls_pict/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_pict/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_pict/ksquirrel-libs-pict2ppm.in b/kernel/kls_pict/ksquirrel-libs-pict2ppm.in new file mode 100644 index 0000000..3074acd --- /dev/null +++ b/kernel/kls_pict/ksquirrel-libs-pict2ppm.in @@ -0,0 +1,3 @@ +#!/bin/sh + +@PICTTOPPM@ "$1" > "$2" \ No newline at end of file diff --git a/kernel/kls_pix/Makefile.am b/kernel/kls_pix/Makefile.am new file mode 100644 index 0000000..c26bf49 --- /dev/null +++ b/kernel/kls_pix/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_pix.la + +libkls_pix_la_SOURCES = fmt_codec_pix.cpp fmt_codec_pix_defs.h + +libkls_pix_la_LDFLAGS = ${SQ_RELEASE} + +libkls_pix_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_pix/fmt_codec_pix.cpp b/kernel/kls_pix/fmt_codec_pix.cpp new file mode 100644 index 0000000..9b10298 --- /dev/null +++ b/kernel/kls_pix/fmt_codec_pix.cpp @@ -0,0 +1,156 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fmt_utils.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" + +#include "fmt_codec_pix_defs.h" +#include "fmt_codec_pix.h" + +#include "../xpm/codec_pix.xpm" + +/* + * + * This format is sourced on IRIX + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "1.1.0"; + o->name = "Irix PIX image"; + o->filter = "*.pix "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pix"; + o->pixmap = codec_pix; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + u16 _tmp; + PIX_HEADER pfh; + + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + if(!frs.be_getshort(&pfh.width)) return SQE_R_BADFILE; + if(!frs.be_getshort(&pfh.height)) return SQE_R_BADFILE; + + if(!frs.readK(&_tmp, sizeof(u16))) return SQE_R_BADFILE; + if(!frs.readK(&_tmp, sizeof(u16))) return SQE_R_BADFILE; + + if(!frs.be_getshort(&pfh.bpp)) return SQE_R_BADFILE; + + if(pfh.bpp != 24) + return SQE_R_BADFILE; + + image.w = pfh.width; + image.h = pfh.height; + image.bpp = pfh.bpp; + image.compression = "RLE"; + image.colorspace = fmt_utils::colorSpaceByBpp(24); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + s32 len = 0, i, counter = 0; + u8 count; + RGB rgb; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(im->bpp) + { + case 24: + do + { + if(!frs.readK(&count, 1)) return SQE_R_BADFILE; + len += count; + + if(!frs.readK(&rgb.b, 1)) return SQE_R_BADFILE; + if(!frs.readK(&rgb.g, 1)) return SQE_R_BADFILE; + if(!frs.readK(&rgb.r, 1)) return SQE_R_BADFILE; + + for(i = 0;i < count;i++) + memcpy(scan+counter++, &rgb, 3); + + }while(len < im->w); + break; + + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_pix/fmt_codec_pix_defs.h b/kernel/kls_pix/fmt_codec_pix_defs.h new file mode 100644 index 0000000..993b790 --- /dev/null +++ b/kernel/kls_pix/fmt_codec_pix_defs.h @@ -0,0 +1,36 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include + +#ifndef KSQUIRREL_READ_IMAGE_pix +#define KSQUIRREL_READ_IMAGE_pix + +struct PIX_HEADER +{ + ushort width; + ushort height; + ushort x,y; // not used + ushort bpp; // always 24! + +}PACKED; + +#endif diff --git a/kernel/kls_png/Makefile.am b/kernel/kls_png/Makefile.am new file mode 100644 index 0000000..c66c0f2 --- /dev/null +++ b/kernel/kls_png/Makefile.am @@ -0,0 +1,15 @@ +SUBDIRS = ksquirrel-libs-png + +INCLUDES = -I../include -Iksquirrel-libs-png + +pkglib_LTLIBRARIES = libkls_png.la + +libkls_png_la_SOURCES = fmt_codec_png.cpp fmt_codec_png_defs.h + +libkls_png_la_LDFLAGS = ${SQ_RELEASE} + +libkls_png_la_LIBADD = ${SQ_LOCAL_RPATH} -Lksquirrel-libs-png -lksquirrel-libs-png + +EXTRA_DIST = README + +AM_CXXFLAGS = -DCODEC_PNG \ No newline at end of file diff --git a/kernel/kls_png/README b/kernel/kls_png/README new file mode 100644 index 0000000..df9734d --- /dev/null +++ b/kernel/kls_png/README @@ -0,0 +1,2 @@ +PNG codec uses its own libpng-1.2.20 version +to support APNG images. \ No newline at end of file diff --git a/kernel/kls_png/fmt_codec_png.cpp b/kernel/kls_png/fmt_codec_png.cpp new file mode 100644 index 0000000..66c43ee --- /dev/null +++ b/kernel/kls_png/fmt_codec_png.cpp @@ -0,0 +1,655 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs-png/png.h" + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_png_defs.h" +#include "fmt_codec_png.h" + +#if defined CODEC_SVG || defined CODEC_DICOM +#include +#include +#include +#include +#endif + +#ifdef CODEC_SVG +#include "../xpm/codec_svg.xpm" +#elif defined CODEC_DICOM +#include "../xpm/codec_dicom.xpm" +#else +#include "../xpm/codec_png.xpm" +#endif + +/* + * + * PNG (pronounced "ping") is a bitmap file format used to transmit and + * store bitmapped images. PNG supports the capability of storing up to + * 16 bits (gray-scale) or 48 bits (truecolor) per pixel, and up to 16 bits + * of alpha data. It handles the progressive display + * of image data and the storage of gamma, + * transparency and textual information, and it uses an efficient and + * lossless form of data compression. + * + */ + +inline bool MALLOC_ROWS(png_bytep **A, const int RB, const int H) +{ + *A = (png_bytep*)malloc(H * sizeof(png_bytep*)); + + if(!*A) + return false; + + for(s32 row = 0; row < H; row++) + (*A)[row] = 0; + + for(s32 row = 0; row < (s32)H; row++) + { + (*A)[row] = (png_bytep)malloc(RB); + + if(!(*A)[row]) + return false; + + memset((*A)[row], 0, RB); + } + + return true; +} + +inline void FREE_ROWS(png_bytep **A, const int H) +{ + if(*A) + { + for(s32 i = 0;i < H;i++) + { + if((*A)[i]) + free((*A)[i]); + } + + free(*A); + *A = 0; + } +} + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ +#ifdef CODEC_SVG + o->version = "0.1.2"; + o->name = "Scalable Vector Graphics"; + o->filter = "*.svg *.svgz "; + o->config = std::string(SVG_UI); // SVG_UI comes from Makefile.am + o->mime = ""; + o->mimetype = "image/svg+xml"; + o->pixmap = codec_svg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DICOM + o->version = "1.1.3"; + o->name = "DICOM"; + o->filter = "*.dcm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-dicom"; + o->pixmap = codec_dicom; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "1.1.3"; + o->name = "Portable Network Graphics"; + o->filter = "*.png "; + o->config = ""; + o->mime = "\x0089\x0050\x004E\x0047\x000D\x000A\x001A\x000A"; + o->mimetype = "image/png"; + o->pixmap = codec_png; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#ifdef CODEC_ANOTHER +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_int; + val.iVal = 1; + + m_settings["scale"] = val; +} +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + png_ptr = 0; + info_ptr = 0; + fptr = 0; + frame = 0; + prev = 0; + cur = 0; + zerror = false; + +#ifdef CODEC_SVG + int status; + + fmt_settings::iterator it = m_settings.find("scale"); + + // percents / 100 + int scale = (it == m_settings.end() || (*it).second.type != settings_value::v_int) + ? 1 : (*it).second.iVal; + + if(scale < 1 || scale > 10) + scale = 1; + + char z[32]; + snprintf(z, 32, "%d", scale); + + pid_t pid = fork(); + + if(!pid) + { + execlp(SVG2PNG, SVG2PNG, "--binary", RSVG, "--input", file.c_str(), "--output", tmp.c_str(), "-z", z, (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DICOM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(DICOM, DICOM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#else + fptr = fopen(file.c_str(), "rb"); +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + if((png_ptr = my_png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0)) == NULL) + { + zerror = true; + return SQE_R_NOMEMORY; + } + + if((info_ptr = my_png_create_info_struct(png_ptr)) == NULL) + { + zerror = true; + return SQE_R_NOMEMORY; + } + + if(setjmp(png_jmpbuf(png_ptr))) + { + zerror = true; + return SQE_R_BADFILE; + } + + my_png_init_io(png_ptr, fptr); + my_png_read_info(png_ptr, info_ptr); + my_png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, (int*)0, (int*)0); + + img.w = next_frame_width = width; + img.h = next_frame_height = height; + img.bpp = bit_depth; + + if(img.bpp == 16) + my_png_set_strip_16(png_ptr); + + if(img.bpp < 8) + my_png_set_packing(png_ptr); + + if(color_type == PNG_COLOR_TYPE_GRAY && img.bpp < 8) + my_png_set_gray_1_2_4_to_8(png_ptr); + + if(color_type == PNG_COLOR_TYPE_PALETTE) + my_png_set_palette_to_rgb(png_ptr); + + if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + my_png_set_gray_to_rgb(png_ptr); + + if(my_png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + my_png_set_tRNS_to_alpha(png_ptr); + + my_png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + + number_passes = my_png_set_interlace_handling(png_ptr); + + my_png_read_update_info(png_ptr, info_ptr); + + finfo.animated = !!my_png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL); + + frames = finfo.animated ? my_png_get_num_frames(png_ptr, info_ptr) : 1; + + if(!frames) return SQE_R_BADFILE; + + img.interlaced = number_passes > 1; + img.passes = finfo.animated ? 1 : number_passes; + + if(finfo.animated) + { + if(!MALLOC_ROWS(&prev, width * sizeof(RGBA), height)) + return SQE_R_NOMEMORY; + + if(!MALLOC_ROWS(&cur, width * sizeof(RGBA), height)) + return SQE_R_NOMEMORY; + } + + std::string color_; + + img.hasalpha = (color_type & PNG_COLOR_MASK_ALPHA); + + switch((color_type & ~PNG_COLOR_MASK_ALPHA)) + { + case PNG_COLOR_TYPE_RGB: color_ = "RGB"; break; + case PNG_COLOR_TYPE_PALETTE: color_ = "Color indexed"; break; + case PNG_COLOR_TYPE_GRAY: color_ = "Grayscale"; break; + + default: + color_ = "Unknown"; + } + + if(img.hasalpha) + color_ += " with ALPHA"; + + img.compression = "Deflate method 8, 32K window"; + img.colorspace = color_; + if(!finfo.animated) img.delay = 0; + +#ifdef PNG_TEXT_SUPPORTED + png_textp lines = info_ptr->text; + + if(!lines || !info_ptr->num_text) + return SQE_OK; + + for(s32 i = 0;i < info_ptr->num_text;i++) + { + fmt_metaentry mt; + + mt.group = lines[i].key; + mt.data = lines[i].text; + + addmeta(mt); + } +#endif + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage == frames) + return SQE_NOTOK; + + if(setjmp(png_jmpbuf(png_ptr))) + { + zerror = true; + return SQE_R_BADFILE; + } + + if(finfo.animated) + { + if(currentImage) + { + if(next_frame_dispose_op == PNG_DISPOSE_OP_BACKGROUND) + { + for(u32 j = next_frame_y_offset,i = 0;i < next_frame_height;j++,i++) + memset(cur[j]+next_frame_x_offset*sizeof(RGBA), 0, next_frame_width * sizeof(RGBA)); + } + else if(next_frame_dispose_op == PNG_DISPOSE_OP_PREVIOUS) + { + for(u32 i = 0;i < height;i++) + memcpy(cur[i], prev[i], width*sizeof(RGBA)); + } + else // next_frame_dispose_op == PNG_DISPOSE_OP_NONE + { + } + + for(u32 i = 0;i < height;i++) + memcpy(prev[i], cur[i], width*sizeof(RGBA)); + } + else if(my_png_get_first_frame_is_hidden(png_ptr, info_ptr)) + { + if(!MALLOC_ROWS(&frame, width * sizeof(RGBA), height)) + return SQE_R_NOMEMORY; + + my_png_read_frame_head(png_ptr, info_ptr); + my_png_read_image(png_ptr, frame); + + FREE_ROWS(&frame, height); + + frames--; + + if(frames == 1) + { + my_png_read_frame_head(png_ptr, info_ptr); + finfo.animated = false; + img.passes = number_passes; + finfo.image.push_back(img); + return SQE_OK; + } + else if(!frames) + return SQE_R_BADFILE; // oops? + } + + FREE_ROWS(&frame, next_frame_height); + + my_png_read_frame_head(png_ptr, info_ptr); + + if(my_png_get_valid(png_ptr, info_ptr, PNG_INFO_fcTL)) + { + my_png_get_next_frame_fcTL(png_ptr, info_ptr, + &next_frame_width, &next_frame_height, + &next_frame_x_offset, &next_frame_y_offset, + &next_frame_delay_num, &next_frame_delay_den, + &next_frame_dispose_op, &next_frame_blend_op); + } + else + { + next_frame_width = width; + next_frame_height = height; + next_frame_x_offset = 0; + next_frame_y_offset = 0; + next_frame_dispose_op = PNG_DISPOSE_OP_BACKGROUND; + next_frame_blend_op = PNG_BLEND_OP_SOURCE; + } + + if(!next_frame_delay_den) next_frame_delay_den = 100; + + img.delay = (s32)(((double)next_frame_delay_num / next_frame_delay_den) * 1000); + + if(next_frame_width + next_frame_x_offset > width || next_frame_height + next_frame_y_offset > height) + return SQE_R_BADFILE; + + if(!MALLOC_ROWS(&frame, next_frame_width * sizeof(RGBA), next_frame_height)) + return SQE_R_NOMEMORY; + + my_png_read_image(png_ptr, frame); + + // copy all pixel values including alpha + if(!currentImage || next_frame_blend_op == PNG_BLEND_OP_SOURCE) + { + for(u32 j = next_frame_y_offset,i = 0;i < next_frame_height;j++,i++) + memcpy(cur[j]+next_frame_x_offset*sizeof(RGBA), frame[i], next_frame_width * sizeof(RGBA)); + } + else // over + { + RGBA *src, *dst; + + for(u32 j = next_frame_y_offset,i = 0;i < next_frame_height;j++,i++) + { + src = (RGBA *)frame[i]; + dst = (RGBA *)(cur[j]+next_frame_x_offset*sizeof(RGBA)); + u32 k = next_frame_width; + + while(k--) + { + // fully transparent foreground + if(src->a == 0) + ; + else if(src->a == 255 || dst->a == 0) + *dst = *src; + else // composite + { + dst->r = ((src->a * (src->r - dst->r))>>8) + dst->r; + dst->g = ((src->a * (src->g - dst->g))>>8) + dst->g; + dst->b = ((src->a * (src->b - dst->b))>>8) + dst->b; + //dst->a = ((src->a * (src->a - dst->a))>>8) + dst->a; + } + + src++; + dst++; + } + } + } + } + + finfo.image.push_back(img); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + fmt_image *im = image(currentImage); + + line++; + + if(zerror || setjmp(png_jmpbuf(png_ptr))) + { + zerror = true; + return SQE_R_BADFILE; + } + + if(finfo.animated) + memcpy(scan, cur[line], im->w * sizeof(RGBA)); + else + my_png_read_row(png_ptr, (png_bytep)scan, png_bytep_NULL); + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(png_ptr) my_png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); + + if(fptr) fclose(fptr); + + FREE_ROWS(&frame, next_frame_height); + FREE_ROWS(&prev, height); + FREE_ROWS(&cur, height); + + finfo.meta.clear(); + finfo.image.clear(); +} + +#ifdef CODEC_PNG + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = true; + opt->compression_scheme = CompressionInternal; + opt->compression_min = 1; + opt->compression_max = 9; + opt->compression_def = 7; + opt->passes = 8; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + m_png_ptr = 0; + m_info_ptr = 0; + m_fptr = 0; + m_zerror = false; + + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + m_fptr = fopen(file.c_str(), "wb"); + + if(!m_fptr) + return SQE_W_NOFILE; + + m_png_ptr = my_png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + + if(!m_png_ptr) + { + m_zerror = true; + return SQE_W_NOMEMORY; + } + + m_info_ptr = my_png_create_info_struct(m_png_ptr); + + if(!m_info_ptr) + { + m_zerror = true; + return SQE_W_NOMEMORY; + } + + if(setjmp(png_jmpbuf(m_png_ptr))) + { + m_zerror = true; + return SQE_W_ERROR; + } + + my_png_init_io(m_png_ptr, m_fptr); + + my_png_set_IHDR(m_png_ptr, m_info_ptr, writeimage.w, writeimage.h, 8, PNG_COLOR_TYPE_RGB_ALPHA, + ((writeopt.interlaced) ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE), + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_color_8 sig_bit; + + sig_bit.red = 8; + sig_bit.green = 8; + sig_bit.blue = 8; + sig_bit.alpha = 8; + + my_png_set_sBIT(m_png_ptr, m_info_ptr, &sig_bit); + + s32 factor = (writeopt.compression_level < 1 || writeopt.compression_level > 9) ? 1 : writeopt.compression_level; + + my_png_set_compression_level(m_png_ptr, factor); + + my_png_write_info(m_png_ptr, m_info_ptr); + + my_png_set_shift(m_png_ptr, &sig_bit); + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + my_png_set_swap(m_png_ptr); + + my_png_set_packswap(m_png_ptr); + + my_png_set_interlace_handling(m_png_ptr); + + return SQE_OK; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + if(m_zerror || setjmp(png_jmpbuf(m_png_ptr))) + { + m_zerror = true; + return SQE_W_ERROR; + } + + m_row_pointer = (png_bytep)scan; + + my_png_write_rows(m_png_ptr, &m_row_pointer, 1); + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + if(m_png_ptr && !m_zerror) my_png_write_end(m_png_ptr, m_info_ptr); + if(m_png_ptr) my_png_destroy_write_struct(&m_png_ptr, &m_info_ptr); + if(m_fptr) fclose(m_fptr); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("png"); +} + +#endif + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_png/fmt_codec_png_defs.h b/kernel/kls_png/fmt_codec_png_defs.h new file mode 100644 index 0000000..afef4ac --- /dev/null +++ b/kernel/kls_png/fmt_codec_png_defs.h @@ -0,0 +1,27 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_png +#define KSQUIRREL_READ_IMAGE_png + +// Nothing to define at this moment :) + +#endif diff --git a/kernel/kls_png/ksquirrel-libs-png/Makefile.am b/kernel/kls_png/ksquirrel-libs-png/Makefile.am new file mode 100644 index 0000000..9f88f20 --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/Makefile.am @@ -0,0 +1,8 @@ +INCLUDES = -I. + +lib_LTLIBRARIES = libksquirrel-libs-png.la + +libksquirrel_libs_png_la_SOURCES = png.c pngconf.h pngerror.c pnggccrd.c pngget.c png.h pngmem.c pngpread.c pngread.c pngrio.c pngrtran.c \ +pngrutil.c pngset.c pngtrans.c pngvcrd.c pngwio.c pngwrite.c pngwtran.c pngwutil.c pnghack.h + +libksquirrel_libs_png_la_LIBADD = -lz -lm diff --git a/kernel/kls_png/ksquirrel-libs-png/png.c b/kernel/kls_png/ksquirrel-libs-png/png.c new file mode 100644 index 0000000..3e507c6 --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/png.c @@ -0,0 +1,792 @@ + +/* png.c - location for general purpose libpng functions + * + * Last changed in libpng 1.2.19 August 19, 2007 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2007 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#define PNG_NO_EXTERN +#include "png.h" + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef version_1_2_20 Your_png_h_is_not_version_1_2_20; + +/* Version information for C files. This had better match the version + * string defined in png.h. */ + +#ifdef PNG_USE_GLOBAL_ARRAYS +/* png_libpng_ver was changed to a function in version 1.0.5c */ +PNG_CONST char png_libpng_ver[18] = PNG_LIBPNG_VER_STRING; + +#ifdef PNG_READ_SUPPORTED + +/* png_sig was changed to a function in version 1.0.5c */ +/* Place to hold the signature string for a PNG file. */ +PNG_CONST png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; +#endif /* PNG_READ_SUPPORTED */ + +/* Invoke global declarations for constant strings for known chunk types */ +PNG_IHDR; +PNG_IDAT; +PNG_IEND; +PNG_PLTE; +PNG_bKGD; +PNG_cHRM; +PNG_gAMA; +PNG_hIST; +PNG_iCCP; +PNG_iTXt; +PNG_oFFs; +PNG_pCAL; +PNG_sCAL; +PNG_pHYs; +PNG_sBIT; +PNG_sPLT; +PNG_sRGB; +PNG_tEXt; +PNG_tIME; +PNG_tRNS; +PNG_zTXt; +PNG_acTL; +PNG_fcTL; +PNG_fdAT; + +#ifdef PNG_READ_SUPPORTED +/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + +/* start of interlace block */ +PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + +/* offset to next interlace block */ +PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + +/* start of interlace block in the y direction */ +PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + +/* offset to next interlace block in the y direction */ +PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + +/* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h +PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; +*/ + +/* Mask to determine which pixels are valid in a pass */ +PNG_CONST int FARDATA png_pass_mask[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; + +/* Mask to determine which pixels to overwrite while displaying */ +PNG_CONST int FARDATA png_pass_dsp_mask[] + = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; + +#endif /* PNG_READ_SUPPORTED */ +#endif /* PNG_USE_GLOBAL_ARRAYS */ + +/* Tells libpng that we have already handled the first "num_bytes" bytes + * of the PNG file signature. If the PNG data is embedded into another + * stream we can set num_bytes = 8 so that libpng will not attempt to read + * or write any of the magic bytes before it starts on the IHDR. + */ + +#ifdef PNG_READ_SUPPORTED +void PNGAPI +png_set_sig_bytes(png_structp png_ptr, int num_bytes) +{ + if(png_ptr == NULL) return; + png_debug(1, "in png_set_sig_bytes\n"); + if (num_bytes > 8) + png_error(png_ptr, "Too many bytes for PNG signature."); + + png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes); +} + +/* Checks whether the supplied bytes match the PNG signature. We allow + * checking less than the full 8-byte signature so that those apps that + * already read the first few bytes of a file to determine the file type + * can simply check the remaining bytes for extra assurance. Returns + * an integer less than, equal to, or greater than zero if sig is found, + * respectively, to be less than, to match, or be greater than the correct + * PNG signature (this is the same behaviour as strcmp, memcmp, etc). + */ +int PNGAPI +png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + if (num_to_check > 8) + num_to_check = 8; + else if (num_to_check < 1) + return (-1); + + if (start > 7) + return (-1); + + if (start + num_to_check > 8) + num_to_check = 8 - start; + + return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check))); +} + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +/* (Obsolete) function to check signature bytes. It does not allow one + * to check a partial signature. This function might be removed in the + * future - use png_sig_cmp(). Returns true (nonzero) if the file is PNG. + */ +int PNGAPI +png_check_sig(png_bytep sig, int num) +{ + return ((int)!png_sig_cmp(sig, (png_size_t)0, (png_size_t)num)); +} +#endif +#endif /* PNG_READ_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +/* Function to allocate memory for zlib and clear it to 0. */ +#ifdef PNG_1_0_X +voidpf PNGAPI +#else +voidpf /* private */ +#endif +png_zalloc(voidpf png_ptr, uInt items, uInt size) +{ + png_voidp ptr; + png_structp p=(png_structp)png_ptr; + png_uint_32 save_flags=p->flags; + png_uint_32 num_bytes; + + if(png_ptr == NULL) return (NULL); + if (items > PNG_UINT_32_MAX/size) + { + png_warning (p, "Potential overflow in png_zalloc()"); + return (NULL); + } + num_bytes = (png_uint_32)items * size; + + p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes); + p->flags=save_flags; + +#if defined(PNG_1_0_X) && !defined(PNG_NO_ZALLOC_ZERO) + if (ptr == NULL) + return ((voidpf)ptr); + + if (num_bytes > (png_uint_32)0x8000L) + { + png_memset(ptr, 0, (png_size_t)0x8000L); + png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0, + (png_size_t)(num_bytes - (png_uint_32)0x8000L)); + } + else + { + png_memset(ptr, 0, (png_size_t)num_bytes); + } +#endif + return ((voidpf)ptr); +} + +/* function to free memory for zlib */ +#ifdef PNG_1_0_X +void PNGAPI +#else +void /* private */ +#endif +png_zfree(voidpf png_ptr, voidpf ptr) +{ + png_free((png_structp)png_ptr, (png_voidp)ptr); +} + +/* Reset the CRC variable to 32 bits of 1's. Care must be taken + * in case CRC is > 32 bits to leave the top bits 0. + */ +void /* PRIVATE */ +png_reset_crc(png_structp png_ptr) +{ + png_ptr->crc = crc32(0, Z_NULL, 0); +} + +/* Calculate the CRC over a section of data. We can only pass as + * much data to this routine as the largest single buffer size. We + * also check that this data will actually be used before going to the + * trouble of calculating it. + */ +void /* PRIVATE */ +png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length) +{ + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + if (need_crc) + png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length); +} + +/* Allocate the memory for an info_struct for the application. We don't + * really need the png_ptr, but it could potentially be useful in the + * future. This should be used in favour of malloc(png_sizeof(png_info)) + * and png_info_init() so that applications that want to use a shared + * libpng don't have to be recompiled if png_info changes size. + */ +png_infop PNGAPI +png_create_info_struct(png_structp png_ptr) +{ + png_infop info_ptr; + + png_debug(1, "in png_create_info_struct\n"); + if(png_ptr == NULL) return (NULL); +#ifdef PNG_USER_MEM_SUPPORTED + info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO, + png_ptr->malloc_fn, png_ptr->mem_ptr); +#else + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); +#endif + if (info_ptr != NULL) + png_info_init_3(&info_ptr, png_sizeof(png_info)); + + return (info_ptr); +} + +/* This function frees the memory associated with a single info struct. + * Normally, one would use either png_destroy_read_struct() or + * png_destroy_write_struct() to free an info struct, but this may be + * useful for some applications. + */ +void PNGAPI +png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr) +{ + png_infop info_ptr = NULL; + if(png_ptr == NULL) return; + + png_debug(1, "in png_destroy_info_struct\n"); + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + png_info_destroy(png_ptr, info_ptr); + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn, + png_ptr->mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } +} + +/* Initialize the info structure. This is now an internal function (0.89) + * and applications using it are urged to use png_create_info_struct() + * instead. + */ + +void PNGAPI +png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size) +{ + png_infop info_ptr = *ptr_ptr; + + if(info_ptr == NULL) return; + + png_debug(1, "in png_info_init_3\n"); + + if(png_sizeof(png_info) > png_info_struct_size) + { + png_destroy_struct(info_ptr); + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); + *ptr_ptr = info_ptr; + } + + /* set everything to 0 */ + png_memset(info_ptr, 0, png_sizeof (png_info)); +} + +#ifdef PNG_FREE_ME_SUPPORTED +void PNGAPI +png_data_freer(png_structp png_ptr, png_infop info_ptr, + int freer, png_uint_32 mask) +{ + png_debug(1, "in png_data_freer\n"); + if (png_ptr == NULL || info_ptr == NULL) + return; + if(freer == PNG_DESTROY_WILL_FREE_DATA) + info_ptr->free_me |= mask; + else if(freer == PNG_USER_WILL_FREE_DATA) + info_ptr->free_me &= ~mask; + else + png_warning(png_ptr, + "Unknown freer parameter in png_data_freer."); +} +#endif + +void PNGAPI +png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, + int num) +{ + png_debug(1, "in png_free_data\n"); + if (png_ptr == NULL || info_ptr == NULL) + return; + +#if defined(PNG_TEXT_SUPPORTED) +/* free text item num or (if num == -1) all text items */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) +#else +if (mask & PNG_FREE_TEXT) +#endif +{ + if (num != -1) + { + if (info_ptr->text && info_ptr->text[num].key) + { + png_free(png_ptr, info_ptr->text[num].key); + info_ptr->text[num].key = NULL; + } + } + else + { + int i; + for (i = 0; i < info_ptr->num_text; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); + png_free(png_ptr, info_ptr->text); + info_ptr->text = NULL; + info_ptr->num_text=0; + } +} +#endif + +#if defined(PNG_tRNS_SUPPORTED) +/* free any tRNS entry */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) +#else +if ((mask & PNG_FREE_TRNS) && (png_ptr->flags & PNG_FLAG_FREE_TRNS)) +#endif +{ + png_free(png_ptr, info_ptr->trans); + info_ptr->valid &= ~PNG_INFO_tRNS; +#ifndef PNG_FREE_ME_SUPPORTED + png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; +#endif + info_ptr->trans = NULL; +} +#endif + +#if defined(PNG_sCAL_SUPPORTED) +/* free any sCAL entry */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) +#else +if (mask & PNG_FREE_SCAL) +#endif +{ +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, info_ptr->scal_s_width); + png_free(png_ptr, info_ptr->scal_s_height); + info_ptr->scal_s_width = NULL; + info_ptr->scal_s_height = NULL; +#endif + info_ptr->valid &= ~PNG_INFO_sCAL; +} +#endif + +#if defined(PNG_pCAL_SUPPORTED) +/* free any pCAL entry */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) +#else +if (mask & PNG_FREE_PCAL) +#endif +{ + png_free(png_ptr, info_ptr->pcal_purpose); + png_free(png_ptr, info_ptr->pcal_units); + info_ptr->pcal_purpose = NULL; + info_ptr->pcal_units = NULL; + if (info_ptr->pcal_params != NULL) + { + int i; + for (i = 0; i < (int)info_ptr->pcal_nparams; i++) + { + png_free(png_ptr, info_ptr->pcal_params[i]); + info_ptr->pcal_params[i]=NULL; + } + png_free(png_ptr, info_ptr->pcal_params); + info_ptr->pcal_params = NULL; + } + info_ptr->valid &= ~PNG_INFO_pCAL; +} +#endif + +#if defined(PNG_iCCP_SUPPORTED) +/* free any iCCP entry */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) +#else +if (mask & PNG_FREE_ICCP) +#endif +{ + png_free(png_ptr, info_ptr->iccp_name); + png_free(png_ptr, info_ptr->iccp_profile); + info_ptr->iccp_name = NULL; + info_ptr->iccp_profile = NULL; + info_ptr->valid &= ~PNG_INFO_iCCP; +} +#endif + +#if defined(PNG_sPLT_SUPPORTED) +/* free a given sPLT entry, or (if num == -1) all sPLT entries */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) +#else +if (mask & PNG_FREE_SPLT) +#endif +{ + if (num != -1) + { + if(info_ptr->splt_palettes) + { + png_free(png_ptr, info_ptr->splt_palettes[num].name); + png_free(png_ptr, info_ptr->splt_palettes[num].entries); + info_ptr->splt_palettes[num].name = NULL; + info_ptr->splt_palettes[num].entries = NULL; + } + } + else + { + if(info_ptr->splt_palettes_num) + { + int i; + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i); + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = NULL; + info_ptr->splt_palettes_num = 0; + } + info_ptr->valid &= ~PNG_INFO_sPLT; + } +} +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + if(png_ptr->unknown_chunk.data) + { + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) +#else +if (mask & PNG_FREE_UNKN) +#endif +{ + if (num != -1) + { + if(info_ptr->unknown_chunks) + { + png_free(png_ptr, info_ptr->unknown_chunks[num].data); + info_ptr->unknown_chunks[num].data = NULL; + } + } + else + { + int i; + + if(info_ptr->unknown_chunks_num) + { + for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i); + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + info_ptr->unknown_chunks_num = 0; + } + } +} +#endif + +#if defined(PNG_hIST_SUPPORTED) +/* free any hIST entry */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_HIST) & info_ptr->free_me) +#else +if ((mask & PNG_FREE_HIST) && (png_ptr->flags & PNG_FLAG_FREE_HIST)) +#endif +{ + png_free(png_ptr, info_ptr->hist); + info_ptr->hist = NULL; + info_ptr->valid &= ~PNG_INFO_hIST; +#ifndef PNG_FREE_ME_SUPPORTED + png_ptr->flags &= ~PNG_FLAG_FREE_HIST; +#endif +} +#endif + +/* free any PLTE entry that was internally allocated */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) +#else +if ((mask & PNG_FREE_PLTE) && (png_ptr->flags & PNG_FLAG_FREE_PLTE)) +#endif +{ + png_zfree(png_ptr, info_ptr->palette); + info_ptr->palette = NULL; + info_ptr->valid &= ~PNG_INFO_PLTE; +#ifndef PNG_FREE_ME_SUPPORTED + png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; +#endif + info_ptr->num_palette = 0; +} + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +/* free any image bits attached to the info structure */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) +#else +if (mask & PNG_FREE_ROWS) +#endif +{ + if(info_ptr->row_pointers) + { + int row; + for (row = 0; row < (int)info_ptr->height; row++) + { + png_free(png_ptr, info_ptr->row_pointers[row]); + info_ptr->row_pointers[row]=NULL; + } + png_free(png_ptr, info_ptr->row_pointers); + info_ptr->row_pointers=NULL; + } + info_ptr->valid &= ~PNG_INFO_IDAT; +} +#endif + +#ifdef PNG_FREE_ME_SUPPORTED + if(num == -1) + info_ptr->free_me &= ~mask; + else + info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL); +#endif +} + +/* This is an internal routine to free any memory that the info struct is + * pointing to before re-using it or freeing the struct itself. Recall + * that png_free() checks for NULL pointers for us. + */ +void /* PRIVATE */ +png_info_destroy(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_info_destroy\n"); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + png_ptr->num_chunk_list=0; + } +#endif + + png_info_init_3(&info_ptr, png_sizeof(png_info)); +} +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +/* This function returns a pointer to the io_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy() or png_read_destroy() are called. + */ +png_voidp PNGAPI +png_get_io_ptr(png_structp png_ptr) +{ + if(png_ptr == NULL) return (NULL); + return (png_ptr->io_ptr); +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#if !defined(PNG_NO_STDIO) +/* Initialize the default input/output functions for the PNG file. If you + * use your own read or write routines, you can call either png_set_read_fn() + * or png_set_write_fn() instead of png_init_io(). If you have defined + * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't + * necessarily available. + */ +void PNGAPI +png_init_io(png_structp png_ptr, png_FILE_p fp) +{ + png_debug(1, "in png_init_io\n"); + if(png_ptr == NULL) return; + png_ptr->io_ptr = (png_voidp)fp; +} +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) +/* Convert the supplied time into an RFC 1123 string suitable for use in + * a "Creation Time" or other text-based time string. + */ +png_charp PNGAPI +png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime) +{ + static PNG_CONST char short_months[12][4] = + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + if(png_ptr == NULL) return (NULL); + if (png_ptr->time_buffer == NULL) + { + png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29* + png_sizeof(char))); + } + +#if defined(_WIN32_WCE) + { + wchar_t time_buf[29]; + wsprintf(time_buf, TEXT("%d %S %d %02d:%02d:%02d +0000"), + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); + WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer, 29, + NULL, NULL); + } +#else +#ifdef USE_FAR_KEYWORD + { + char near_time_buf[29]; + png_snprintf6(near_time_buf,29,"%d %s %d %02d:%02d:%02d +0000", + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); + png_memcpy(png_ptr->time_buffer, near_time_buf, + 29*png_sizeof(char)); + } +#else + png_snprintf6(png_ptr->time_buffer,29,"%d %s %d %02d:%02d:%02d +0000", + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); +#endif +#endif /* _WIN32_WCE */ + return ((png_charp)png_ptr->time_buffer); +} +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +png_charp PNGAPI +png_get_copyright(png_structp png_ptr) +{ + png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ + return ((png_charp) "\n libpng version 1.2.20 - September 8, 2007\n\ + Copyright (c) 1998-2007 Glenn Randers-Pehrson\n\ + Copyright (c) 1996-1997 Andreas Dilger\n\ + Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\n"); +} + +/* The following return the library version as a short string in the + * format 1.0.0 through 99.99.99zz. To get the version of *.h files + * used with your application, print out PNG_LIBPNG_VER_STRING, which + * is defined in png.h. + * Note: now there is no difference between png_get_libpng_ver() and + * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, + * it is guaranteed that png.c uses the correct version of png.h. + */ +png_charp PNGAPI +png_get_libpng_ver(png_structp png_ptr) +{ + /* Version of *.c files used when building libpng */ + png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ + return ((png_charp) PNG_LIBPNG_VER_STRING); +} + +png_charp PNGAPI +png_get_header_ver(png_structp png_ptr) +{ + /* Version of *.h files used when building libpng */ + png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ + return ((png_charp) PNG_LIBPNG_VER_STRING); +} + +png_charp PNGAPI +png_get_header_version(png_structp png_ptr) +{ + /* Returns longer string containing both version and date */ + png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ + return ((png_charp) PNG_HEADER_VERSION_STRING +#ifndef PNG_READ_SUPPORTED + " (NO READ SUPPORT)" +#endif + "\n"); +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +int PNGAPI +png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name) +{ + /* check chunk_name and return "keep" value if it's on the list, else 0 */ + int i; + png_bytep p; + if(png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0) + return 0; + p=png_ptr->chunk_list+png_ptr->num_chunk_list*5-5; + for (i = png_ptr->num_chunk_list; i; i--, p-=5) + if (!png_memcmp(chunk_name, p, 4)) + return ((int)*(p+4)); + return 0; +} +#endif + +/* This function, added to libpng-1.0.6g, is untested. */ +int PNGAPI +png_reset_zstream(png_structp png_ptr) +{ + if (png_ptr == NULL) return Z_STREAM_ERROR; + return (inflateReset(&png_ptr->zstream)); +} +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +/* This function was added to libpng-1.0.7 */ +png_uint_32 PNGAPI +png_access_version_number(void) +{ + /* Version of *.c files used when building libpng */ + return((png_uint_32) PNG_LIBPNG_VER); +} + + +#if defined(PNG_READ_SUPPORTED) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) +#if !defined(PNG_1_0_X) +/* this function was added to libpng 1.2.0 */ +int PNGAPI +png_mmx_support(void) +{ + /* obsolete, to be removed from libpng-1.4.0 */ + return -1; +} +#endif /* PNG_1_0_X */ +#endif /* PNG_READ_SUPPORTED && PNG_ASSEMBLER_CODE_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#ifdef PNG_SIZE_T +/* Added at libpng version 1.2.6 */ + PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); +png_size_t PNGAPI +png_convert_size(size_t size) +{ + if (size > (png_size_t)-1) + PNG_ABORT(); /* We haven't got access to png_ptr, so no png_error() */ + return ((png_size_t)size); +} +#endif /* PNG_SIZE_T */ +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ diff --git a/kernel/kls_png/ksquirrel-libs-png/png.h b/kernel/kls_png/ksquirrel-libs-png/png.h new file mode 100644 index 0000000..0b4873c --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/png.h @@ -0,0 +1,3672 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.2.20 - September 8, 2007 + * Copyright (c) 1998-2007 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.2.20 - September 8, 2007: Glenn + * See also "Contributing Authors", below. + * + * Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + * 1.0.8rc1 1 10008 2.1.0.8rc1 + * 1.0.8 1 10008 2.1.0.8 + * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + * 1.0.9rc1 1 10009 2.1.0.9rc1 + * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + * 1.0.9rc2 1 10009 2.1.0.9rc2 + * 1.0.9 1 10009 2.1.0.9 + * 1.0.10beta1 1 10010 2.1.0.10beta1 + * 1.0.10rc1 1 10010 2.1.0.10rc1 + * 1.0.10 1 10010 2.1.0.10 + * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + * 1.0.11rc1 1 10011 2.1.0.11rc1 + * 1.0.11 1 10011 2.1.0.11 + * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + * 1.0.12rc1 2 10012 2.1.0.12rc1 + * 1.0.12 2 10012 2.1.0.12 + * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) + * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + * 1.2.0rc1 3 10200 3.1.2.0rc1 + * 1.2.0 3 10200 3.1.2.0 + * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 + * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + * 1.2.1 3 10201 3.1.2.1 + * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + * 1.0.13 10 10013 10.so.0.1.0.13 + * 1.2.2 12 10202 12.so.0.1.2.2 + * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + * 1.2.3 12 10203 12.so.0.1.2.3 + * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 + * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + * 1.0.14 10 10014 10.so.0.1.0.14 + * 1.2.4 13 10204 12.so.0.1.2.4 + * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 + * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 + * 1.0.15 10 10015 10.so.0.1.0.15 + * 1.2.5 13 10205 12.so.0.1.2.5 + * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + * 1.0.16 10 10016 10.so.0.1.0.16 + * 1.2.6 13 10206 12.so.0.1.2.6 + * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + * 1.0.17rc1 10 10017 10.so.0.1.0.17rc1 + * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + * 1.0.17 10 10017 10.so.0.1.0.17 + * 1.2.7 13 10207 12.so.0.1.2.7 + * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 + * 1.0.18rc1-5 10 10018 10.so.0.1.0.18rc1-5 + * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + * 1.0.18 10 10018 10.so.0.1.0.18 + * 1.2.8 13 10208 12.so.0.1.2.8 + * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 + * 1.2.9beta4-11 13 10209 12.so.0.9[.0] + * 1.2.9rc1 13 10209 12.so.0.9[.0] + * 1.2.9 13 10209 12.so.0.9[.0] + * 1.2.10beta1-8 13 10210 12.so.0.10[.0] + * 1.2.10rc1-3 13 10210 12.so.0.10[.0] + * 1.2.10 13 10210 12.so.0.10[.0] + * 1.2.11beta1-4 13 10211 12.so.0.11[.0] + * 1.0.19rc1-5 10 10019 10.so.0.19[.0] + * 1.2.11rc1-5 13 10211 12.so.0.11[.0] + * 1.0.19 10 10019 10.so.0.19[.0] + * 1.2.11 13 10211 12.so.0.11[.0] + * 1.0.20 10 10020 10.so.0.20[.0] + * 1.2.12 13 10212 12.so.0.12[.0] + * 1.2.13beta1 13 10213 12.so.0.13[.0] + * 1.0.21 10 10021 10.so.0.21[.0] + * 1.2.13 13 10213 12.so.0.13[.0] + * 1.2.14beta1-2 13 10214 12.so.0.14[.0] + * 1.0.22rc1 10 10022 10.so.0.22[.0] + * 1.2.14rc1 13 10214 12.so.0.14[.0] + * 1.0.22 10 10022 10.so.0.22[.0] + * 1.2.14 13 10214 12.so.0.14[.0] + * 1.2.15beta1-6 13 10215 12.so.0.15[.0] + * 1.0.23rc1-5 10 10023 10.so.0.23[.0] + * 1.2.15rc1-5 13 10215 12.so.0.15[.0] + * 1.0.23 10 10023 10.so.0.23[.0] + * 1.2.15 13 10215 12.so.0.15[.0] + * 1.2.16beta1-2 13 10216 12.so.0.16[.0] + * 1.2.16rc1 13 10216 12.so.0.16[.0] + * 1.0.24 10 10024 10.so.0.24[.0] + * 1.2.16 13 10216 12.so.0.16[.0] + * 1.2.17beta1-2 13 10217 12.so.0.17[.0] + * 1.0.25rc1 10 10025 10.so.0.25[.0] + * 1.2.17rc1-3 13 10217 12.so.0.17[.0] + * 1.0.25 10 10025 10.so.0.25[.0] + * 1.2.17 13 10217 12.so.0.17[.0] + * 1.0.26 10 10026 10.so.0.26[.0] + * 1.2.18 13 10218 12.so.0.18[.0] + * 1.2.19beta1-31 13 10219 12.so.0.19[.0] + * 1.0.27rc1-6 10 10027 10.so.0.27[.0] + * 1.2.19rc1-6 13 10219 12.so.0.19[.0] + * 1.0.27 10 10027 10.so.0.27[.0] + * 1.2.19 13 10219 12.so.0.19[.0] + * 1.2.20beta01-04 13 10220 12.so.0.20[.0] + * 1.0.28rc1-6 10 10028 10.so.0.28[.0] + * 1.2.20rc1-6 13 10220 12.so.0.20[.0] + * 1.0.28 10 10028 10.so.0.28[.0] + * 1.2.20 13 10220 12.so.0.20[.0] + * + * Henceforth the source version will match the shared-library major + * and minor numbers; the shared-library major version number will be + * used for changes in backward compatibility, as it is intended. The + * PNG_LIBPNG_VER macro, which is not used within libpng but is available + * for applications, is an unsigned integer of the form xyyzz corresponding + * to the source version x.y.z (leading zeros in y and z). Beta versions + * were given the previous public release number plus a letter, until + * version 1.0.6j; from then on they were given the upcoming public + * release number plus "betaNN" or "rcN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as a W3C Recommendation and as an ISO Specification, + * defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001 +#define PNG_INFO_sBIT 0x0002 +#define PNG_INFO_cHRM 0x0004 +#define PNG_INFO_PLTE 0x0008 +#define PNG_INFO_tRNS 0x0010 +#define PNG_INFO_bKGD 0x0020 +#define PNG_INFO_hIST 0x0040 +#define PNG_INFO_pHYs 0x0080 +#define PNG_INFO_oFFs 0x0100 +#define PNG_INFO_tIME 0x0200 +#define PNG_INFO_pCAL 0x0400 +#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ +#define PNG_INFO_acTL 0x10000L +#define PNG_INFO_fcTL 0x20000L + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + png_uint_32 rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info FAR * png_row_infop; +typedef png_row_info FAR * FAR * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. + */ +typedef struct png_struct_def png_struct; +typedef png_struct FAR * png_structp; + +typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); +typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); +typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); +typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, + int)); +typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, + png_uint_32, int)); +#if defined(PNG_APNG_SUPPORTED) +typedef void (PNGAPI *png_progressive_frame_ptr) PNGARG((png_structp, + png_uint_32)); +#endif +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, + png_row_infop, png_bytep)); +#endif + +#if defined(PNG_USER_CHUNKS_SUPPORTED) +typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp)); +#endif +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* WRITE only */ + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t)); +typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); + +/* The structure that holds the information to read and write PNG files. + * The only people who need to care about what is inside of this are the + * people who will be modifying the library for their own special needs. + * It should NOT be accessed directly by an application, except to store + * the jmp_buf. + */ + +struct png_struct_def +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf jmpbuf; /* used in png_error */ +#endif + png_error_ptr error_fn; /* function for printing errors and aborting */ + png_error_ptr warning_fn; /* function for printing warnings */ + png_voidp error_ptr; /* user supplied struct for error functions */ + png_rw_ptr write_data_fn; /* function for writing output data */ + png_rw_ptr read_data_fn; /* function for reading input data */ + png_voidp io_ptr; /* ptr to application struct for I/O functions */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + png_user_transform_ptr read_user_transform_fn; /* user read transform */ +#endif + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_user_transform_ptr write_user_transform_fn; /* user write transform */ +#endif + +/* These were added in libpng-1.0.2 */ +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_voidp user_transform_ptr; /* user supplied struct for user transform */ + png_byte user_transform_depth; /* bit depth of user transformed pixels */ + png_byte user_transform_channels; /* channels in user transformed pixels */ +#endif +#endif + + png_uint_32 mode; /* tells us where we are in the PNG file */ + png_uint_32 flags; /* flags indicating various things to libpng */ + png_uint_32 transformations; /* which transformations to perform */ + + z_stream zstream; /* pointer to decompression structure (below) */ + png_bytep zbuf; /* buffer for zlib */ + png_size_t zbuf_size; /* size of zbuf */ + int zlib_level; /* holds zlib compression level */ + int zlib_method; /* holds zlib compression method */ + int zlib_window_bits; /* holds zlib compression window bits */ + int zlib_mem_level; /* holds zlib compression memory level */ + int zlib_strategy; /* holds zlib compression strategy */ + + png_uint_32 width; /* width of image in pixels */ + png_uint_32 height; /* height of image in pixels */ + png_uint_32 num_rows; /* number of rows in current pass */ + png_uint_32 usr_width; /* width of row at start of write */ + png_uint_32 rowbytes; /* size of row in bytes */ + png_uint_32 irowbytes; /* size of current interlaced row in bytes */ + png_uint_32 iwidth; /* width of current interlaced row in pixels */ + png_uint_32 row_number; /* current row in interlace pass */ + png_bytep prev_row; /* buffer to save previous (unfiltered) row */ + png_bytep row_buf; /* buffer to save current (unfiltered) row */ + png_bytep sub_row; /* buffer to save "sub" row when filtering */ + png_bytep up_row; /* buffer to save "up" row when filtering */ + png_bytep avg_row; /* buffer to save "avg" row when filtering */ + png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ + png_row_info row_info; /* used for transformation routines */ + + png_uint_32 idat_size; /* current IDAT size for read */ + png_uint_32 crc; /* current chunk CRC value */ + png_colorp palette; /* palette from the input file */ + png_uint_16 num_palette; /* number of color entries in palette */ + png_uint_16 num_trans; /* number of transparency values */ + png_byte chunk_name[5]; /* null-terminated name of current chunk */ + png_byte compression; /* file compression type (always 0) */ + png_byte filter; /* file filter type (always 0) */ + png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + png_byte pass; /* current interlace pass (0 - 6) */ + png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte color_type; /* color type of file */ + png_byte bit_depth; /* bit depth of file */ + png_byte usr_bit_depth; /* bit depth of users row */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte channels; /* number of channels in file */ + png_byte usr_channels; /* channels at start of write */ + png_byte sig_bytes; /* magic bytes read/written from start of file */ + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +#ifdef PNG_LEGACY_SUPPORTED + png_byte filler; /* filler byte for pixel expansion */ +#else + png_uint_16 filler; /* filler bytes for pixel expansion */ +#endif +#endif + +#if defined(PNG_bKGD_SUPPORTED) + png_byte background_gamma_type; +# ifdef PNG_FLOATING_POINT_SUPPORTED + float background_gamma; +# endif + png_color_16 background; /* background color in screen gamma space */ +#if defined(PNG_READ_GAMMA_SUPPORTED) + png_color_16 background_1; /* background normalized to gamma 1.0 */ +#endif +#endif /* PNG_bKGD_SUPPORTED */ + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) + png_flush_ptr output_flush_fn;/* Function for flushing output */ + png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows; /* number of rows written since last flush */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + int gamma_shift; /* number of "insignificant" bits 16-bit gamma */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + float gamma; /* file gamma value */ + float screen_gamma; /* screen gamma value (display_exponent) */ +#endif +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep gamma_table; /* gamma table for 8-bit depth files */ + png_bytep gamma_from_1; /* converts from 1.0 to screen */ + png_bytep gamma_to_1; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ + png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ + png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) + png_color_8 sig_bit; /* significant bits in each available channel */ +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift; /* shift for significant bit tranformation */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ + || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep trans; /* transparency values for paletted files */ + png_color_16 trans_values; /* transparency values for non-paletted files */ +#endif + + png_read_status_ptr read_row_fn; /* called after each row is decoded */ + png_write_status_ptr write_row_fn; /* called after each row is encoded */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn; /* called after header data fully read */ + png_progressive_row_ptr row_fn; /* called after each prog. row is decoded */ + png_progressive_end_ptr end_fn; /* called after image is complete */ + png_bytep save_buffer_ptr; /* current location in save_buffer */ + png_bytep save_buffer; /* buffer for previously read data */ + png_bytep current_buffer_ptr; /* current location in current_buffer */ + png_bytep current_buffer; /* buffer for recently used data */ + png_uint_32 push_length; /* size of current input chunk */ + png_uint_32 skip_length; /* bytes to skip in input data */ + png_size_t save_buffer_size; /* amount of data now in save_buffer */ + png_size_t save_buffer_max; /* total size of save_buffer */ + png_size_t buffer_size; /* total amount of available input data */ + png_size_t current_buffer_size; /* amount of data now in current_buffer */ + int process_mode; /* what push library is currently doing */ + int cur_palette; /* current push library palette index */ + +# if defined(PNG_TEXT_SUPPORTED) + png_size_t current_text_size; /* current size of text input data */ + png_size_t current_text_left; /* how much text left to read in input */ + png_charp current_text; /* current text chunk buffer */ + png_charp current_text_ptr; /* current location in current_text */ +# endif /* PNG_TEXT_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* for the Borland special 64K segment handler */ + png_bytepp offset_table_ptr; + png_bytep offset_table; + png_uint_16 offset_table_number; + png_uint_16 offset_table_count; + png_uint_16 offset_table_count_free; +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) + png_bytep palette_lookup; /* lookup table for dithering */ + png_bytep dither_index; /* index translation for palette files */ +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED) + png_uint_16p hist; /* histogram */ +#endif + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_byte heuristic_method; /* heuristic for row filter selection */ + png_byte num_prev_filters; /* number of weights for previous rows */ + png_bytep prev_filters; /* filter type(s) of previous row(s) */ + png_uint_16p filter_weights; /* weight(s) for previous line(s) */ + png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ + png_uint_16p filter_costs; /* relative filter calculation cost */ + png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) + png_charp time_buffer; /* String to hold RFC 1123 time text */ +#endif + +/* New members added in libpng-1.0.6 */ + +#ifdef PNG_FREE_ME_SUPPORTED + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ +#endif + +#if defined(PNG_USER_CHUNKS_SUPPORTED) + png_voidp user_chunk_ptr; + png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + int num_chunk_list; + png_bytep chunk_list; +#endif + +/* New members added in libpng-1.0.3 */ +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + png_byte rgb_to_gray_status; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff; + png_uint_16 rgb_to_gray_green_coeff; + png_uint_16 rgb_to_gray_blue_coeff; +#endif + +/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ + defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* changed from png_byte to png_uint_32 at version 1.2.0 */ +#ifdef PNG_1_0_X + png_byte mng_features_permitted; +#else + png_uint_32 mng_features_permitted; +#endif /* PNG_1_0_X */ +#endif + +/* New member added in libpng-1.0.7 */ +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_fixed_point int_gamma; +#endif + +/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) + png_byte filter_type; +#endif + +#if defined(PNG_1_0_X) +/* New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 */ + png_uint_32 row_buf_size; +#endif + +/* New members added in libpng-1.2.0 */ +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) +# if !defined(PNG_1_0_X) +# if defined(PNG_MMX_CODE_SUPPORTED) + png_byte mmx_bitdepth_threshold; + png_uint_32 mmx_rowbytes_threshold; +# endif + png_uint_32 asm_flags; +# endif +#endif + +/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +#ifdef PNG_USER_MEM_SUPPORTED + png_voidp mem_ptr; /* user supplied struct for mem functions */ + png_malloc_ptr malloc_fn; /* function for allocating memory */ + png_free_ptr free_fn; /* function for freeing memory */ +#endif + +/* New member added in libpng-1.0.13 and 1.2.0 */ + png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ + +#if defined(PNG_READ_DITHER_SUPPORTED) +/* The following three members were added at version 1.0.14 and 1.2.4 */ + png_bytep dither_sort; /* working sort array */ + png_bytep index_to_palette; /* where the original index currently is */ + /* in the palette */ + png_bytep palette_to_index; /* which original index points to this */ + /* palette color */ +#endif + +/* New members added in libpng-1.0.16 and 1.2.6 */ + png_byte compression_type; + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max; + png_uint_32 user_height_max; +#endif + +#if defined(PNG_APNG_SUPPORTED) + png_uint_32 apng_flags; + png_uint_32 next_seq_num; /* next fcTL/fdAT chunk sequence number */ + png_uint_32 first_frame_width; + png_uint_32 first_frame_height; + +#if defined(PNG_READ_APNG_SUPPORTED) + png_uint_32 num_frames_read; /* incremented after all image data of */ + /* a frame is read */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_frame_ptr frame_info_fn; /* frame info read callback */ + png_progressive_frame_ptr frame_end_fn; /* frame data read callback */ +#endif +#endif + +#if defined(PNG_WRITE_APNG_SUPPORTED) + png_uint_32 num_frames_to_write; + png_uint_32 num_frames_written; +#endif +#endif + +/* For png_struct.apng_flags: */ +#define PNG_FIRST_FRAME_HIDDEN 0x0001 + +/* dispose_op flags from inside fcTL */ +#define PNG_DISPOSE_OP_NONE 0x00 +#define PNG_DISPOSE_OP_BACKGROUND 0x01 +#define PNG_DISPOSE_OP_PREVIOUS 0x02 + +/* blend_op flags from inside fcTL */ +#define PNG_BLEND_OP_SOURCE 0x00 +#define PNG_BLEND_OP_OVER 0x01 + +/* New member added in libpng-1.0.25 and 1.2.17 */ +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + /* storage for unknown chunk that the library doesn't recognize. */ + png_unknown_chunk unknown_chunk; +#endif +}; + + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef png_structp version_1_2_20; + +typedef png_struct FAR * FAR * png_structpp; + +/* Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + */ + +/* Returns the version number of the library */ +extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, + int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, + png_size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num)); + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +extern PNG_EXPORT(png_structp,png_create_read_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +extern PNG_EXPORT(png_structp,png_create_write_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)); + +#ifdef PNG_WRITE_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_compression_buffer_size) + PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_WRITE_SUPPORTED +extern PNG_EXPORT(void,png_set_compression_buffer_size) + PNGARG((png_structp png_ptr, png_uint_32 size)); +#endif + +/* Reset the compression stream */ +extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_structp,png_create_read_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +extern PNG_EXPORT(png_structp,png_create_write_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +#endif + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_bytep data, png_size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); + +/* Allocate and initialize the info structure */ +extern PNG_EXPORT(png_infop,png_create_info_struct) + PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, + png_size_t png_info_struct_size)); + +/* Writes all the PNG information before the image. */ +extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read the information before the actual image data. */ +extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) +extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) + PNGARG((png_structp png_ptr, png_timep ptime)); +#endif + +#if !defined(_WIN32_WCE) +/* "time.h" functions are not supported on WindowsCE */ +#if defined(PNG_WRITE_tIME_SUPPORTED) +/* convert from a struct tm to png_time */ +extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, + struct tm FAR * ttime)); + +/* convert from time_t to png_time. Uses gmtime() */ +extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, + time_t ttime)); +#endif /* PNG_WRITE_tIME_SUPPORTED */ +#endif /* _WIN32_WCE */ + +#if defined(PNG_READ_EXPAND_SUPPORTED) +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); +#if !defined(PNG_1_0_X) +extern PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp + png_ptr)); +#endif +extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Deprecated */ +extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr)); +#endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +/* Expand the grayscale to 24-bit RGB if necessary. */ +extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +/* Reduce RGB to grayscale. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, + int error_action, double red, double green )); +#endif +extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green )); +extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp + png_ptr)); +#endif + +extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, + png_colorp palette)); + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ +extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +#define PNG_FILLER_BEFORE 0 +#define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ +#if !defined(PNG_1_0_X) +extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +#endif +#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, + png_color_8p true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. */ +extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) +/* Handle alpha and tRNS by replacing with a background color. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)); +#endif +#define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +#define PNG_BACKGROUND_GAMMA_SCREEN 1 +#define PNG_BACKGROUND_GAMMA_FILE 2 +#define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +/* strip the second byte of information from a 16-bit depth file. */ +extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +/* Turn on dithering, and reduce the palette to the number of colors available. */ +extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_uint_16p histogram, int full_dither)); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) +/* Handle gamma correction. Screen_gamma=(display_exponent) */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, + double screen_gamma, double default_file_gamma)); +#endif +#endif + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* Permit or disallow empty PLTE (0: not permitted, 1: permitted) */ +/* Deprecated and will be removed. Use png_permit_mng_features() instead. */ +extern PNG_EXPORT(void,png_permit_empty_plte) PNGARG((png_structp png_ptr, + int empty_plte_permitted)); +#endif +#endif + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +/* Set how many lines between output flushes - 0 for no flushing */ +extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); +#endif + +/* optional update palette with requested transformations */ +extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); + +/* optional call to update the users info structure */ +extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read one or more rows of image data. */ +extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read a row of data. */ +extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, + png_bytep row, + png_bytep display_row)); +#endif + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read the whole image into memory at once. */ +extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, + png_bytepp image)); +#endif + +/* write a row of image data */ +extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, + png_bytep row)); + +/* write a few rows of image data */ +extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_uint_32 num_rows)); + +/* write the image data */ +extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, + png_bytepp image)); + +#if defined(PNG_WRITE_APNG_SUPPORTED) +extern PNG_EXPORT (void,png_write_frame_head) PNGARG((png_structp png_ptr, + png_infop png_info, png_bytepp row_pointers, + png_uint_32 width, png_uint_32 height, + png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, + png_byte blend_op)); + +extern PNG_EXPORT (void,png_write_frame_tail) PNGARG((png_structp png_ptr, + png_infop png_info)); +#endif + +/* writes the end of the PNG file. */ +extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read the end of the PNG file. */ +extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +/* free any memory associated with the png_info_struct */ +extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, + png_infopp info_ptr_ptr)); + +/* free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp + png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* free all memory used by the read (old method - NOT DLL EXPORTED) */ +extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr, + png_infop end_info_ptr)); + +/* free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_write_struct) + PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); + +/* free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ +extern void png_write_destroy PNGARG((png_structp png_ptr)); + +/* set the libpng method of handling chunk CRC errors */ +extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, + int crit_action, int ancil_action)); + +/* Values for png_set_crc_action() to say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, + int filters)); + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ + PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */ +/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ + * defines, either the default (minimum-sum-of-absolute-differences), or + * the experimental method (weighted-minimum-sum-of-absolute-differences). + * + * Weights are factors >= 1.0, indicating how important it is to keep the + * filter type consistent between rows. Larger numbers mean the current + * filter is that many times as likely to be the same as the "num_weights" + * previous filters. This is cumulative for each previous row with a weight. + * There needs to be "num_weights" values in "filter_weights", or it can be + * NULL if the weights aren't being specified. Weights have no influence on + * the selection of the first row filter. Well chosen weights can (in theory) + * improve the compression for a given image. + * + * Costs are factors >= 1.0 indicating the relative decoding costs of a + * filter type. Higher costs indicate more decoding expense, and are + * therefore less likely to be selected over a filter with lower computational + * costs. There needs to be a value in "filter_costs" for each valid filter + * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't + * setting the costs. Costs try to improve the speed of decompression without + * unduly increasing the compressed image size. + * + * A negative weight or cost indicates the default value is to be used, and + * values in the range [0.0, 1.0) indicate the value is to remain unchanged. + * The default values for both weights and costs are currently 1.0, but may + * change if good general weighting/cost heuristics can be found. If both + * the weights and costs are set to 1.0, this degenerates the WEIGHTED method + * to the UNWEIGHTED method, but with added encoding time/computation. + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, + int heuristic_method, int num_weights, png_doublep filter_weights, + png_doublep filter_costs)); +#endif +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +/* Heuristic used for row filter selection. These defines should NOT be + * changed. + */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, + int level)); + +extern PNG_EXPORT(void,png_set_compression_mem_level) + PNGARG((png_structp png_ptr, int mem_level)); + +extern PNG_EXPORT(void,png_set_compression_strategy) + PNGARG((png_structp png_ptr, int strategy)); + +extern PNG_EXPORT(void,png_set_compression_window_bits) + PNGARG((png_structp png_ptr, int window_bits)); + +extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, + int method)); + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng.txt for + * more information. + */ + +#if !defined(PNG_NO_STDIO) +/* Initialize the input/output for the PNG file to the default functions. */ +extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + */ +extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, + png_read_status_ptr read_row_fn)); + +extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr read_user_transform_fn)); +#endif + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr write_user_transform_fn)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp + png_ptr, png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) + PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp + png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr, + png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn)); +#if defined(PNG_READ_APNG_SUPPORTED) +extern PNG_EXPORT(void,png_set_progressive_frame_fn) PNGARG((png_structp png_ptr, + png_progressive_frame_ptr frame_info_fn, + png_progressive_frame_ptr frame_end_fn)); +#endif + +/* returns the user pointer associated with the push read functions */ +extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) + PNGARG((png_structp png_ptr)); + +/* function to be called when data becomes available */ +extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); + +/* function that combines rows. Not very much different than the + * png_combine_row() call. Is this even used????? + */ +extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, + png_bytep old_row, png_bytep new_row)); +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, + png_uint_32 size)); + +#if defined(PNG_1_0_X) +# define png_malloc_warn png_malloc +#else +/* Added at libpng version 1.2.4 */ +extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, + png_uint_32 size)); +#endif + +/* frees a pointer allocated by png_malloc() */ +extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); + +#if defined(PNG_1_0_X) +/* Function to allocate memory for zlib. */ +extern PNG_EXPORT(voidpf,png_zalloc) PNGARG((voidpf png_ptr, uInt items, + uInt size)); + +/* Function to free memory for zlib */ +extern PNG_EXPORT(void,png_zfree) PNGARG((voidpf png_ptr, voidpf ptr)); +#endif + +/* Free data that was allocated internally */ +extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 free_me, int num)); +#ifdef PNG_FREE_ME_SUPPORTED +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application */ +extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, + png_infop info_ptr, int freer, png_uint_32 mask)); +#endif +/* assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008 +#define PNG_FREE_ICCP 0x0010 +#define PNG_FREE_SPLT 0x0020 +#define PNG_FREE_ROWS 0x0040 +#define PNG_FREE_PCAL 0x0080 +#define PNG_FREE_SCAL 0x0100 +#define PNG_FREE_UNKN 0x0200 +#define PNG_FREE_LIST 0x0400 +#define PNG_FREE_PLTE 0x1000 +#define PNG_FREE_TRNS 0x2000 +#define PNG_FREE_TEXT 0x4000 +#define PNG_FREE_ALL 0x7fff +#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, + png_uint_32 size)); +extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, + png_voidp ptr)); +#endif + +extern PNG_EXPORT(png_voidp,png_memcpy_check) PNGARG((png_structp png_ptr, + png_voidp s1, png_voidp s2, png_uint_32 size)); + +extern PNG_EXPORT(png_voidp,png_memset_check) PNGARG((png_structp png_ptr, + png_voidp s1, int value, png_uint_32 size)); + +#if defined(USE_FAR_KEYWORD) /* memory model conversion function */ +extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr, + int check)); +#endif /* USE_FAR_KEYWORD */ + +#ifndef PNG_NO_ERROR_TEXT +/* Fatal error in PNG image of libpng - can't continue */ +extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)); + +/* The same, but the chunk name is prepended to the error string. */ +extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)); +#else +/* Fatal error in PNG image of libpng - can't continue */ +extern PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr)); +#endif + +#ifndef PNG_NO_WARNINGS +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_READ_SUPPORTED +/* Non-fatal error in libpng, chunk name is prepended to message. */ +extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); +#endif /* PNG_READ_SUPPORTED */ +#endif /* PNG_NO_WARNINGS */ + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +extern PNG_EXPORT(png_uint_32,png_get_rowbytes) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +/* Returns row_pointers, which is an array of pointers to scanlines that was +returned from png_read_png(). */ +extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, +png_infop info_ptr)); +/* Set row_pointers, which is an array of pointers to scanlines for use +by png_write_png(). */ +extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image height in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image bit_depth. */ +extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image color_type. */ +extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image filter_type. */ +extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image interlace_type. */ +extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image compression_type. */ +extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +#endif + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +/* Returns pointer to signature string read from PNG header */ +extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#if defined(PNG_bKGD_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p *background)); +#endif + +#if defined(PNG_bKGD_SUPPORTED) +extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p background)); +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point + *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point + *int_blue_x, png_fixed_point *int_blue_y)); +#endif +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double white_x, double white_y, double red_x, + double red_y, double green_x, double green_y, double blue_x, double blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *file_gamma)); +#endif +extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_file_gamma)); +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double file_gamma)); +#endif +extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); +#endif + +#if defined(PNG_hIST_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p *hist)); +#endif + +#if defined(PNG_hIST_SUPPORTED) +extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p hist)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#if defined(PNG_oFFs_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#if defined(PNG_oFFs_SUPPORTED) +extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#if defined(PNG_pCAL_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, + int *type, int *nparams, png_charp *units, png_charpp *params)); +#endif + +#if defined(PNG_pCAL_SUPPORTED) +extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_charp units, png_charpp params)); +#endif + +#if defined(PNG_pHYs_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif + +#if defined(PNG_pHYs_SUPPORTED) +extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp *palette, int *num_palette)); + +extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp palette, int num_palette)); + +#if defined(PNG_sBIT_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p *sig_bit)); +#endif + +#if defined(PNG_sBIT_SUPPORTED) +extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p sig_bit)); +#endif + +#if defined(PNG_sRGB_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *intent)); +#endif + +#if defined(PNG_sRGB_SUPPORTED) +extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +#endif + +#if defined(PNG_iCCP_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen)); + /* Note to maintainer: profile should be png_bytepp */ +#endif + +#if defined(PNG_iCCP_SUPPORTED) +extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#if defined(PNG_sPLT_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tpp entries)); +#endif + +#if defined(PNG_sPLT_SUPPORTED) +extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries)); +#endif + +#if defined(PNG_TEXT_SUPPORTED) +/* png_get_text also returns the number of text chunks in *num_text */ +extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* + * Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#if defined(PNG_TEXT_SUPPORTED) +extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); +#endif + +#if defined(PNG_tIME_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep *mod_time)); +#endif + +#if defined(PNG_tIME_SUPPORTED) +extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep mod_time)); +#endif + +#if defined(PNG_tRNS_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep *trans, int *num_trans, + png_color_16p *trans_values)); +#endif + +#if defined(PNG_tRNS_SUPPORTED) +extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep trans, int num_trans, + png_color_16p trans_values)); +#endif + +#if defined(PNG_tRNS_SUPPORTED) +#endif + +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, double *width, double *height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED */ + +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, double width, double height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ + +#if defined(PNG_APNG_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_acTL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays)); +extern PNG_EXPORT(png_uint_32,png_set_acTL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays)); +extern PNG_EXPORT(png_uint_32,png_get_num_frames) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_num_plays) + PNGARG((png_structp png_ptr, png_infop info_ptr)); + +extern PNG_EXPORT(png_uint_32,png_get_next_frame_fcTL) + PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 *width, + png_uint_32 *height, png_uint_32 *x_offset, png_uint_32 *y_offset, + png_uint_16 *delay_num, png_uint_16 *delay_den, png_byte *dispose_op, + png_byte *blend_op)); +extern PNG_EXPORT(png_uint_32,png_set_next_frame_fcTL) + PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 width, + png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, + png_byte blend_op)); +extern PNG_EXPORT(void,png_ensure_fcTL_is_valid) + PNGARG((png_structp png_ptr, + png_uint_32 width, png_uint_32 height, + png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, + png_byte dispose_op, png_byte blend_op)); +extern PNG_EXPORT(png_uint_32,png_get_next_frame_width) + PNGARG((png_structp png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_next_frame_height) + PNGARG((png_structp png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_next_frame_x_offset) + PNGARG((png_structp png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_next_frame_y_offset) + PNGARG((png_structp png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_16,png_get_next_frame_delay_num) + PNGARG((png_structp png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_16,png_get_next_frame_delay_den) + PNGARG((png_structp png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_byte,png_get_next_frame_dispose_op) + PNGARG((png_structp png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_byte,png_get_next_frame_blend_op) + PNGARG((png_structp png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_byte,png_get_first_frame_is_hidden) + PNGARG((png_structp png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32,png_set_first_frame_is_hidden) + PNGARG((png_structp png_ptr, png_infop info_ptr, png_byte is_hidden)); +#endif /* PNG_APNG_SUPPORTED */ + +#if defined(PNG_READ_APNG_SUPPORTED) +extern PNG_EXPORT(void,png_read_frame_head) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +/* provide a list of chunks and how they are to be handled, if the built-in + handling or default unknown chunk handling is not desired. Any chunks not + listed will be handled in the default manner. The IHDR and IEND chunks + must not be listed. + keep = 0: follow default behaviour + = 1: do not keep + = 2: keep only if safe-to-copy + = 3: keep even if unsafe-to-copy +*/ +extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp + png_ptr, int keep, png_bytep chunk_list, int num_chunks)); +extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); +extern PNG_EXPORT(void, png_set_unknown_chunk_location) + PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); +extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp + png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); +#endif +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep + chunk_name)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + If you need to turn it off for a chunk that your application has freed, + you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */ +extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, + png_infop info_ptr, int mask)); + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +/* The "params" pointer is currently not used and is for future expansion. */ +extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +#endif + +/* Define PNG_DEBUG at compile time for debugging information. Higher + * numbers for PNG_DEBUG mean more debugging information. This has + * only been added since version 0.95 so it is not implemented throughout + * libpng yet, but more support will be added as needed. + */ +#ifdef PNG_DEBUG +#if (PNG_DEBUG > 0) +#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) +#include +#if (PNG_DEBUG > 1) +#define png_debug(l,m) _RPT0(_CRT_WARN,m) +#define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m,p1) +#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m,p1,p2) +#endif +#else /* PNG_DEBUG_FILE || !_MSC_VER */ +#ifndef PNG_DEBUG_FILE +#define PNG_DEBUG_FILE stderr +#endif /* PNG_DEBUG_FILE */ +#if (PNG_DEBUG > 1) +#define png_debug(l,m) \ +{ \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ +} +#define png_debug1(l,m,p1) \ +{ \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ +} +#define png_debug2(l,m,p1,p2) \ +{ \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ +} +#endif /* (PNG_DEBUG > 1) */ +#endif /* _MSC_VER */ +#endif /* (PNG_DEBUG > 0) */ +#endif /* PNG_DEBUG */ +#ifndef png_debug +#define png_debug(l, m) +#endif +#ifndef png_debug1 +#define png_debug1(l, m, p1) +#endif +#ifndef png_debug2 +#define png_debug2(l, m, p1, p2) +#endif + +extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp + png_ptr, png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 + +/* Added to version 1.2.0 */ +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) +#if defined(PNG_MMX_CODE_SUPPORTED) +#define PNG_ASM_FLAG_MMX_SUPPORT_COMPILED 0x01 /* not user-settable */ +#define PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU 0x02 /* not user-settable */ +#define PNG_ASM_FLAG_MMX_READ_COMBINE_ROW 0x04 +#define PNG_ASM_FLAG_MMX_READ_INTERLACE 0x08 +#define PNG_ASM_FLAG_MMX_READ_FILTER_SUB 0x10 +#define PNG_ASM_FLAG_MMX_READ_FILTER_UP 0x20 +#define PNG_ASM_FLAG_MMX_READ_FILTER_AVG 0x40 +#define PNG_ASM_FLAG_MMX_READ_FILTER_PAETH 0x80 +#define PNG_ASM_FLAGS_INITIALIZED 0x80000000 /* not user-settable */ + +#define PNG_MMX_READ_FLAGS ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ + | PNG_ASM_FLAG_MMX_READ_INTERLACE \ + | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ + | PNG_ASM_FLAG_MMX_READ_FILTER_UP \ + | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ + | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ) +#define PNG_MMX_WRITE_FLAGS ( 0 ) + +#define PNG_MMX_FLAGS ( PNG_ASM_FLAG_MMX_SUPPORT_COMPILED \ + | PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU \ + | PNG_MMX_READ_FLAGS \ + | PNG_MMX_WRITE_FLAGS ) + +#define PNG_SELECT_READ 1 +#define PNG_SELECT_WRITE 2 +#endif /* PNG_MMX_CODE_SUPPORTED */ + +#if !defined(PNG_1_0_X) +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_mmx_flagmask) + PNGARG((int flag_select, int *compilerID)); + +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_asm_flagmask) + PNGARG((int flag_select)); + +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_asm_flags) + PNGARG((png_structp png_ptr)); + +/* pngget.c */ +extern PNG_EXPORT(png_byte,png_get_mmx_bitdepth_threshold) + PNGARG((png_structp png_ptr)); + +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_mmx_rowbytes_threshold) + PNGARG((png_structp png_ptr)); + +/* pngset.c */ +extern PNG_EXPORT(void,png_set_asm_flags) + PNGARG((png_structp png_ptr, png_uint_32 asm_flags)); + +/* pngset.c */ +extern PNG_EXPORT(void,png_set_mmx_thresholds) + PNGARG((png_structp png_ptr, png_byte mmx_bitdepth_threshold, + png_uint_32 mmx_rowbytes_threshold)); + +#endif /* PNG_1_0_X */ + +#if !defined(PNG_1_0_X) +/* png.c, pnggccrd.c, or pngvcrd.c */ +extern PNG_EXPORT(int,png_mmx_support) PNGARG((void)); +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp + png_ptr, png_uint_32 strip_mode)); +#endif + +#endif /* PNG_1_0_X */ + +/* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp + png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); +extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp + png_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp + png_ptr)); +#endif + +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project defs */ + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 - \ + (png_uint_16)(alpha)) + (png_uint_16)128); \ + (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } + +# define png_composite_16(composite, fg, alpha, bg) \ + { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(png_uint_32)(65535L - \ + (png_uint_32)(alpha)) + (png_uint_32)32768L); \ + (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } + +#else /* standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + (png_uint_16)127) / 255) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ + (png_uint_32)32767) / (png_uint_32)65535L) + +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ + +/* Inline macros to do direct reads of bytes from the input buffer. These + * require that you are using an architecture that uses PNG byte ordering + * (MSB first) and supports unaligned data storage. I think that PowerPC + * in big-endian mode and 680x0 are the only ones that will support this. + * The x86 line of processors definitely do not. The png_get_int_32() + * routine also assumes we are using two's complement format for negative + * values, which is almost certainly true. + */ +#if defined(PNG_READ_BIG_ENDIAN_SUPPORTED) +# define png_get_uint_32(buf) ( *((png_uint_32p) (buf))) +# define png_get_uint_16(buf) ( *((png_uint_16p) (buf))) +# define png_get_int_32(buf) ( *((png_int_32p) (buf))) +#else +extern PNG_EXPORT(png_uint_32,png_get_uint_32) PNGARG((png_bytep buf)); +extern PNG_EXPORT(png_uint_16,png_get_uint_16) PNGARG((png_bytep buf)); +extern PNG_EXPORT(png_int_32,png_get_int_32) PNGARG((png_bytep buf)); +#endif /* !PNG_READ_BIG_ENDIAN_SUPPORTED */ +extern PNG_EXPORT(png_uint_32,png_get_uint_31) + PNGARG((png_structp png_ptr, png_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). + */ +extern PNG_EXPORT(void,png_save_uint_32) + PNGARG((png_bytep buf, png_uint_32 i)); +extern PNG_EXPORT(void,png_save_int_32) + PNGARG((png_bytep buf, png_int_32 i)); + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +extern PNG_EXPORT(void,png_save_uint_16) + PNGARG((png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ + +/* ************************************************************************* */ + +/* These next functions are used internally in the code. They generally + * shouldn't be used unless you are writing code to add or replace some + * functionality in libpng. More information about most functions can + * be found in the files where the functions are located. + */ + + +/* Various modes of operation, that are visible to applications because + * they are used for unknown chunk location. + */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_HAVE_IDAT 0x04 +#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ +#define PNG_HAVE_IEND 0x10 + +#if defined(PNG_INTERNAL) + +/* More modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. + */ +#define PNG_HAVE_gAMA 0x20 +#define PNG_HAVE_cHRM 0x40 +#define PNG_HAVE_sRGB 0x80 +#define PNG_HAVE_CHUNK_HEADER 0x100 +#define PNG_WROTE_tIME 0x200 +#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 +#define PNG_BACKGROUND_IS_GRAY 0x800 +#define PNG_HAVE_PNG_SIGNATURE 0x1000 +#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ +#define PNG_HAVE_acTL 0x4000 +#define PNG_HAVE_fcTL 0x8000L + +/* flags for the transformations the PNG library does on the image data */ +#define PNG_BGR 0x0001 +#define PNG_INTERLACE 0x0002 +#define PNG_PACK 0x0004 +#define PNG_SHIFT 0x0008 +#define PNG_SWAP_BYTES 0x0010 +#define PNG_INVERT_MONO 0x0020 +#define PNG_DITHER 0x0040 +#define PNG_BACKGROUND 0x0080 +#define PNG_BACKGROUND_EXPAND 0x0100 + /* 0x0200 unused */ +#define PNG_16_TO_8 0x0400 +#define PNG_RGBA 0x0800 +#define PNG_EXPAND 0x1000 +#define PNG_GAMMA 0x2000 +#define PNG_GRAY_TO_RGB 0x4000 +#define PNG_FILLER 0x8000L +#define PNG_PACKSWAP 0x10000L +#define PNG_SWAP_ALPHA 0x20000L +#define PNG_STRIP_ALPHA 0x40000L +#define PNG_INVERT_ALPHA 0x80000L +#define PNG_USER_TRANSFORM 0x100000L +#define PNG_RGB_TO_GRAY_ERR 0x200000L +#define PNG_RGB_TO_GRAY_WARN 0x400000L +#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ + /* 0x800000L Unused */ +#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +/* flags for png_create_struct */ +#define PNG_STRUCT_PNG 0x0001 +#define PNG_STRUCT_INFO 0x0002 + +/* Scaling factor for filter heuristic weighting calculations */ +#define PNG_WEIGHT_SHIFT 8 +#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) +#define PNG_COST_SHIFT 3 +#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) + +/* flags for the png_ptr->flags rather than declaring a byte for each one */ +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 +#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 +#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 +#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 +#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 +#define PNG_FLAG_ZLIB_FINISHED 0x0020 +#define PNG_FLAG_ROW_INIT 0x0040 +#define PNG_FLAG_FILLER_AFTER 0x0080 +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 +#define PNG_FLAG_FREE_PLTE 0x1000 +#define PNG_FLAG_FREE_TRNS 0x2000 +#define PNG_FLAG_FREE_HIST 0x4000 +#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L +#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L +#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L +#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */ +#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */ + /* 0x800000L unused */ + /* 0x1000000L unused */ + /* 0x2000000L unused */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ + PNG_FLAG_CRC_ANCILLARY_NOWARN) + +#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ + PNG_FLAG_CRC_CRITICAL_IGNORE) + +#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ + PNG_FLAG_CRC_CRITICAL_MASK) + +/* save typing and make code easier to understand */ + +#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ + abs((int)((c1).green) - (int)((c2).green)) + \ + abs((int)((c1).blue) - (int)((c2).blue))) + +/* Added to libpng-1.2.6 JB */ +#define PNG_ROWBYTES(pixel_bits, width) \ + ((pixel_bits) >= 8 ? \ + ((width) * (((png_uint_32)(pixel_bits)) >> 3)) : \ + (( ((width) * ((png_uint_32)(pixel_bits))) + 7) >> 3) ) + +/* PNG_OUT_OF_RANGE returns true if value is outside the range + ideal-delta..ideal+delta. Each argument is evaluated twice. + "ideal" and "delta" should be constants, normally simple + integers, "value" a variable. Added to libpng-1.2.6 JB */ +#define PNG_OUT_OF_RANGE(value, ideal, delta) \ + ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) + +/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */ +#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) +/* place to hold the signature string for a PNG file. */ +#ifdef PNG_USE_GLOBAL_ARRAYS + PNG_EXPORT_VAR (PNG_CONST png_byte FARDATA) png_sig[8]; +#else +#endif +#endif /* PNG_NO_EXTERN */ + +/* Constant strings for known chunk types. If you need to add a chunk, + * define the name here, and add an invocation of the macro in png.c and + * wherever it's needed. + */ +#define PNG_IHDR png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} +#define PNG_IDAT png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} +#define PNG_IEND png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} +#define PNG_PLTE png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'} +#define PNG_bKGD png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'} +#define PNG_cHRM png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'} +#define PNG_gAMA png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'} +#define PNG_hIST png_byte png_hIST[5] = {104, 73, 83, 84, '\0'} +#define PNG_iCCP png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} +#define PNG_iTXt png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'} +#define PNG_oFFs png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'} +#define PNG_pCAL png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'} +#define PNG_sCAL png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'} +#define PNG_pHYs png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'} +#define PNG_sBIT png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'} +#define PNG_sPLT png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'} +#define PNG_sRGB png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'} +#define PNG_tEXt png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'} +#define PNG_tIME png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} +#define PNG_tRNS png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} +#define PNG_zTXt png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} +#define PNG_acTL png_byte png_acTL[5] = { 97, 99, 84, 76, '\0'} +#define PNG_fcTL png_byte png_fcTL[5] = {102, 99, 84, 76, '\0'} +#define PNG_fdAT png_byte png_fdAT[5] = {102, 100, 65, 84, '\0'} + +#ifdef PNG_USE_GLOBAL_ARRAYS +PNG_EXPORT_VAR (png_byte FARDATA) png_IHDR[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_IDAT[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_IEND[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_PLTE[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_bKGD[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_cHRM[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_gAMA[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_hIST[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_iCCP[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_iTXt[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_oFFs[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_pCAL[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_sCAL[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_pHYs[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_sBIT[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_sPLT[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_sRGB[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_tEXt[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_tIME[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_tRNS[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_zTXt[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_acTL[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_fcTL[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_fdAT[5]; +#endif /* PNG_USE_GLOBAL_ARRAYS */ + +extern PNG_EXPORT(void,png_read_init_3) PNGARG((png_structpp ptr_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size)); +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +extern PNG_EXPORT(void,png_read_init_2) PNGARG((png_structp png_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); +#endif + +extern PNG_EXPORT(void,png_write_init_3) PNGARG((png_structpp ptr_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size)); +extern PNG_EXPORT(void,png_write_init_2) PNGARG((png_structp png_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); + +/* Allocate memory for an internal libpng struct */ +PNG_EXTERN png_voidp png_create_struct PNGARG((int type)); + +/* Free memory from internal libpng struct */ +PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); + +PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr + malloc_fn, png_voidp mem_ptr)); +PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, + png_free_ptr free_fn, png_voidp mem_ptr)); + +/* Free any memory that info_ptr points to and reset struct. */ +PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_1_0_X +/* Function to allocate memory for zlib. */ +PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size)); + +/* Function to free memory for zlib */ +PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); + +#ifdef PNG_SIZE_T +/* Function to convert a sizeof an item to png_sizeof item */ + PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); +#endif + +/* Next four functions are used internally as callbacks. PNGAPI is required + * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3. */ + +PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); +#endif + +PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +#if !defined(PNG_NO_STDIO) +PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr)); +#endif +#endif +#else /* PNG_1_0_X */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); +#endif +#endif /* PNG_1_0_X */ + +/* Reset the CRC variable */ +PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); + +/* Write the "data" buffer to whatever output you are using. */ +PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read data from whatever input you are using into the "data" buffer */ +PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read bytes into buf, and update png_ptr->crc */ +PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, + png_size_t length)); + +/* Decompress data in a chunk that uses compression */ +#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ + defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) +PNG_EXTERN png_charp png_decompress_chunk PNGARG((png_structp png_ptr, + int comp_type, png_charp chunkdata, png_size_t chunklength, + png_size_t prefix_length, png_size_t *data_length)); +#endif + +/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ +PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); + +/* Read the CRC from the file and compare it to the libpng calculated CRC */ +PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); + +/* Calculate the CRC over a section of data. Note that we are only + * passing a maximum of 64K on systems that have this as a memory limit, + * since this is the maximum buffer size we can specify. + */ +PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr, + png_size_t length)); + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); +#endif + +/* simple function to write the signature */ +PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr)); + +/* write various chunks */ + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. + */ +PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, + png_uint_32 height, + int bit_depth, int color_type, int compression_method, int filter_method, + int interlace_method)); + +PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette, + png_uint_32 num_pal)); + +PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); + +#if defined(PNG_WRITE_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, png_fixed_point + file_gamma)); +#endif +#endif + +#if defined(PNG_WRITE_sBIT_SUPPORTED) +PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit, + int color_type)); +#endif + +#if defined(PNG_WRITE_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr, + double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif +#endif + +#if defined(PNG_WRITE_sRGB_SUPPORTED) +PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, + int intent)); +#endif + +#if defined(PNG_WRITE_iCCP_SUPPORTED) +PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, + png_charp name, int compression_type, + png_charp profile, int proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#if defined(PNG_WRITE_sPLT_SUPPORTED) +PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, + png_sPLT_tp palette)); +#endif + +#if defined(PNG_WRITE_tRNS_SUPPORTED) +PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans, + png_color_16p values, int number, int color_type)); +#endif + +#if defined(PNG_WRITE_bKGD_SUPPORTED) +PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, + png_color_16p values, int color_type)); +#endif + +#if defined(PNG_WRITE_hIST_SUPPORTED) +PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist, + int num_hist)); +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, + png_charp key, png_charpp new_key)); +#endif + +#if defined(PNG_WRITE_tEXt_SUPPORTED) +PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len)); +#endif + +#if defined(PNG_WRITE_zTXt_SUPPORTED) +PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len, int compression)); +#endif + +#if defined(PNG_WRITE_iTXt_SUPPORTED) +PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, + int compression, png_charp key, png_charp lang, png_charp lang_key, + png_charp text)); +#endif + +#if defined(PNG_TEXT_SUPPORTED) /* Added at version 1.0.14 and 1.2.4 */ +PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); +#endif + +#if defined(PNG_WRITE_oFFs_SUPPORTED) +PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, + png_int_32 x_offset, png_int_32 y_offset, int unit_type)); +#endif + +#if defined(PNG_WRITE_pCAL_SUPPORTED) +PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, + png_int_32 X0, png_int_32 X1, int type, int nparams, + png_charp units, png_charpp params)); +#endif + +#if defined(PNG_WRITE_pHYs_SUPPORTED) +PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, + png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, + int unit_type)); +#endif + +#if defined(PNG_WRITE_tIME_SUPPORTED) +PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, + png_timep mod_time)); +#endif + +#if defined(PNG_WRITE_sCAL_SUPPORTED) +#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) +PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr, + int unit, double width, double height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, + int unit, png_charp width, png_charp height)); +#endif +#endif +#endif + +#if defined(PNG_WRITE_APNG_SUPPORTED) +PNG_EXTERN void png_write_acTL PNGARG((png_structp png_ptr, + png_uint_32 num_frames, png_uint_32 num_plays)); + +PNG_EXTERN void png_write_fcTL PNGARG((png_structp png_ptr, + png_uint_32 width, png_uint_32 height, + png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, + png_byte dispose_op, png_byte blend_op)); +#endif + +/* Called when finished processing a row of data */ +PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); + +/* Internal use only. Called before first row of data */ +PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); + +#if defined(PNG_READ_GAMMA_SUPPORTED) +PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr)); +#endif + +/* combine a row of data, dealing with alpha, etc. if requested */ +PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, + int mask)); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) +/* expand an interlaced row */ +/* OLD pre-1.0.9 interface: +PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass, png_uint_32 transformations)); + */ +PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); +#endif + +/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* grab pixels out of a row for an interlaced pass */ +PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass)); +#endif + +/* unfilter a row */ +PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, + png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter)); + +/* Choose the best filter to use and filter the row data */ +PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, + png_row_infop row_info)); + +/* Write out the filtered row. */ +PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, + png_bytep filtered_row)); +/* finish a row while reading, dealing with interlacing passes, etc. */ +PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); + +/* initialize the row buffers, etc. */ +PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); +/* optional call to update the users info structure */ +PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#if defined(PNG_READ_APNG_SUPPORTED) +/* private, reset some things to become ready for reading next frame */ +PNG_EXTERN void png_read_reset PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_read_reinit PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_progressive_read_reset PNGARG((png_structp png_ptr)); +#endif +#if defined(PNG_WRITE_APNG_SUPPORTED) +/* private, reset some things to become ready for writing next frame */ +PNG_EXTERN void png_write_reset PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_write_reinit PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 width, png_uint_32 height)); +#endif + +/* these are the functions that do the transformations */ +#if defined(PNG_READ_FILLER_SUPPORTED) +PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 filler, png_uint_32 flags)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 flags)); +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) +PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop + row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) +PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) +PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p sig_bits)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +PNG_EXTERN void png_do_dither PNGARG((png_row_infop row_info, + png_bytep row, png_bytep palette_lookup, png_bytep dither_lookup)); + +# if defined(PNG_CORRECT_PALETTE_SUPPORTED) +PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette)); +# endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_WRITE_PACK_SUPPORTED) +PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 bit_depth)); +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) +PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p bit_depth)); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) +#if defined(PNG_READ_GAMMA_SUPPORTED) +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background, + png_color_16p background_1, + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, + png_uint_16pp gamma_16_to_1, int gamma_shift)); +#else +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background)); +#endif +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) +PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row, + png_bytep gamma_table, png_uint_16pp gamma_16_table, + int gamma_shift)); +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) +PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, + png_bytep row, png_colorp palette, png_bytep trans, int num_trans)); +PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, + png_bytep row, png_color_16p trans_value)); +#endif + +/* The following decodes the appropriate chunks, and does error correction, + * then calls the appropriate callback for the chunk if it is valid. + */ + +/* decode the IHDR chunk */ +PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); + +#if defined(PNG_READ_bKGD_SUPPORTED) +PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_cHRM_SUPPORTED) +PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_gAMA_SUPPORTED) +PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_hIST_SUPPORTED) +PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_iCCP_SUPPORTED) +extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#if defined(PNG_READ_iTXt_SUPPORTED) +PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_oFFs_SUPPORTED) +PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_pCAL_SUPPORTED) +PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_pHYs_SUPPORTED) +PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_sBIT_SUPPORTED) +PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_sCAL_SUPPORTED) +PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_sPLT_SUPPORTED) +extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#if defined(PNG_READ_sRGB_SUPPORTED) +PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_tEXt_SUPPORTED) +PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_tIME_SUPPORTED) +PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_tRNS_SUPPORTED) +PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_zTXt_SUPPORTED) +PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_APNG_SUPPORTED) +PNG_EXTERN void png_handle_acTL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_fcTL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_have_info PNGARG((png_structp png_ptr, png_infop info_ptr)); +PNG_EXTERN void png_handle_fdAT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_ensure_sequence_number PNGARG((png_structp png_ptr, + png_uint_32 length)); +#endif + +PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); + +PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, + png_bytep chunk_name)); + +/* handle the transformations for reading and writing */ +PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); + +PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, + png_uint_32 length)); +PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); +PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); +#if defined(PNG_READ_tEXt_SUPPORTED) +PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) +PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) +PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) +#if defined(PNG_MMX_CODE_SUPPORTED) +/* png.c */ /* PRIVATE */ +PNG_EXTERN void png_init_mmx_flags PNGARG((png_structp png_ptr)); +#endif +#endif + +#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) +PNG_EXTERN png_uint_32 png_get_pixels_per_inch PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN png_uint_32 png_get_x_pixels_per_inch PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN png_uint_32 png_get_y_pixels_per_inch PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN float png_get_x_offset_inches PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN float png_get_y_offset_inches PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#if defined(PNG_pHYs_SUPPORTED) +PNG_EXTERN png_uint_32 png_get_pHYs_dpi PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ + +/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +#endif /* PNG_INTERNAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* do not put anything past this line */ +#endif /* PNG_H */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pngconf.h b/kernel/kls_png/ksquirrel-libs-png/pngconf.h new file mode 100644 index 0000000..12a1848 --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngconf.h @@ -0,0 +1,1490 @@ + +/* pngconf.h - machine configurable file for libpng + * + * libpng version 1.2.20 - September 8, 2007 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2007 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +/* Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#define PNG_1_2_X + +/* + * PNG_USER_CONFIG has to be defined on the compiler command line. This + * includes the resource compiler for Windows DLL configurations. + */ +#ifdef PNG_USER_CONFIG +# ifndef PNG_USER_PRIVATEBUILD +# define PNG_USER_PRIVATEBUILD +# endif +#include "pngusr.h" +#endif + +/* PNG_CONFIGURE_LIBPNG is set by the "configure" script. */ +#ifdef PNG_CONFIGURE_LIBPNG +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#endif + +/* + * Added at libpng-1.2.8 + * + * If you create a private DLL you need to define in "pngusr.h" the followings: + * #define PNG_USER_PRIVATEBUILD + * e.g. #define PNG_USER_PRIVATEBUILD "Build by MyCompany for xyz reasons." + * #define PNG_USER_DLLFNAME_POSTFIX + * e.g. // private DLL "libpng13gx.dll" + * #define PNG_USER_DLLFNAME_POSTFIX "gx" + * + * The following macros are also at your disposal if you want to complete the + * DLL VERSIONINFO structure. + * - PNG_USER_VERSIONINFO_COMMENTS + * - PNG_USER_VERSIONINFO_COMPANYNAME + * - PNG_USER_VERSIONINFO_LEGALTRADEMARKS + */ + +#ifdef __STDC__ +#ifdef SPECIALBUILD +# pragma message("PNG_LIBPNG_SPECIALBUILD (and deprecated SPECIALBUILD)\ + are now LIBPNG reserved macros. Use PNG_USER_PRIVATEBUILD instead.") +#endif + +#ifdef PRIVATEBUILD +# pragma message("PRIVATEBUILD is deprecated.\ + Use PNG_USER_PRIVATEBUILD instead.") +# define PNG_USER_PRIVATEBUILD PRIVATEBUILD +#endif +#endif /* __STDC__ */ + +#ifndef PNG_VERSION_INFO_ONLY + +/* End of material added to libpng-1.2.8 */ + +/* Added at libpng-1.2.19, removed at libpng-1.2.20 because it caused trouble +# define PNG_WARN_UNINITIALIZED_ROW 1 +*/ +/* End of material added at libpng-1.2.19 */ + +/* This is the size of the compression buffer, and thus the size of + * an IDAT chunk. Make this whatever size you feel is best for your + * machine. One of these will be allocated per png_struct. When this + * is full, it writes the data to the disk, and does some other + * calculations. Making this an extremely small size will slow + * the library down, but you may want to experiment to determine + * where it becomes significant, if you are concerned with memory + * usage. Note that zlib allocates at least 32Kb also. For readers, + * this describes the size of the buffer available to read the data in. + * Unless this gets smaller than the size of a row (compressed), + * it should not make much difference how big this is. + */ + +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif + +/* Enable if you want a write-only libpng */ + +#ifndef PNG_NO_READ_SUPPORTED +# define PNG_READ_SUPPORTED +#endif + +/* Enable if you want a read-only libpng */ + +#ifndef PNG_NO_WRITE_SUPPORTED +# define PNG_WRITE_SUPPORTED +#endif + +/* Enabled by default in 1.2.0. You can disable this if you don't need to + support PNGs that are embedded in MNG datastreams */ +#if !defined(PNG_1_0_X) && !defined(PNG_NO_MNG_FEATURES) +# ifndef PNG_MNG_FEATURES_SUPPORTED +# define PNG_MNG_FEATURES_SUPPORTED +# endif +#endif + +#ifndef PNG_NO_FLOATING_POINT_SUPPORTED +# ifndef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FLOATING_POINT_SUPPORTED +# endif +#endif + +/* If you are running on a machine where you cannot allocate more + * than 64K of memory at once, uncomment this. While libpng will not + * normally need that much memory in a chunk (unless you load up a very + * large file), zlib needs to know how big of a chunk it can use, and + * libpng thus makes sure to check any memory allocation to verify it + * will fit into memory. +#define PNG_MAX_MALLOC_64K + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) +# define PNG_MAX_MALLOC_64K +#endif + +/* Special munging to support doing things the 'cygwin' way: + * 'Normal' png-on-win32 defines/defaults: + * PNG_BUILD_DLL -- building dll + * PNG_USE_DLL -- building an application, linking to dll + * (no define) -- building static library, or building an + * application and linking to the static lib + * 'Cygwin' defines/defaults: + * PNG_BUILD_DLL -- (ignored) building the dll + * (no define) -- (ignored) building an application, linking to the dll + * PNG_STATIC -- (ignored) building the static lib, or building an + * application that links to the static lib. + * ALL_STATIC -- (ignored) building various static libs, or building an + * application that links to the static libs. + * Thus, + * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and + * this bit of #ifdefs will define the 'correct' config variables based on + * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but + * unnecessary. + * + * Also, the precedence order is: + * ALL_STATIC (since we can't #undef something outside our namespace) + * PNG_BUILD_DLL + * PNG_STATIC + * (nothing) == PNG_USE_DLL + * + * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent + * of auto-import in binutils, we no longer need to worry about + * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, + * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes + * to __declspec() stuff. However, we DO need to worry about + * PNG_BUILD_DLL and PNG_STATIC because those change some defaults + * such as CONSOLE_IO and whether GLOBAL_ARRAYS are allowed. + */ +#if defined(__CYGWIN__) +# if defined(ALL_STATIC) +# if defined(PNG_BUILD_DLL) +# undef PNG_BUILD_DLL +# endif +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if defined(PNG_DLL) +# undef PNG_DLL +# endif +# if !defined(PNG_STATIC) +# define PNG_STATIC +# endif +# else +# if defined (PNG_BUILD_DLL) +# if defined(PNG_STATIC) +# undef PNG_STATIC +# endif +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if !defined(PNG_DLL) +# define PNG_DLL +# endif +# else +# if defined(PNG_STATIC) +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if defined(PNG_DLL) +# undef PNG_DLL +# endif +# else +# if !defined(PNG_USE_DLL) +# define PNG_USE_DLL +# endif +# if !defined(PNG_DLL) +# define PNG_DLL +# endif +# endif +# endif +# endif +#endif + +/* This protects us against compilers that run on a windowing system + * and thus don't have or would rather us not use the stdio types: + * stdin, stdout, and stderr. The only one currently used is stderr + * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will + * prevent these from being compiled and used. #defining PNG_NO_STDIO + * will also prevent these, plus will prevent the entire set of stdio + * macros and functions (FILE *, printf, etc.) from being compiled and used, + * unless (PNG_DEBUG > 0) has been #defined. + * + * #define PNG_NO_CONSOLE_IO + * #define PNG_NO_STDIO + */ + +#if defined(_WIN32_WCE) +# include + /* Console I/O functions are not supported on WindowsCE */ +# define PNG_NO_CONSOLE_IO +# ifdef PNG_DEBUG +# undef PNG_DEBUG +# endif +#endif + +#ifdef PNG_BUILD_DLL +# ifndef PNG_CONSOLE_IO_SUPPORTED +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# endif +#endif + +# ifdef PNG_NO_STDIO +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# include +# endif +# endif +# else +# if !defined(_WIN32_WCE) +/* "stdio.h" functions are not supported on WindowsCE */ +# include +# endif +# endif + +/* This macro protects us against machines that don't have function + * prototypes (ie K&R style headers). If your compiler does not handle + * function prototypes, define this macro and use the included ansi2knr. + * I've always been able to use _NO_PROTO as the indicator, but you may + * need to drag the empty declaration out in front of here, or change the + * ifdef to suit your own needs. + */ +#ifndef PNGARG + +#ifdef OF /* zlib prototype munger */ +# define PNGARG(arglist) OF(arglist) +#else + +#ifdef _NO_PROTO +# define PNGARG(arglist) () +# ifndef PNG_TYPECAST_NULL +# define PNG_TYPECAST_NULL +# endif +#else +# define PNGARG(arglist) arglist +#endif /* _NO_PROTO */ + + +#endif /* OF */ + +#endif /* PNGARG */ + +/* Try to determine if we are compiling on a Mac. Note that testing for + * just __MWERKS__ is not good enough, because the Codewarrior is now used + * on non-Mac platforms. + */ +#ifndef MACOS +# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ + defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) +# define MACOS +# endif +#endif + +/* enough people need this for various reasons to include it here */ +#if !defined(MACOS) && !defined(RISCOS) && !defined(_WIN32_WCE) +# include +#endif + +#if !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED) +# define PNG_SETJMP_SUPPORTED +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This is an attempt to force a single setjmp behaviour on Linux. If + * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. + */ + +# ifdef __linux__ +# ifdef _BSD_SOURCE +# define PNG_SAVE_BSD_SOURCE +# undef _BSD_SOURCE +# endif +# ifdef _SETJMP_H + /* If you encounter a compiler error here, see the explanation + * near the end of INSTALL. + */ + __png.h__ already includes setjmp.h; + __dont__ include it again.; +# endif +# endif /* __linux__ */ + + /* include setjmp.h for error handling */ +# include + +# ifdef __linux__ +# ifdef PNG_SAVE_BSD_SOURCE +# define _BSD_SOURCE +# undef PNG_SAVE_BSD_SOURCE +# endif +# endif /* __linux__ */ +#endif /* PNG_SETJMP_SUPPORTED */ + +#ifdef BSD +# include +#else +# include +#endif + +/* Other defines for things like memory and the like can go here. */ +#ifdef PNG_INTERNAL + +#include + +/* The functions exported by PNG_EXTERN are PNG_INTERNAL functions, which + * aren't usually used outside the library (as far as I know), so it is + * debatable if they should be exported at all. In the future, when it is + * possible to have run-time registry of chunk-handling functions, some of + * these will be made available again. +#define PNG_EXTERN extern + */ +#define PNG_EXTERN + +/* Other defines specific to compilers can go here. Try to keep + * them inside an appropriate ifdef/endif pair for portability. + */ + +#if defined(PNG_FLOATING_POINT_SUPPORTED) +# if defined(MACOS) + /* We need to check that hasn't already been included earlier + * as it seems it doesn't agree with , yet we should really use + * if possible. + */ +# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) +# include +# endif +# else +# include +# endif +# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) + /* Amiga SAS/C: We must include builtin FPU functions when compiling using + * MATH=68881 + */ +# include +# endif +#endif + +/* Codewarrior on NT has linking problems without this. */ +#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__) +# define PNG_ALWAYS_EXTERN +#endif + +/* This provides the non-ANSI (far) memory allocation routines. */ +#if defined(__TURBOC__) && defined(__MSDOS__) +# include +# include +#endif + +/* I have no idea why is this necessary... */ +#if defined(_MSC_VER) && (defined(WIN32) || defined(_Windows) || \ + defined(_WINDOWS) || defined(_WIN32) || defined(__WIN32__)) +# include +#endif + +/* This controls how fine the dithering gets. As this allocates + * a largish chunk of memory (32K), those who are not as concerned + * with dithering quality can decrease some or all of these. + */ +#ifndef PNG_DITHER_RED_BITS +# define PNG_DITHER_RED_BITS 5 +#endif +#ifndef PNG_DITHER_GREEN_BITS +# define PNG_DITHER_GREEN_BITS 5 +#endif +#ifndef PNG_DITHER_BLUE_BITS +# define PNG_DITHER_BLUE_BITS 5 +#endif + +/* This controls how fine the gamma correction becomes when you + * are only interested in 8 bits anyway. Increasing this value + * results in more memory being used, and more pow() functions + * being called to fill in the gamma tables. Don't set this value + * less then 8, and even that may not work (I haven't tested it). + */ + +#ifndef PNG_MAX_GAMMA_8 +# define PNG_MAX_GAMMA_8 11 +#endif + +/* This controls how much a difference in gamma we can tolerate before + * we actually start doing gamma conversion. + */ +#ifndef PNG_GAMMA_THRESHOLD +# define PNG_GAMMA_THRESHOLD 0.05 +#endif + +#endif /* PNG_INTERNAL */ + +/* The following uses const char * instead of char * for error + * and warning message functions, so some compilers won't complain. + * If you do not want to use const, define PNG_NO_CONST here. + */ + +#ifndef PNG_NO_CONST +# define PNG_CONST const +#else +# define PNG_CONST +#endif + +/* The following defines give you the ability to remove code from the + * library that you will not be using. I wish I could figure out how to + * automate this, but I can't do that without making it seriously hard + * on the users. So if you are not using an ability, change the #define + * to and #undef, and that part of the library will not be compiled. If + * your linker can't find a function, you may want to make sure the + * ability is defined here. Some of these depend upon some others being + * defined. I haven't figured out all the interactions here, so you may + * have to experiment awhile to get everything to compile. If you are + * creating or using a shared library, you probably shouldn't touch this, + * as it will affect the size of the structures, and this will cause bad + * things to happen if the library and/or application ever change. + */ + +/* Any features you will not be using can be undef'ed here */ + +/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user + * to turn it off with "*TRANSFORMS_NOT_SUPPORTED" or *PNG_NO_*_TRANSFORMS + * on the compile line, then pick and choose which ones to define without + * having to edit this file. It is safe to use the *TRANSFORMS_NOT_SUPPORTED + * if you only want to have a png-compliant reader/writer but don't need + * any of the extra transformations. This saves about 80 kbytes in a + * typical installation of the library. (PNG_NO_* form added in version + * 1.0.1c, for consistency) + */ + +/* The size of the png_text structure changed in libpng-1.0.6 when + * iTXt support was added. iTXt support was turned off by default through + * libpng-1.2.x, to support old apps that malloc the png_text structure + * instead of calling png_set_text() and letting libpng malloc it. It + * was turned on by default in libpng-1.3.0. + */ + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +# ifndef PNG_NO_iTXt_SUPPORTED +# define PNG_NO_iTXt_SUPPORTED +# endif +# ifndef PNG_NO_READ_iTXt +# define PNG_NO_READ_iTXt +# endif +# ifndef PNG_NO_WRITE_iTXt +# define PNG_NO_WRITE_iTXt +# endif +#endif + +#if !defined(PNG_NO_iTXt_SUPPORTED) +# if !defined(PNG_READ_iTXt_SUPPORTED) && !defined(PNG_NO_READ_iTXt) +# define PNG_READ_iTXt +# endif +# if !defined(PNG_WRITE_iTXt_SUPPORTED) && !defined(PNG_NO_WRITE_iTXt) +# define PNG_WRITE_iTXt +# endif +#endif + +/* The following support, added after version 1.0.0, can be turned off here en + * masse by defining PNG_LEGACY_SUPPORTED in case you need binary compatibility + * with old applications that require the length of png_struct and png_info + * to remain unchanged. + */ + +#ifdef PNG_LEGACY_SUPPORTED +# define PNG_NO_FREE_ME +# define PNG_NO_READ_UNKNOWN_CHUNKS +# define PNG_NO_WRITE_UNKNOWN_CHUNKS +# define PNG_NO_READ_USER_CHUNKS +# define PNG_NO_READ_iCCP +# define PNG_NO_WRITE_iCCP +# define PNG_NO_READ_iTXt +# define PNG_NO_WRITE_iTXt +# define PNG_NO_READ_sCAL +# define PNG_NO_WRITE_sCAL +# define PNG_NO_READ_sPLT +# define PNG_NO_WRITE_sPLT +# define PNG_NO_INFO_IMAGE +# define PNG_NO_READ_RGB_TO_GRAY +# define PNG_NO_READ_USER_TRANSFORM +# define PNG_NO_WRITE_USER_TRANSFORM +# define PNG_NO_USER_MEM +# define PNG_NO_READ_EMPTY_PLTE +# define PNG_NO_MNG_FEATURES +# define PNG_NO_FIXED_POINT_SUPPORTED +#endif + +/* Ignore attempt to turn off both floating and fixed point support */ +#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ + !defined(PNG_NO_FIXED_POINT_SUPPORTED) +# define PNG_FIXED_POINT_SUPPORTED +#endif + +#ifndef PNG_NO_FREE_ME +# define PNG_FREE_ME_SUPPORTED +#endif + +#if defined(PNG_READ_SUPPORTED) + +#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_TRANSFORMS) +# define PNG_READ_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_READ_EXPAND +# define PNG_READ_EXPAND_SUPPORTED +# endif +# ifndef PNG_NO_READ_SHIFT +# define PNG_READ_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACK +# define PNG_READ_PACK_SUPPORTED +# endif +# ifndef PNG_NO_READ_BGR +# define PNG_READ_BGR_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP +# define PNG_READ_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACKSWAP +# define PNG_READ_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT +# define PNG_READ_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_READ_DITHER +# define PNG_READ_DITHER_SUPPORTED +# endif +# ifndef PNG_NO_READ_BACKGROUND +# define PNG_READ_BACKGROUND_SUPPORTED +# endif +# ifndef PNG_NO_READ_16_TO_8 +# define PNG_READ_16_TO_8_SUPPORTED +# endif +# ifndef PNG_NO_READ_FILLER +# define PNG_READ_FILLER_SUPPORTED +# endif +# ifndef PNG_NO_READ_GAMMA +# define PNG_READ_GAMMA_SUPPORTED +# endif +# ifndef PNG_NO_READ_GRAY_TO_RGB +# define PNG_READ_GRAY_TO_RGB_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP_ALPHA +# define PNG_READ_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT_ALPHA +# define PNG_READ_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_STRIP_ALPHA +# define PNG_READ_STRIP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_USER_TRANSFORM +# define PNG_READ_USER_TRANSFORM_SUPPORTED +# endif +# ifndef PNG_NO_READ_RGB_TO_GRAY +# define PNG_READ_RGB_TO_GRAY_SUPPORTED +# endif +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +#if !defined(PNG_NO_PROGRESSIVE_READ) && \ + !defined(PNG_PROGRESSIVE_READ_SUPPORTED) /* if you don't do progressive */ +# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ +#endif /* about interlacing capability! You'll */ + /* still have interlacing unless you change the following line: */ + +#define PNG_READ_INTERLACING_SUPPORTED /* required in PNG-compliant decoders */ + +#ifndef PNG_NO_READ_COMPOSITE_NODIV +# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ +# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ +# endif +#endif + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Deprecated, will be removed from version 2.0.0. + Use PNG_MNG_FEATURES_SUPPORTED instead. */ +#ifndef PNG_NO_READ_EMPTY_PLTE +# define PNG_READ_EMPTY_PLTE_SUPPORTED +#endif +#endif + +#endif /* PNG_READ_SUPPORTED */ + +#if defined(PNG_WRITE_SUPPORTED) + +# if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_TRANSFORMS) +# define PNG_WRITE_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_WRITE_SHIFT +# define PNG_WRITE_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACK +# define PNG_WRITE_PACK_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_BGR +# define PNG_WRITE_BGR_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_SWAP +# define PNG_WRITE_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACKSWAP +# define PNG_WRITE_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT +# define PNG_WRITE_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_FILLER +# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ +# endif +# ifndef PNG_NO_WRITE_SWAP_ALPHA +# define PNG_WRITE_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT_ALPHA +# define PNG_WRITE_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_USER_TRANSFORM +# define PNG_WRITE_USER_TRANSFORM_SUPPORTED +# endif +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ + +#if !defined(PNG_NO_WRITE_INTERLACING_SUPPORTED) && \ + !defined(PNG_WRITE_INTERLACING_SUPPORTED) +#define PNG_WRITE_INTERLACING_SUPPORTED /* not required for PNG-compliant + encoders, but can cause trouble + if left undefined */ +#endif + +#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ + !defined(PNG_WRITE_WEIGHTED_FILTER) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) +# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#endif + +#ifndef PNG_NO_WRITE_FLUSH +# define PNG_WRITE_FLUSH_SUPPORTED +#endif + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Deprecated, see PNG_MNG_FEATURES_SUPPORTED, above */ +#ifndef PNG_NO_WRITE_EMPTY_PLTE +# define PNG_WRITE_EMPTY_PLTE_SUPPORTED +#endif +#endif + +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef PNG_1_0_X +# ifndef PNG_NO_ERROR_NUMBERS +# define PNG_ERROR_NUMBERS_SUPPORTED +# endif +#endif /* PNG_1_0_X */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +# ifndef PNG_NO_USER_TRANSFORM_PTR +# define PNG_USER_TRANSFORM_PTR_SUPPORTED +# endif +#endif + +#ifndef PNG_NO_STDIO +# define PNG_TIME_RFC1123_SUPPORTED +#endif + +/* This adds extra functions in pngget.c for accessing data from the + * info pointer (added in version 0.99) + * png_get_image_width() + * png_get_image_height() + * png_get_bit_depth() + * png_get_color_type() + * png_get_compression_type() + * png_get_filter_type() + * png_get_interlace_type() + * png_get_pixel_aspect_ratio() + * png_get_pixels_per_meter() + * png_get_x_offset_pixels() + * png_get_y_offset_pixels() + * png_get_x_offset_microns() + * png_get_y_offset_microns() + */ +#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) +# define PNG_EASY_ACCESS_SUPPORTED +#endif + +/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 + * and removed from version 1.2.20. The following will be removed + * from libpng-1.4.0 +*/ + +#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_OPTIMIZED_CODE) +# ifndef PNG_OPTIMIZED_CODE_SUPPORTED +# define PNG_OPTIMIZED_CODE_SUPPORTED +# endif +#endif + +#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_ASSEMBLER_CODE) +# ifndef PNG_ASSEMBLER_CODE_SUPPORTED +# define PNG_ASSEMBLER_CODE_SUPPORTED +# endif + +# if defined(__GNUC__) && defined(__x86_64__) && (__GNUC__ < 4) + /* work around 64-bit gcc compiler bugs in gcc-3.x */ +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_NO_MMX_CODE +# endif +# endif + +# if defined(__APPLE__) +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_NO_MMX_CODE +# endif +# endif + +# if (defined(__MWERKS__) && ((__MWERKS__ < 0x0900) || macintosh)) +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_NO_MMX_CODE +# endif +# endif + +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_MMX_CODE_SUPPORTED +# endif + +#endif +/* end of obsolete code to be removed from libpng-1.4.0 */ + +#if !defined(PNG_1_0_X) +#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) +# define PNG_USER_MEM_SUPPORTED +#endif +#endif /* PNG_1_0_X */ + +/* Added at libpng-1.2.6 */ +#if !defined(PNG_1_0_X) +#ifndef PNG_SET_USER_LIMITS_SUPPORTED +#if !defined(PNG_NO_SET_USER_LIMITS) && !defined(PNG_SET_USER_LIMITS_SUPPORTED) +# define PNG_SET_USER_LIMITS_SUPPORTED +#endif +#endif +#endif /* PNG_1_0_X */ + +/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGS no matter + * how large, set these limits to 0x7fffffffL + */ +#ifndef PNG_USER_WIDTH_MAX +# define PNG_USER_WIDTH_MAX 1000000L +#endif +#ifndef PNG_USER_HEIGHT_MAX +# define PNG_USER_HEIGHT_MAX 1000000L +#endif + +/* These are currently experimental features, define them if you want */ + +/* very little testing */ +/* +#ifdef PNG_READ_SUPPORTED +# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# endif +#endif +*/ + +/* This is only for PowerPC big-endian and 680x0 systems */ +/* some testing */ +/* +#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED +# define PNG_READ_BIG_ENDIAN_SUPPORTED +#endif +*/ + +/* Buggy compilers (e.g., gcc 2.7.2.2) need this */ +/* +#define PNG_NO_POINTER_INDEXING +*/ + +/* These functions are turned off by default, as they will be phased out. */ +/* +#define PNG_USELESS_TESTS_SUPPORTED +#define PNG_CORRECT_PALETTE_SUPPORTED +*/ + +/* Any chunks you are not interested in, you can undef here. The + * ones that allocate memory may be expecially important (hIST, + * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info + * a bit smaller. + */ + +#if defined(PNG_READ_SUPPORTED) && \ + !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_ANCILLARY_CHUNKS) +# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#endif + +#if defined(PNG_WRITE_SUPPORTED) && \ + !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) +# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#endif + +#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_READ_TEXT +# define PNG_NO_READ_iTXt +# define PNG_NO_READ_tEXt +# define PNG_NO_READ_zTXt +#endif +#ifndef PNG_NO_READ_bKGD +# define PNG_READ_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +#endif +#ifndef PNG_NO_READ_cHRM +# define PNG_READ_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +#endif +#ifndef PNG_NO_READ_gAMA +# define PNG_READ_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +#endif +#ifndef PNG_NO_READ_hIST +# define PNG_READ_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +#endif +#ifndef PNG_NO_READ_iCCP +# define PNG_READ_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +#endif +#ifndef PNG_NO_READ_iTXt +# ifndef PNG_READ_iTXt_SUPPORTED +# define PNG_READ_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_READ_oFFs +# define PNG_READ_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +#endif +#ifndef PNG_NO_READ_pCAL +# define PNG_READ_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_sCAL +# define PNG_READ_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_pHYs +# define PNG_READ_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +#endif +#ifndef PNG_NO_READ_sBIT +# define PNG_READ_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sPLT +# define PNG_READ_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sRGB +# define PNG_READ_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +#endif +#ifndef PNG_NO_READ_tEXt +# define PNG_READ_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_tIME +# define PNG_READ_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +#endif +#ifndef PNG_NO_READ_tRNS +# define PNG_READ_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +#endif +#ifndef PNG_NO_READ_zTXt +# define PNG_READ_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_APNG +# define PNG_READ_APNG_SUPPORTED +# define PNG_APNG_SUPPORTED +#endif +#ifndef PNG_NO_READ_UNKNOWN_CHUNKS +# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_NO_HANDLE_AS_UNKNOWN +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +#endif +#if !defined(PNG_NO_READ_USER_CHUNKS) && \ + defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) +# define PNG_READ_USER_CHUNKS_SUPPORTED +# define PNG_USER_CHUNKS_SUPPORTED +# ifdef PNG_NO_READ_UNKNOWN_CHUNKS +# undef PNG_NO_READ_UNKNOWN_CHUNKS +# endif +# ifdef PNG_NO_HANDLE_AS_UNKNOWN +# undef PNG_NO_HANDLE_AS_UNKNOWN +# endif +#endif +#ifndef PNG_NO_READ_OPT_PLTE +# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ +#endif /* optional PLTE chunk in RGB and RGBA images */ +#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ + defined(PNG_READ_zTXt_SUPPORTED) +# define PNG_READ_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +#endif + +#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ + +#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_WRITE_TEXT +# define PNG_NO_WRITE_iTXt +# define PNG_NO_WRITE_tEXt +# define PNG_NO_WRITE_zTXt +#endif +#ifndef PNG_NO_WRITE_bKGD +# define PNG_WRITE_bKGD_SUPPORTED +# ifndef PNG_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_cHRM +# define PNG_WRITE_cHRM_SUPPORTED +# ifndef PNG_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_gAMA +# define PNG_WRITE_gAMA_SUPPORTED +# ifndef PNG_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_hIST +# define PNG_WRITE_hIST_SUPPORTED +# ifndef PNG_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iCCP +# define PNG_WRITE_iCCP_SUPPORTED +# ifndef PNG_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iTXt +# ifndef PNG_WRITE_iTXt_SUPPORTED +# define PNG_WRITE_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_oFFs +# define PNG_WRITE_oFFs_SUPPORTED +# ifndef PNG_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pCAL +# define PNG_WRITE_pCAL_SUPPORTED +# ifndef PNG_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sCAL +# define PNG_WRITE_sCAL_SUPPORTED +# ifndef PNG_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pHYs +# define PNG_WRITE_pHYs_SUPPORTED +# ifndef PNG_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sBIT +# define PNG_WRITE_sBIT_SUPPORTED +# ifndef PNG_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sPLT +# define PNG_WRITE_sPLT_SUPPORTED +# ifndef PNG_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sRGB +# define PNG_WRITE_sRGB_SUPPORTED +# ifndef PNG_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tEXt +# define PNG_WRITE_tEXt_SUPPORTED +# ifndef PNG_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tIME +# define PNG_WRITE_tIME_SUPPORTED +# ifndef PNG_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tRNS +# define PNG_WRITE_tRNS_SUPPORTED +# ifndef PNG_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_zTXt +# define PNG_WRITE_zTXt_SUPPORTED +# ifndef PNG_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_APNG +# define PNG_WRITE_APNG_SUPPORTED +# ifndef PNG_APNG_SUPPORTED +# define PNG_APNG_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS +# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_NO_HANDLE_AS_UNKNOWN +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +# endif +#endif +#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ + defined(PNG_WRITE_zTXt_SUPPORTED) +# define PNG_WRITE_TEXT_SUPPORTED +# ifndef PNG_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +# endif +#endif + +#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ + +/* Turn this off to disable png_read_png() and + * png_write_png() and leave the row_pointers member + * out of the info structure. + */ +#ifndef PNG_NO_INFO_IMAGE +# define PNG_INFO_IMAGE_SUPPORTED +#endif + +/* need the time information for reading tIME chunks */ +#if defined(PNG_tIME_SUPPORTED) +# if !defined(_WIN32_WCE) + /* "time.h" functions are not supported on WindowsCE */ +# include +# endif +#endif + +/* Some typedefs to get us started. These should be safe on most of the + * common platforms. The typedefs should be at least as large as the + * numbers suggest (a png_uint_32 must be at least 32 bits long), but they + * don't have to be exactly that size. Some compilers dislike passing + * unsigned shorts as function parameters, so you may be better off using + * unsigned int for png_uint_16. Likewise, for 64-bit systems, you may + * want to have unsigned int for png_uint_32 instead of unsigned long. + */ + +typedef unsigned long png_uint_32; +typedef long png_int_32; +typedef unsigned short png_uint_16; +typedef short png_int_16; +typedef unsigned char png_byte; + +/* This is usually size_t. It is typedef'ed just in case you need it to + change (I'm not sure if you will or not, so I thought I'd be safe) */ +#ifdef PNG_SIZE_T + typedef PNG_SIZE_T png_size_t; +# define png_sizeof(x) png_convert_size(sizeof (x)) +#else + typedef size_t png_size_t; +# define png_sizeof(x) sizeof (x) +#endif + +/* The following is needed for medium model support. It cannot be in the + * PNG_INTERNAL section. Needs modification for other compilers besides + * MSC. Model independent support declares all arrays and pointers to be + * large using the far keyword. The zlib version used must also support + * model independent data. As of version zlib 1.0.4, the necessary changes + * have been made in zlib. The USE_FAR_KEYWORD define triggers other + * changes that are needed. (Tim Wegner) + */ + +/* Separate compiler dependencies (problem here is that zlib.h always + defines FAR. (SJT) */ +#ifdef __BORLANDC__ +# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) +# define LDATA 1 +# else +# define LDATA 0 +# endif + /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ +# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) +# define PNG_MAX_MALLOC_64K +# if (LDATA != 1) +# ifndef FAR +# define FAR __far +# endif +# define USE_FAR_KEYWORD +# endif /* LDATA != 1 */ + /* Possibly useful for moving data out of default segment. + * Uncomment it if you want. Could also define FARDATA as + * const if your compiler supports it. (SJT) +# define FARDATA FAR + */ +# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ +#endif /* __BORLANDC__ */ + + +/* Suggest testing for specific compiler first before testing for + * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, + * making reliance oncertain keywords suspect. (SJT) + */ + +/* MSC Medium model */ +#if defined(FAR) +# if defined(M_I86MM) +# define USE_FAR_KEYWORD +# define FARDATA FAR +# include +# endif +#endif + +/* SJT: default case */ +#ifndef FAR +# define FAR +#endif + +/* At this point FAR is always defined */ +#ifndef FARDATA +# define FARDATA +#endif + +/* Typedef for floating-point numbers that are converted + to fixed-point with a multiple of 100,000, e.g., int_gamma */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void FAR * png_voidp; +typedef png_byte FAR * png_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST char FAR * png_const_charp; +typedef char FAR * png_charp; +typedef png_fixed_point FAR * png_fixed_point_p; + +#ifndef PNG_NO_STDIO +#if defined(_WIN32_WCE) +typedef HANDLE png_FILE_p; +#else +typedef FILE * png_FILE_p; +#endif +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * png_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte FAR * FAR * png_bytepp; +typedef png_uint_32 FAR * FAR * png_uint_32pp; +typedef png_int_32 FAR * FAR * png_int_32pp; +typedef png_uint_16 FAR * FAR * png_uint_16pp; +typedef png_int_16 FAR * FAR * png_int_16pp; +typedef PNG_CONST char FAR * FAR * png_const_charpp; +typedef char FAR * FAR * png_charpp; +typedef png_fixed_point FAR * FAR * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * FAR * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char FAR * FAR * FAR * png_charppp; + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +/* SPC - Is this stuff deprecated? */ +/* It'll be removed as of libpng-1.3.0 - GR-P */ +/* libpng typedefs for types in zlib. If zlib changes + * or another compression library is used, then change these. + * Eliminates need to change all the source files. + */ +typedef charf * png_zcharp; +typedef charf * FAR * png_zcharpp; +typedef z_stream FAR * png_zstreamp; +#endif /* (PNG_1_0_X) || defined(PNG_1_2_X) */ + +/* + * Define PNG_BUILD_DLL if the module being built is a Windows + * LIBPNG DLL. + * + * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. + * It is equivalent to Microsoft predefined macro _DLL that is + * automatically defined when you compile using the share + * version of the CRT (C Run-Time library) + * + * The cygwin mods make this behavior a little different: + * Define PNG_BUILD_DLL if you are building a dll for use with cygwin + * Define PNG_STATIC if you are building a static library for use with cygwin, + * -or- if you are building an application that you want to link to the + * static library. + * PNG_USE_DLL is defined by default (no user action needed) unless one of + * the other flags is defined. + */ + +#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) +# define PNG_DLL +#endif +/* If CYGWIN, then disallow GLOBAL ARRAYS unless building a static lib. + * When building a static lib, default to no GLOBAL ARRAYS, but allow + * command-line override + */ +#if defined(__CYGWIN__) +# if !defined(PNG_STATIC) +# if defined(PNG_USE_GLOBAL_ARRAYS) +# undef PNG_USE_GLOBAL_ARRAYS +# endif +# if !defined(PNG_USE_LOCAL_ARRAYS) +# define PNG_USE_LOCAL_ARRAYS +# endif +# else +# if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNG_NO_GLOBAL_ARRAYS) +# if defined(PNG_USE_GLOBAL_ARRAYS) +# undef PNG_USE_GLOBAL_ARRAYS +# endif +# endif +# endif +# if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) +# define PNG_USE_LOCAL_ARRAYS +# endif +#endif + +/* Do not use global arrays (helps with building DLL's) + * They are no longer used in libpng itself, since version 1.0.5c, + * but might be required for some pre-1.0.5c applications. + */ +#if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) +# if defined(PNG_NO_GLOBAL_ARRAYS) || \ + (defined(__GNUC__) && defined(PNG_DLL)) || defined(_MSC_VER) +# define PNG_USE_LOCAL_ARRAYS +# else +# define PNG_USE_GLOBAL_ARRAYS +# endif +#endif + +#if defined(__CYGWIN__) +# undef PNGAPI +# define PNGAPI __cdecl +# undef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", + * you may get warnings regarding the linkage of png_zalloc and png_zfree. + * Don't ignore those warnings; you must also reset the default calling + * convention in your compiler to match your PNGAPI, and you must build + * zlib and your applications the same way you build libpng. + */ + +#if defined(__MINGW32__) && !defined(PNG_MODULEDEF) +# ifndef PNG_NO_MODULEDEF +# define PNG_NO_MODULEDEF +# endif +#endif + +#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF) +# define PNG_IMPEXP +#endif + +#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ + (( defined(_Windows) || defined(_WINDOWS) || \ + defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) + +# ifndef PNGAPI +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGAPI __cdecl +# else +# define PNGAPI _cdecl +# endif +# endif + +# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ + 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) +# define PNG_IMPEXP +# endif + +# if !defined(PNG_IMPEXP) + +# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol +# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol + + /* Borland/Microsoft */ +# if defined(_MSC_VER) || defined(__BORLANDC__) +# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) +# define PNG_EXPORT PNG_EXPORT_TYPE1 +# else +# define PNG_EXPORT PNG_EXPORT_TYPE2 +# if defined(PNG_BUILD_DLL) +# define PNG_IMPEXP __export +# else +# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in + VC++ */ +# endif /* Exists in Borland C++ for + C++ classes (== huge) */ +# endif +# endif + +# if !defined(PNG_IMPEXP) +# if defined(PNG_BUILD_DLL) +# define PNG_IMPEXP __declspec(dllexport) +# else +# define PNG_IMPEXP __declspec(dllimport) +# endif +# endif +# endif /* PNG_IMPEXP */ +#else /* !(DLL || non-cygwin WINDOWS) */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# ifndef PNGAPI +# define PNGAPI _System +# endif +# else +# if 0 /* ... other platforms, with other meanings */ +# endif +# endif +#endif + +#ifndef PNGAPI +# define PNGAPI +#endif +#ifndef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +#ifdef PNG_BUILDSYMS +# ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END +# endif +# ifdef PNG_USE_GLOBAL_ARRAYS +# ifndef PNG_EXPORT_VAR +# define PNG_EXPORT_VAR(type) PNG_DATA_EXPORT +# endif +# endif +#endif + +#ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol +#endif + +#ifdef PNG_USE_GLOBAL_ARRAYS +# ifndef PNG_EXPORT_VAR +# define PNG_EXPORT_VAR(type) extern PNG_IMPEXP type +# endif +#endif + +/* User may want to use these so they are not in PNG_INTERNAL. Any library + * functions that are passed far data must be model independent. + */ + +#ifndef PNG_ABORT +# define PNG_ABORT() abort() +#endif + +#ifdef PNG_SETJMP_SUPPORTED +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_SETJMP_NOT_SUPPORTED) +#endif + +#if defined(USE_FAR_KEYWORD) /* memory model independent fns */ +/* use this to make far-to-near assignments */ +# define CHECK 1 +# define NOCHECK 0 +# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) +# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) +# define png_snprintf _fsnprintf /* Added to v 1.2.19 */ +# define png_strcpy _fstrcpy +# define png_strncpy _fstrncpy /* Added to v 1.2.6 */ +# define png_strlen _fstrlen +# define png_memcmp _fmemcmp /* SJT: added */ +# define png_memcpy _fmemcpy +# define png_memset _fmemset +#else /* use the usual functions */ +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# ifndef PNG_NO_SNPRINTF +# ifdef _MSC_VER +# define png_snprintf _snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 _snprintf +# define png_snprintf6 _snprintf +# else +# define png_snprintf snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 snprintf +# define png_snprintf6 snprintf +# endif +# else + /* You don't have or don't want to use snprintf(). Caution: Using + * sprintf instead of snprintf exposes your application to accidental + * or malevolent buffer overflows. If you don't have snprintf() + * as a general rule you should provide one (you can get one from + * Portable OpenSSH). */ +# define png_snprintf(s1,n,fmt,x1) sprintf(s1,fmt,x1) +# define png_snprintf2(s1,n,fmt,x1,x2) sprintf(s1,fmt,x1,x2) +# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \ + sprintf(s1,fmt,x1,x2,x3,x4,x5,x6) +# endif +# define png_strcpy strcpy +# define png_strncpy strncpy /* Added to v 1.2.6 */ +# define png_strlen strlen +# define png_memcmp memcmp /* SJT: added */ +# define png_memcpy memcpy +# define png_memset memset +#endif +/* End of memory model independent support */ + +/* Just a little check that someone hasn't tried to define something + * contradictory. + */ +#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) +# undef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 65536L +#endif + +/* Added at libpng-1.2.8 */ +#endif /* PNG_VERSION_INFO_ONLY */ + +#endif /* PNGCONF_H */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pngerror.c b/kernel/kls_png/ksquirrel-libs-png/pngerror.c new file mode 100644 index 0000000..159c5d4 --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngerror.c @@ -0,0 +1,341 @@ + +/* pngerror.c - stub functions for i/o and memory allocation + * + * Last changed in libpng 1.2.20 September 8, 2007 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2007 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all error handling. Users who + * need special error handling are expected to write replacement functions + * and use png_set_error_fn() to use those functions. See the instructions + * at each function. + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +static void /* PRIVATE */ +png_default_error PNGARG((png_structp png_ptr, + png_const_charp error_message)); +#ifndef PNG_NO_WARNINGS +static void /* PRIVATE */ +png_default_warning PNGARG((png_structp png_ptr, + png_const_charp warning_message)); +#endif /* PNG_NO_WARNINGS */ + +/* This function is called whenever there is a fatal error. This function + * should not be changed. If there is a need to handle errors differently, + * you should supply a replacement error function and use png_set_error_fn() + * to replace the error function at run-time. + */ +#ifndef PNG_NO_ERROR_TEXT +void PNGAPI +png_error(png_structp png_ptr, png_const_charp error_message) +{ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + char msg[16]; + if (png_ptr != NULL) + { + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) + { + if (*error_message == '#') + { + int offset; + for (offset=1; offset<15; offset++) + if (*(error_message+offset) == ' ') + break; + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + int i; + for (i=0; iflags&PNG_FLAG_STRIP_ERROR_TEXT) + { + msg[0]='0'; + msg[1]='\0'; + error_message=msg; + } + } + } + } +#endif + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, error_message); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, error_message); +} +#else +void PNGAPI +png_err(png_structp png_ptr) +{ + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, '\0'); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, '\0'); +} +#endif /* PNG_NO_ERROR_TEXT */ + +#ifndef PNG_NO_WARNINGS +/* This function is called whenever there is a non-fatal error. This function + * should not be changed. If there is a need to handle warnings differently, + * you should supply a replacement warning function and use + * png_set_error_fn() to replace the warning function at run-time. + */ +void PNGAPI +png_warning(png_structp png_ptr, png_const_charp warning_message) +{ + int offset = 0; + if (png_ptr != NULL) + { +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) +#endif + { + if (*warning_message == '#') + { + for (offset=1; offset<15; offset++) + if (*(warning_message+offset) == ' ') + break; + } + } + if (png_ptr != NULL && png_ptr->warning_fn != NULL) + (*(png_ptr->warning_fn))(png_ptr, warning_message+offset); + } + else + png_default_warning(png_ptr, warning_message+offset); +} +#endif /* PNG_NO_WARNINGS */ + + +/* These utilities are used internally to build an error message that relates + * to the current chunk. The chunk name comes from png_ptr->chunk_name, + * this is used to prefix the message. The message is limited in length + * to 63 bytes, the name characters are output as hex digits wrapped in [] + * if the character is invalid. + */ +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) +static PNG_CONST char png_digit[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' +}; + +#if !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT) +static void /* PRIVATE */ +png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp + error_message) +{ + int iout = 0, iin = 0; + + while (iin < 4) + { + int c = png_ptr->chunk_name[iin++]; + if (isnonalpha(c)) + { + buffer[iout++] = '['; + buffer[iout++] = png_digit[(c & 0xf0) >> 4]; + buffer[iout++] = png_digit[c & 0x0f]; + buffer[iout++] = ']'; + } + else + { + buffer[iout++] = (png_byte)c; + } + } + + if (error_message == NULL) + buffer[iout] = 0; + else + { + buffer[iout++] = ':'; + buffer[iout++] = ' '; + png_strncpy(buffer+iout, error_message, 63); + buffer[iout+63] = 0; + } +} + +#ifdef PNG_READ_SUPPORTED +void PNGAPI +png_chunk_error(png_structp png_ptr, png_const_charp error_message) +{ + char msg[18+64]; + if (png_ptr == NULL) + png_error(png_ptr, error_message); + else + { + png_format_buffer(png_ptr, msg, error_message); + png_error(png_ptr, msg); + } +} +#endif /* PNG_READ_SUPPORTED */ +#endif /* !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT) */ + +#ifndef PNG_NO_WARNINGS +void PNGAPI +png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) +{ + char msg[18+64]; + if (png_ptr == NULL) + png_warning(png_ptr, warning_message); + else + { + png_format_buffer(png_ptr, msg, warning_message); + png_warning(png_ptr, msg); + } +} +#endif /* PNG_NO_WARNINGS */ + + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void /* PRIVATE */ +png_default_error(png_structp png_ptr, png_const_charp error_message) +{ +#ifndef PNG_NO_CONSOLE_IO +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*error_message == '#') + { + int offset; + char error_number[16]; + for (offset=0; offset<15; offset++) + { + error_number[offset] = *(error_message+offset+1); + if (*(error_message+offset) == ' ') + break; + } + if((offset > 1) && (offset < 15)) + { + error_number[offset-1]='\0'; + fprintf(stderr, "libpng error no. %s: %s\n", error_number, + error_message+offset); + } + else + fprintf(stderr, "libpng error: %s, offset=%d\n", error_message,offset); + } + else +#endif + fprintf(stderr, "libpng error: %s\n", error_message); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + if (png_ptr) + { +# ifdef USE_FAR_KEYWORD + { + jmp_buf jmpbuf; + png_memcpy(jmpbuf, png_ptr->jmpbuf, png_sizeof(jmp_buf)); + longjmp(jmpbuf, 1); + } +# else + longjmp(png_ptr->jmpbuf, 1); +# endif + } +#else + PNG_ABORT(); +#endif +#ifdef PNG_NO_CONSOLE_IO + error_message = error_message; /* make compiler happy */ +#endif +} + +#ifndef PNG_NO_WARNINGS +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want them to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void /* PRIVATE */ +png_default_warning(png_structp png_ptr, png_const_charp warning_message) +{ +#ifndef PNG_NO_CONSOLE_IO +# ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*warning_message == '#') + { + int offset; + char warning_number[16]; + for (offset=0; offset<15; offset++) + { + warning_number[offset]=*(warning_message+offset+1); + if (*(warning_message+offset) == ' ') + break; + } + if((offset > 1) && (offset < 15)) + { + warning_number[offset-1]='\0'; + fprintf(stderr, "libpng warning no. %s: %s\n", warning_number, + warning_message+offset); + } + else + fprintf(stderr, "libpng warning: %s\n", warning_message); + } + else +# endif + fprintf(stderr, "libpng warning: %s\n", warning_message); +#else + warning_message = warning_message; /* make compiler happy */ +#endif + png_ptr = png_ptr; /* make compiler happy */ +} +#endif /* PNG_NO_WARNINGS */ + +/* This function is called when the application wants to use another method + * of handling errors and warnings. Note that the error function MUST NOT + * return to the calling routine or serious problems will occur. The return + * method used in the default routine calls longjmp(png_ptr->jmpbuf, 1) + */ +void PNGAPI +png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warning_fn) +{ + if (png_ptr == NULL) + return; + png_ptr->error_ptr = error_ptr; + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; +} + + +/* This function returns a pointer to the error_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_error_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return NULL; + return ((png_voidp)png_ptr->error_ptr); +} + + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +void PNGAPI +png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) +{ + if(png_ptr != NULL) + { + png_ptr->flags &= + ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); + } +} +#endif +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pnggccrd.c b/kernel/kls_png/ksquirrel-libs-png/pnggccrd.c new file mode 100644 index 0000000..a7248d6 --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pnggccrd.c @@ -0,0 +1,101 @@ +/* pnggccrd.c was removed from libpng-1.2.20. */ + +/* This code snippet is for use by configure's compilation test. */ + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && \ + defined(PNG_MMX_CODE_SUPPORTED) +int PNGAPI png_dummy_mmx_support(void); + +static int _mmx_supported = 2; // 0: no MMX; 1: MMX supported; 2: not tested + +int PNGAPI +png_dummy_mmx_support(void) __attribute__((noinline)); + +int PNGAPI +png_dummy_mmx_support(void) +{ + int result; +#if defined(PNG_MMX_CODE_SUPPORTED) // superfluous, but what the heck + __asm__ __volatile__ ( +#if defined(__x86_64__) + "pushq %%rbx \n\t" // rbx gets clobbered by CPUID instruction + "pushq %%rcx \n\t" // so does rcx... + "pushq %%rdx \n\t" // ...and rdx (but rcx & rdx safe on Linux) + "pushfq \n\t" // save Eflag to stack + "popq %%rax \n\t" // get Eflag from stack into rax + "movq %%rax, %%rcx \n\t" // make another copy of Eflag in rcx + "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21) + "pushq %%rax \n\t" // save modified Eflag back to stack + "popfq \n\t" // restore modified value to Eflag reg + "pushfq \n\t" // save Eflag to stack + "popq %%rax \n\t" // get Eflag from stack + "pushq %%rcx \n\t" // save original Eflag to stack + "popfq \n\t" // restore original Eflag +#else + "pushl %%ebx \n\t" // ebx gets clobbered by CPUID instruction + "pushl %%ecx \n\t" // so does ecx... + "pushl %%edx \n\t" // ...and edx (but ecx & edx safe on Linux) + "pushfl \n\t" // save Eflag to stack + "popl %%eax \n\t" // get Eflag from stack into eax + "movl %%eax, %%ecx \n\t" // make another copy of Eflag in ecx + "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21) + "pushl %%eax \n\t" // save modified Eflag back to stack + "popfl \n\t" // restore modified value to Eflag reg + "pushfl \n\t" // save Eflag to stack + "popl %%eax \n\t" // get Eflag from stack + "pushl %%ecx \n\t" // save original Eflag to stack + "popfl \n\t" // restore original Eflag +#endif + "xorl %%ecx, %%eax \n\t" // compare new Eflag with original Eflag + "jz 0f \n\t" // if same, CPUID instr. is not supported + + "xorl %%eax, %%eax \n\t" // set eax to zero +// ".byte 0x0f, 0xa2 \n\t" // CPUID instruction (two-byte opcode) + "cpuid \n\t" // get the CPU identification info + "cmpl $1, %%eax \n\t" // make sure eax return non-zero value + "jl 0f \n\t" // if eax is zero, MMX is not supported + + "xorl %%eax, %%eax \n\t" // set eax to zero and... + "incl %%eax \n\t" // ...increment eax to 1. This pair is + // faster than the instruction "mov eax, 1" + "cpuid \n\t" // get the CPU identification info again + "andl $0x800000, %%edx \n\t" // mask out all bits but MMX bit (23) + "cmpl $0, %%edx \n\t" // 0 = MMX not supported + "jz 0f \n\t" // non-zero = yes, MMX IS supported + + "movl $1, %%eax \n\t" // set return value to 1 + "jmp 1f \n\t" // DONE: have MMX support + + "0: \n\t" // .NOT_SUPPORTED: target label for jump instructions + "movl $0, %%eax \n\t" // set return value to 0 + "1: \n\t" // .RETURN: target label for jump instructions +#if defined(__x86_64__) + "popq %%rdx \n\t" // restore rdx + "popq %%rcx \n\t" // restore rcx + "popq %%rbx \n\t" // restore rbx +#else + "popl %%edx \n\t" // restore edx + "popl %%ecx \n\t" // restore ecx + "popl %%ebx \n\t" // restore ebx +#endif + +// "ret \n\t" // DONE: no MMX support + // (fall through to standard C "ret") + + : "=a" (result) // output list + + : // any variables used on input (none) + + // no clobber list +// , "%ebx", "%ecx", "%edx" // GRR: we handle these manually +// , "memory" // if write to a variable gcc thought was in a reg +// , "cc" // "condition codes" (flag bits) + ); + _mmx_supported = result; +#else + _mmx_supported = 0; +#endif /* PNG_MMX_CODE_SUPPORTED */ + + return _mmx_supported; +} +#endif diff --git a/kernel/kls_png/ksquirrel-libs-png/pngget.c b/kernel/kls_png/ksquirrel-libs-png/pngget.c new file mode 100644 index 0000000..d700f30 --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngget.c @@ -0,0 +1,1062 @@ + +/* pngget.c - retrieval of values from info struct + * + * Last changed in libpng 1.2.15 January 5, 2007 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2007 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +png_uint_32 PNGAPI +png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->valid & flag); + else + return(0); +} + +png_uint_32 PNGAPI +png_get_rowbytes(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->rowbytes); + else + return(0); +} + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +png_bytepp PNGAPI +png_get_rows(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->row_pointers); + else + return(0); +} +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* easy access to info, added in libpng-0.99 */ +png_uint_32 PNGAPI +png_get_image_width(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->width; + } + return (0); +} + +png_uint_32 PNGAPI +png_get_image_height(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->height; + } + return (0); +} + +png_byte PNGAPI +png_get_bit_depth(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->bit_depth; + } + return (0); +} + +png_byte PNGAPI +png_get_color_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->color_type; + } + return (0); +} + +png_byte PNGAPI +png_get_filter_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->filter_type; + } + return (0); +} + +png_byte PNGAPI +png_get_interlace_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->interlace_type; + } + return (0); +} + +png_byte PNGAPI +png_get_compression_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->compression_type; + } + return (0); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_x_pixels_per_meter"); + if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER) + return (0); + else return (info_ptr->x_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_y_pixels_per_meter"); + if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER) + return (0); + else return (info_ptr->y_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +png_uint_32 PNGAPI +png_get_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_pixels_per_meter"); + if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER || + info_ptr->x_pixels_per_unit != info_ptr->y_pixels_per_unit) + return (0); + else return (info_ptr->x_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_pixel_aspect_ratio(png_structp png_ptr, png_infop info_ptr) + { + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_aspect_ratio"); + if (info_ptr->x_pixels_per_unit == 0) + return ((float)0.0); + else + return ((float)((float)info_ptr->y_pixels_per_unit + /(float)info_ptr->x_pixels_per_unit)); + } +#else + return (0.0); +#endif + return ((float)0.0); +} +#endif + +png_int_32 PNGAPI +png_get_x_offset_microns(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) + return (0); + else return (info_ptr->x_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_microns(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) + return (0); + else return (info_ptr->y_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_x_offset_pixels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) + return (0); + else return (info_ptr->x_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_pixels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) + return (0); + else return (info_ptr->y_offset); + } +#else + return (0); +#endif + return (0); +} + +#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) +png_uint_32 PNGAPI +png_get_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_x_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_y_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +float PNGAPI +png_get_x_offset_inches(png_structp png_ptr, png_infop info_ptr) +{ + return ((float)png_get_x_offset_microns(png_ptr, info_ptr) + *.00003937); +} + +float PNGAPI +png_get_y_offset_inches(png_structp png_ptr, png_infop info_ptr) +{ + return ((float)png_get_y_offset_microns(png_ptr, info_ptr) + *.00003937); +} + +#if defined(PNG_pHYs_SUPPORTED) +png_uint_32 PNGAPI +png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function\n", "pHYs"); + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + if(*unit_type == 1) + { + if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); + if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); + } + } + } + return (retval); +} +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ + +/* png_get_channels really belongs in here, too, but it's been around longer */ + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +png_byte PNGAPI +png_get_channels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->channels); + else + return (0); +} + +png_bytep PNGAPI +png_get_signature(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->signature); + else + return (NULL); +} + +#if defined(PNG_bKGD_SUPPORTED) +png_uint_32 PNGAPI +png_get_bKGD(png_structp png_ptr, png_infop info_ptr, + png_color_16p *background) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) + && background != NULL) + { + png_debug1(1, "in %s retrieval function\n", "bKGD"); + *background = &(info_ptr->background); + return (PNG_INFO_bKGD); + } + return (0); +} +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM(png_structp png_ptr, png_infop info_ptr, + double *white_x, double *white_y, double *red_x, double *red_y, + double *green_x, double *green_y, double *blue_x, double *blue_y) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + png_debug1(1, "in %s retrieval function\n", "cHRM"); + if (white_x != NULL) + *white_x = (double)info_ptr->x_white; + if (white_y != NULL) + *white_y = (double)info_ptr->y_white; + if (red_x != NULL) + *red_x = (double)info_ptr->x_red; + if (red_y != NULL) + *red_y = (double)info_ptr->y_red; + if (green_x != NULL) + *green_x = (double)info_ptr->x_green; + if (green_y != NULL) + *green_y = (double)info_ptr->y_green; + if (blue_x != NULL) + *blue_x = (double)info_ptr->x_blue; + if (blue_y != NULL) + *blue_y = (double)info_ptr->y_blue; + return (PNG_INFO_cHRM); + } + return (0); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x, + png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y, + png_fixed_point *blue_x, png_fixed_point *blue_y) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + png_debug1(1, "in %s retrieval function\n", "cHRM"); + if (white_x != NULL) + *white_x = info_ptr->int_x_white; + if (white_y != NULL) + *white_y = info_ptr->int_y_white; + if (red_x != NULL) + *red_x = info_ptr->int_x_red; + if (red_y != NULL) + *red_y = info_ptr->int_y_red; + if (green_x != NULL) + *green_x = info_ptr->int_x_green; + if (green_y != NULL) + *green_y = info_ptr->int_y_green; + if (blue_x != NULL) + *blue_x = info_ptr->int_x_blue; + if (blue_y != NULL) + *blue_y = info_ptr->int_y_blue; + return (PNG_INFO_cHRM); + } + return (0); +} +#endif +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) + && file_gamma != NULL) + { + png_debug1(1, "in %s retrieval function\n", "gAMA"); + *file_gamma = (double)info_ptr->gamma; + return (PNG_INFO_gAMA); + } + return (0); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point *int_file_gamma) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) + && int_file_gamma != NULL) + { + png_debug1(1, "in %s retrieval function\n", "gAMA"); + *int_file_gamma = info_ptr->int_gamma; + return (PNG_INFO_gAMA); + } + return (0); +} +#endif +#endif + +#if defined(PNG_sRGB_SUPPORTED) +png_uint_32 PNGAPI +png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB) + && file_srgb_intent != NULL) + { + png_debug1(1, "in %s retrieval function\n", "sRGB"); + *file_srgb_intent = (int)info_ptr->srgb_intent; + return (PNG_INFO_sRGB); + } + return (0); +} +#endif + +#if defined(PNG_iCCP_SUPPORTED) +png_uint_32 PNGAPI +png_get_iCCP(png_structp png_ptr, png_infop info_ptr, + png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) + && name != NULL && profile != NULL && proflen != NULL) + { + png_debug1(1, "in %s retrieval function\n", "iCCP"); + *name = info_ptr->iccp_name; + *profile = info_ptr->iccp_profile; + /* compression_type is a dummy so the API won't have to change + if we introduce multiple compression types later. */ + *proflen = (int)info_ptr->iccp_proflen; + *compression_type = (int)info_ptr->iccp_compression; + return (PNG_INFO_iCCP); + } + return (0); +} +#endif + +#if defined(PNG_sPLT_SUPPORTED) +png_uint_32 PNGAPI +png_get_sPLT(png_structp png_ptr, png_infop info_ptr, + png_sPLT_tpp spalettes) +{ + if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) + { + *spalettes = info_ptr->splt_palettes; + return ((png_uint_32)info_ptr->splt_palettes_num); + } + return (0); +} +#endif + +#if defined(PNG_hIST_SUPPORTED) +png_uint_32 PNGAPI +png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) + && hist != NULL) + { + png_debug1(1, "in %s retrieval function\n", "hIST"); + *hist = info_ptr->hist; + return (PNG_INFO_hIST); + } + return (0); +} +#endif + +png_uint_32 PNGAPI +png_get_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *width, png_uint_32 *height, int *bit_depth, + int *color_type, int *interlace_type, int *compression_type, + int *filter_type) + +{ + if (png_ptr != NULL && info_ptr != NULL && width != NULL && height != NULL && + bit_depth != NULL && color_type != NULL) + { + png_debug1(1, "in %s retrieval function\n", "IHDR"); + *width = info_ptr->width; + *height = info_ptr->height; + *bit_depth = info_ptr->bit_depth; + if (info_ptr->bit_depth < 1 || info_ptr->bit_depth > 16) + png_error(png_ptr, "Invalid bit depth"); + *color_type = info_ptr->color_type; + if (info_ptr->color_type > 6) + png_error(png_ptr, "Invalid color type"); + if (compression_type != NULL) + *compression_type = info_ptr->compression_type; + if (filter_type != NULL) + *filter_type = info_ptr->filter_type; + if (interlace_type != NULL) + *interlace_type = info_ptr->interlace_type; + + /* check for potential overflow of rowbytes */ + if (*width == 0 || *width > PNG_UINT_31_MAX) + png_error(png_ptr, "Invalid image width"); + if (*height == 0 || *height > PNG_UINT_31_MAX) + png_error(png_ptr, "Invalid image height"); + if (info_ptr->width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + { + png_warning(png_ptr, + "Width too large for libpng to process image data."); + } + return (1); + } + return (0); +} + +#if defined(PNG_oFFs_SUPPORTED) +png_uint_32 PNGAPI +png_get_oFFs(png_structp png_ptr, png_infop info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) + && offset_x != NULL && offset_y != NULL && unit_type != NULL) + { + png_debug1(1, "in %s retrieval function\n", "oFFs"); + *offset_x = info_ptr->x_offset; + *offset_y = info_ptr->y_offset; + *unit_type = (int)info_ptr->offset_unit_type; + return (PNG_INFO_oFFs); + } + return (0); +} +#endif + +#if defined(PNG_pCAL_SUPPORTED) +png_uint_32 PNGAPI +png_get_pCAL(png_structp png_ptr, png_infop info_ptr, + png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams, + png_charp *units, png_charpp *params) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) + && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && + nparams != NULL && units != NULL && params != NULL) + { + png_debug1(1, "in %s retrieval function\n", "pCAL"); + *purpose = info_ptr->pcal_purpose; + *X0 = info_ptr->pcal_X0; + *X1 = info_ptr->pcal_X1; + *type = (int)info_ptr->pcal_type; + *nparams = (int)info_ptr->pcal_nparams; + *units = info_ptr->pcal_units; + *params = info_ptr->pcal_params; + return (PNG_INFO_pCAL); + } + return (0); +} +#endif + +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL(png_structp png_ptr, png_infop info_ptr, + int *unit, double *width, double *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_pixel_width; + *height = info_ptr->scal_pixel_height; + return (PNG_INFO_sCAL); + } + return(0); +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int *unit, png_charpp width, png_charpp height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_s_width; + *height = info_ptr->scal_s_height; + return (PNG_INFO_sCAL); + } + return(0); +} +#endif +#endif +#endif + +#if defined(PNG_pHYs_SUPPORTED) +png_uint_32 PNGAPI +png_get_pHYs(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function\n", "pHYs"); + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + } + } + return (retval); +} +#endif + +png_uint_32 PNGAPI +png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette, + int *num_palette) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE) + && palette != NULL) + { + png_debug1(1, "in %s retrieval function\n", "PLTE"); + *palette = info_ptr->palette; + *num_palette = info_ptr->num_palette; + png_debug1(3, "num_palette = %d\n", *num_palette); + return (PNG_INFO_PLTE); + } + return (0); +} + +#if defined(PNG_sBIT_SUPPORTED) +png_uint_32 PNGAPI +png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) + && sig_bit != NULL) + { + png_debug1(1, "in %s retrieval function\n", "sBIT"); + *sig_bit = &(info_ptr->sig_bit); + return (PNG_INFO_sBIT); + } + return (0); +} +#endif + +#if defined(PNG_TEXT_SUPPORTED) +png_uint_32 PNGAPI +png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr, + int *num_text) +{ + if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) + { + png_debug1(1, "in %s retrieval function\n", + (png_ptr->chunk_name[0] == '\0' ? "text" + : (png_const_charp)png_ptr->chunk_name)); + if (text_ptr != NULL) + *text_ptr = info_ptr->text; + if (num_text != NULL) + *num_text = info_ptr->num_text; + return ((png_uint_32)info_ptr->num_text); + } + if (num_text != NULL) + *num_text = 0; + return(0); +} +#endif + +#if defined(PNG_tIME_SUPPORTED) +png_uint_32 PNGAPI +png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) + && mod_time != NULL) + { + png_debug1(1, "in %s retrieval function\n", "tIME"); + *mod_time = &(info_ptr->mod_time); + return (PNG_INFO_tIME); + } + return (0); +} +#endif + +#if defined(PNG_tRNS_SUPPORTED) +png_uint_32 PNGAPI +png_get_tRNS(png_structp png_ptr, png_infop info_ptr, + png_bytep *trans, int *num_trans, png_color_16p *trans_values) +{ + png_uint_32 retval = 0; + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_debug1(1, "in %s retrieval function\n", "tRNS"); + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (trans != NULL) + { + *trans = info_ptr->trans; + retval |= PNG_INFO_tRNS; + } + if (trans_values != NULL) + *trans_values = &(info_ptr->trans_values); + } + else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ + { + if (trans_values != NULL) + { + *trans_values = &(info_ptr->trans_values); + retval |= PNG_INFO_tRNS; + } + if(trans != NULL) + *trans = NULL; + } + if(num_trans != NULL) + { + *num_trans = info_ptr->num_trans; + retval |= PNG_INFO_tRNS; + } + } + return (retval); +} +#endif + +#if defined(PNG_APNG_SUPPORTED) +png_uint_32 PNGAPI +png_get_acTL(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *num_frames, png_uint_32 *num_plays) +{ + png_debug1(1, "in %s retrieval function\n", "acTL"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_acTL) && + num_frames != NULL && num_plays != NULL) + { + *num_frames = info_ptr->num_frames; + *num_plays = info_ptr->num_plays; + return (1); + } + + return (0); +} + +png_uint_32 PNGAPI +png_get_num_frames(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_get_num_frames()\n"); + + if (png_ptr != NULL && info_ptr != NULL) + return (info_ptr->num_frames); + return (0); +} + +png_uint_32 PNGAPI +png_get_num_plays(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_get_num_plays()\n"); + + if (png_ptr != NULL && info_ptr != NULL) + return (info_ptr->num_plays); + return (0); +} + +png_uint_32 PNGAPI +png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *width, png_uint_32 *height, + png_uint_32 *x_offset, png_uint_32 *y_offset, + png_uint_16 *delay_num, png_uint_16 *delay_den, + png_byte *dispose_op, png_byte *blend_op) +{ + png_debug1(1, "in %s retrieval function\n", "fcTL"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_fcTL) && + width != NULL && height != NULL && + x_offset != NULL && x_offset != NULL && + delay_num != NULL && delay_den != NULL && + dispose_op != NULL && blend_op != NULL) + { + *width = info_ptr->next_frame_width; + *height = info_ptr->next_frame_height; + *x_offset = info_ptr->next_frame_x_offset; + *y_offset = info_ptr->next_frame_y_offset; + *delay_num = info_ptr->next_frame_delay_num; + *delay_den = info_ptr->next_frame_delay_den; + *dispose_op = info_ptr->next_frame_dispose_op; + *blend_op = info_ptr->next_frame_blend_op; + return (1); + } + + return (0); +} + +png_uint_32 PNGAPI +png_get_next_frame_width(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_get_next_frame_width()\n"); + + if (png_ptr != NULL && info_ptr != NULL) + return (info_ptr->next_frame_width); + return (0); +} + +png_uint_32 PNGAPI +png_get_next_frame_height(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_get_next_frame_height()\n"); + + if (png_ptr != NULL && info_ptr != NULL) + return (info_ptr->next_frame_height); + return (0); +} + +png_uint_32 PNGAPI +png_get_next_frame_x_offset(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_get_next_frame_x_offset()\n"); + + if (png_ptr != NULL && info_ptr != NULL) + return (info_ptr->next_frame_x_offset); + return (0); +} + +png_uint_32 PNGAPI +png_get_next_frame_y_offset(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_get_next_frame_y_offset()\n"); + + if (png_ptr != NULL && info_ptr != NULL) + return (info_ptr->next_frame_y_offset); + return (0); +} + +png_uint_16 PNGAPI +png_get_next_frame_delay_num(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_get_next_frame_delay_num()\n"); + + if (png_ptr != NULL && info_ptr != NULL) + return (info_ptr->next_frame_delay_num); + return (0); +} + +png_uint_16 PNGAPI +png_get_next_frame_delay_den(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_get_next_frame_delay_den()\n"); + + if (png_ptr != NULL && info_ptr != NULL) + return (info_ptr->next_frame_delay_den); + return (0); +} + +png_byte PNGAPI +png_get_next_frame_dispose_op(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_get_next_frame_dispose_op()\n"); + + if (png_ptr != NULL && info_ptr != NULL) + return (info_ptr->next_frame_dispose_op); + return (0); +} + +png_byte PNGAPI +png_get_next_frame_blend_op(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_get_next_frame_blend_op()\n"); + + if (png_ptr != NULL && info_ptr != NULL) + return (info_ptr->next_frame_blend_op); + return (0); +} + +png_byte PNGAPI +png_get_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_first_frame_is_hidden()\n"); + + if (png_ptr != NULL) + return (png_byte)(png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN); + + return 0; +} +#endif /* PNG_APNG_SUPPORTED */ + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +png_uint_32 PNGAPI +png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr, + png_unknown_chunkpp unknowns) +{ + if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) + { + *unknowns = info_ptr->unknown_chunks; + return ((png_uint_32)info_ptr->unknown_chunks_num); + } + return (0); +} +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +png_byte PNGAPI +png_get_rgb_to_gray_status (png_structp png_ptr) +{ + return (png_byte)(png_ptr? png_ptr->rgb_to_gray_status : 0); +} +#endif + +#if defined(PNG_USER_CHUNKS_SUPPORTED) +png_voidp PNGAPI +png_get_user_chunk_ptr(png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_chunk_ptr : NULL); +} +#endif + +#ifdef PNG_WRITE_SUPPORTED +png_uint_32 PNGAPI +png_get_compression_buffer_size(png_structp png_ptr) +{ + return (png_uint_32)(png_ptr? png_ptr->zbuf_size : 0L); +} +#endif + +#ifdef PNG_ASSEMBLER_CODE_SUPPORTED +#ifndef PNG_1_0_X +/* this function was added to libpng 1.2.0 and should exist by default */ +png_uint_32 PNGAPI +png_get_asm_flags (png_structp png_ptr) +{ + /* obsolete, to be removed from libpng-1.4.0 */ + return (png_ptr? 0L: 0L); +} + +/* this function was added to libpng 1.2.0 and should exist by default */ +png_uint_32 PNGAPI +png_get_asm_flagmask (int flag_select) +{ + /* obsolete, to be removed from libpng-1.4.0 */ + flag_select=flag_select; + return 0L; +} + + /* GRR: could add this: && defined(PNG_MMX_CODE_SUPPORTED) */ +/* this function was added to libpng 1.2.0 */ +png_uint_32 PNGAPI +png_get_mmx_flagmask (int flag_select, int *compilerID) +{ + /* obsolete, to be removed from libpng-1.4.0 */ + flag_select=flag_select; + *compilerID = -1; /* unknown (i.e., no asm/MMX code compiled) */ + return 0L; +} + +/* this function was added to libpng 1.2.0 */ +png_byte PNGAPI +png_get_mmx_bitdepth_threshold (png_structp png_ptr) +{ + /* obsolete, to be removed from libpng-1.4.0 */ + return (png_ptr? 0: 0); +} + +/* this function was added to libpng 1.2.0 */ +png_uint_32 PNGAPI +png_get_mmx_rowbytes_threshold (png_structp png_ptr) +{ + /* obsolete, to be removed from libpng-1.4.0 */ + return (png_ptr? 0L: 0L); +} +#endif /* ?PNG_1_0_X */ +#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* these functions were added to libpng 1.2.6 */ +png_uint_32 PNGAPI +png_get_user_width_max (png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_width_max : 0); +} +png_uint_32 PNGAPI +png_get_user_height_max (png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_height_max : 0); +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + + +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pnghack.h b/kernel/kls_png/ksquirrel-libs-png/pnghack.h new file mode 100644 index 0000000..cba90da --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pnghack.h @@ -0,0 +1,409 @@ +#ifndef PNG_NAMES_HACK +#define PNG_NAMES_HACK + +#define png_access_version_number my_png_access_version_number +#define png_acTL my_png_acTL +#define png_bKGD my_png_bKGD +#define png_build_gamma_table my_png_build_gamma_table +#define png_build_grayscale_palette my_png_build_grayscale_palette +#define png_calculate_crc my_png_calculate_crc +#define png_check_chunk_name my_png_check_chunk_name +#define png_check_keyword my_png_check_keyword +#define png_check_sig my_png_check_sig +#define png_cHRM my_png_cHRM +#define png_chunk_error my_png_chunk_error +#define png_chunk_warning my_png_chunk_warning +#define png_combine_row my_png_combine_row +#define png_convert_from_struct_tm my_png_convert_from_struct_tm +#define png_convert_from_time_t my_png_convert_from_time_t +#define png_convert_to_rfc1123 my_png_convert_to_rfc1123 +#define png_crc_error my_png_crc_error +#define png_crc_finish my_png_crc_finish +#define png_crc_read my_png_crc_read +#define png_create_info_struct my_png_create_info_struct +#define png_create_read_struct my_png_create_read_struct +#define png_create_read_struct_2 my_png_create_read_struct_2 +#define png_create_struct my_png_create_struct +#define png_create_struct_2 my_png_create_struct_2 +#define png_create_write_struct my_png_create_write_struct +#define png_create_write_struct_2 my_png_create_write_struct_2 +#define png_data_freer my_png_data_freer +#define png_decompress_chunk my_png_decompress_chunk +#define png_default_flush my_png_default_flush +#define png_default_read_data my_png_default_read_data +#define png_default_write_data my_png_default_write_data +#define png_destroy_info_struct my_png_destroy_info_struct +#define png_destroy_read_struct my_png_destroy_read_struct +#define png_destroy_struct my_png_destroy_struct +#define png_destroy_struct_2 my_png_destroy_struct_2 +#define png_destroy_write_struct my_png_destroy_write_struct +#define png_digit my_png_digit +#define png_do_background my_png_do_background +#define png_do_bgr my_png_do_bgr +#define png_do_chop my_png_do_chop +#define png_do_dither my_png_do_dither +#define png_do_expand my_png_do_expand +#define png_do_expand_palette my_png_do_expand_palette +#define png_do_gamma my_png_do_gamma +#define png_do_gray_to_rgb my_png_do_gray_to_rgb +#define png_do_invert my_png_do_invert +#define png_do_pack my_png_do_pack +#define png_do_packswap my_png_do_packswap +#define png_do_read_filler my_png_do_read_filler +#define png_do_read_interlace my_png_do_read_interlace +#define png_do_read_intrapixel my_png_do_read_intrapixel +#define png_do_read_invert_alpha my_png_do_read_invert_alpha +#define png_do_read_swap_alpha my_png_do_read_swap_alpha +#define png_do_read_transformations my_png_do_read_transformations +#define png_do_rgb_to_gray my_png_do_rgb_to_gray +#define png_do_shift my_png_do_shift +#define png_do_strip_filler my_png_do_strip_filler +#define png_do_swap my_png_do_swap +#define png_do_unpack my_png_do_unpack +#define png_do_unshift my_png_do_unshift +#define png_do_write_interlace my_png_do_write_interlace +#define png_do_write_intrapixel my_png_do_write_intrapixel +#define png_do_write_invert_alpha my_png_do_write_invert_alpha +#define png_do_write_swap_alpha my_png_do_write_swap_alpha +#define png_do_write_transformations my_png_do_write_transformations +#define png_ensure_fcTL_is_valid my_png_ensure_fcTL_is_valid +#define png_ensure_sequence_number my_png_ensure_sequence_number +#define png_error my_png_error +#define png_fcTL my_png_fcTL +#define png_fdAT my_png_fdAT +#define png_flush my_png_flush +#define png_format_buffer my_png_format_buffer +#define png_free my_png_free +#define png_free_data my_png_free_data +#define png_free_default my_png_free_default +#define png_gAMA my_png_gAMA +#define png_gamma_shift my_png_gamma_shift +#define png_get_acTL my_png_get_acTL +#define png_get_asm_flagmask my_png_get_asm_flagmask +#define png_get_asm_flags my_png_get_asm_flags +#define png_get_bit_depth my_png_get_bit_depth +#define png_get_bKGD my_png_get_bKGD +#define png_get_channels my_png_get_channels +#define png_get_cHRM my_png_get_cHRM +#define png_get_cHRM_fixed my_png_get_cHRM_fixed +#define png_get_color_type my_png_get_color_type +#define png_get_compression_buffer_size my_png_get_compression_buffer_size +#define png_get_compression_type my_png_get_compression_type +#define png_get_copyright my_png_get_copyright +#define png_get_error_ptr my_png_get_error_ptr +#define png_get_filter_type my_png_get_filter_type +#define png_get_first_frame_is_hidden my_png_get_first_frame_is_hidden +#define png_get_gAMA my_png_get_gAMA +#define png_get_gAMA_fixed my_png_get_gAMA_fixed +#define png_get_header_ver my_png_get_header_ver +#define png_get_header_version my_png_get_header_version +#define png_get_hIST my_png_get_hIST +#define png_get_iCCP my_png_get_iCCP +#define png_get_IHDR my_png_get_IHDR +#define png_get_image_height my_png_get_image_height +#define png_get_image_width my_png_get_image_width +#define png_get_int_32 my_png_get_int_32 +#define png_get_interlace_type my_png_get_interlace_type +#define png_get_io_ptr my_png_get_io_ptr +#define png_get_libpng_ver my_png_get_libpng_ver +#define png_get_mem_ptr my_png_get_mem_ptr +#define png_get_mmx_bitdepth_threshold my_png_get_mmx_bitdepth_threshold +#define png_get_mmx_flagmask my_png_get_mmx_flagmask +#define png_get_mmx_rowbytes_threshold my_png_get_mmx_rowbytes_threshold +#define png_get_next_frame_blend_op my_png_get_next_frame_blend_op +#define png_get_next_frame_delay_den my_png_get_next_frame_delay_den +#define png_get_next_frame_delay_num my_png_get_next_frame_delay_num +#define png_get_next_frame_dispose_op my_png_get_next_frame_dispose_op +#define png_get_next_frame_fcTL my_png_get_next_frame_fcTL +#define png_get_next_frame_height my_png_get_next_frame_height +#define png_get_next_frame_width my_png_get_next_frame_width +#define png_get_next_frame_x_offset my_png_get_next_frame_x_offset +#define png_get_next_frame_y_offset my_png_get_next_frame_y_offset +#define png_get_num_frames my_png_get_num_frames +#define png_get_num_plays my_png_get_num_plays +#define png_get_oFFs my_png_get_oFFs +#define png_get_pCAL my_png_get_pCAL +#define png_get_pHYs my_png_get_pHYs +#define png_get_pixel_aspect_ratio my_png_get_pixel_aspect_ratio +#define png_get_pixels_per_meter my_png_get_pixels_per_meter +#define png_get_PLTE my_png_get_PLTE +#define png_get_progressive_ptr my_png_get_progressive_ptr +#define png_get_rgb_to_gray_status my_png_get_rgb_to_gray_status +#define png_get_rowbytes my_png_get_rowbytes +#define png_get_rows my_png_get_rows +#define png_get_sBIT my_png_get_sBIT +#define png_get_sCAL my_png_get_sCAL +#define png_get_signature my_png_get_signature +#define png_get_sPLT my_png_get_sPLT +#define png_get_sRGB my_png_get_sRGB +#define png_get_text my_png_get_text +#define png_get_tIME my_png_get_tIME +#define png_get_tRNS my_png_get_tRNS +#define png_get_uint_16 my_png_get_uint_16 +#define png_get_uint_31 my_png_get_uint_31 +#define png_get_uint_32 my_png_get_uint_32 +#define png_get_unknown_chunks my_png_get_unknown_chunks +#define png_get_user_chunk_ptr my_png_get_user_chunk_ptr +#define png_get_user_height_max my_png_get_user_height_max +#define png_get_user_transform_ptr my_png_get_user_transform_ptr +#define png_get_user_width_max my_png_get_user_width_max +#define png_get_valid my_png_get_valid +#define png_get_x_offset_microns my_png_get_x_offset_microns +#define png_get_x_offset_pixels my_png_get_x_offset_pixels +#define png_get_x_pixels_per_meter my_png_get_x_pixels_per_meter +#define png_get_y_offset_microns my_png_get_y_offset_microns +#define png_get_y_offset_pixels my_png_get_y_offset_pixels +#define png_get_y_pixels_per_meter my_png_get_y_pixels_per_meter +#define png_handle_acTL my_png_handle_acTL +#define png_handle_as_unknown my_png_handle_as_unknown +#define png_handle_bKGD my_png_handle_bKGD +#define png_handle_cHRM my_png_handle_cHRM +#define png_handle_fcTL my_png_handle_fcTL +#define png_handle_fdAT my_png_handle_fdAT +#define png_handle_gAMA my_png_handle_gAMA +#define png_handle_hIST my_png_handle_hIST +#define png_handle_iCCP my_png_handle_iCCP +#define png_handle_IEND my_png_handle_IEND +#define png_handle_IHDR my_png_handle_IHDR +#define png_handle_oFFs my_png_handle_oFFs +#define png_handle_pCAL my_png_handle_pCAL +#define png_handle_pHYs my_png_handle_pHYs +#define png_handle_PLTE my_png_handle_PLTE +#define png_handle_sBIT my_png_handle_sBIT +#define png_handle_sCAL my_png_handle_sCAL +#define png_handle_sPLT my_png_handle_sPLT +#define png_handle_sRGB my_png_handle_sRGB +#define png_handle_tEXt my_png_handle_tEXt +#define png_handle_tIME my_png_handle_tIME +#define png_handle_tRNS my_png_handle_tRNS +#define png_handle_unknown my_png_handle_unknown +#define png_handle_zTXt my_png_handle_zTXt +#define png_have_info my_png_have_info +#define png_hIST my_png_hIST +#define png_iCCP my_png_iCCP +#define png_IDAT my_png_IDAT +#define png_IEND my_png_IEND +#define png_IHDR my_png_IHDR +#define png_info_destroy my_png_info_destroy +#define png_info_init my_png_info_init +#define png_info_init_3 my_png_info_init_3 +#define png_init_io my_png_init_io +#define png_init_read_transformations my_png_init_read_transformations +#define png_iTXt my_png_iTXt +#define png_libpng_ver my_png_libpng_ver +#define png_malloc my_png_malloc +#define png_malloc_default my_png_malloc_default +#define png_malloc_warn my_png_malloc_warn +#define png_memcpy_check my_png_memcpy_check +#define png_memset_check my_png_memset_check +#define png_mmx_support my_png_mmx_support +#define png_oFFs my_png_oFFs +#define png_pass_dsp_mask my_png_pass_dsp_mask +#define png_pass_inc my_png_pass_inc +#define png_pass_mask my_png_pass_mask +#define png_pass_start my_png_pass_start +#define png_pass_yinc my_png_pass_yinc +#define png_pass_ystart my_png_pass_ystart +#define png_pCAL my_png_pCAL +#define png_permit_empty_plte my_png_permit_empty_plte +#define png_permit_mng_features my_png_permit_mng_features +#define png_pHYs my_png_pHYs +#define png_PLTE my_png_PLTE +#define png_process_data my_png_process_data +#define png_process_IDAT_data my_png_process_IDAT_data +#define png_process_some_data my_png_process_some_data +#define png_progressive_combine_row my_png_progressive_combine_row +#define png_progressive_read_reset my_png_progressive_read_reset +#define png_push_crc_finish my_png_push_crc_finish +#define png_push_crc_skip my_png_push_crc_skip +#define png_push_fill_buffer my_png_push_fill_buffer +#define png_push_handle_tEXt my_png_push_handle_tEXt +#define png_push_handle_unknown my_png_push_handle_unknown +#define png_push_handle_zTXt my_png_push_handle_zTXt +#define png_push_have_end my_png_push_have_end +#define png_push_have_info my_png_push_have_info +#define png_push_have_row my_png_push_have_row +#define png_push_process_row my_png_push_process_row +#define png_push_read_chunk my_png_push_read_chunk +#define png_push_read_IDAT my_png_push_read_IDAT +#define png_push_read_sig my_png_push_read_sig +#define png_push_read_tEXt my_png_push_read_tEXt +#define png_push_read_zTXt my_png_push_read_zTXt +#define png_push_restore_buffer my_png_push_restore_buffer +#define png_push_save_buffer my_png_push_save_buffer +#define png_read_data my_png_read_data +#define png_read_destroy my_png_read_destroy +#define png_read_end my_png_read_end +#define png_read_filter_row my_png_read_filter_row +#define png_read_finish_row my_png_read_finish_row +#define png_read_frame_head my_png_read_frame_head +#define png_read_image my_png_read_image +#define png_read_info my_png_read_info +#define png_read_init my_png_read_init +#define png_read_init_2 my_png_read_init_2 +#define png_read_init_3 my_png_read_init_3 +#define png_read_png my_png_read_png +#define png_read_push_finish_row my_png_read_push_finish_row +#define png_read_reinit my_png_read_reinit +#define png_read_reset my_png_read_reset +#define png_read_row my_png_read_row +#define png_read_rows my_png_read_rows +#define png_read_start_row my_png_read_start_row +#define png_read_transform_info my_png_read_transform_info +#define png_read_update_info my_png_read_update_info +#define png_reset_crc my_png_reset_crc +#define png_reset_zstream my_png_reset_zstream +#define png_save_int_32 my_png_save_int_32 +#define png_save_uint_16 my_png_save_uint_16 +#define png_save_uint_32 my_png_save_uint_32 +#define png_sBIT my_png_sBIT +#define png_sCAL my_png_sCAL +#define png_set_acTL my_png_set_acTL +#define png_set_add_alpha my_png_set_add_alpha +#define png_set_asm_flags my_png_set_asm_flags +#define png_set_background my_png_set_background +#define png_set_bgr my_png_set_bgr +#define png_set_bKGD my_png_set_bKGD +#define png_set_cHRM my_png_set_cHRM +#define png_set_cHRM_fixed my_png_set_cHRM_fixed +#define png_set_compression_buffer_size my_png_set_compression_buffer_size +#define png_set_compression_level my_png_set_compression_level +#define png_set_compression_mem_level my_png_set_compression_mem_level +#define png_set_compression_method my_png_set_compression_method +#define png_set_compression_strategy my_png_set_compression_strategy +#define png_set_compression_window_bits my_png_set_compression_window_bits +#define png_set_crc_action my_png_set_crc_action +#define png_set_dither my_png_set_dither +#define png_set_error_fn my_png_set_error_fn +#define png_set_expand my_png_set_expand +#define png_set_expand_gray_1_2_4_to_8 my_png_set_expand_gray_1_2_4_to_8 +#define png_set_filler my_png_set_filler +#define png_set_filter my_png_set_filter +#define png_set_filter_heuristics my_png_set_filter_heuristics +#define png_set_first_frame_is_hidden my_png_set_first_frame_is_hidden +#define png_set_flush my_png_set_flush +#define png_set_gAMA my_png_set_gAMA +#define png_set_gAMA_fixed my_png_set_gAMA_fixed +#define png_set_gamma my_png_set_gamma +#define png_set_gray_1_2_4_to_8 my_png_set_gray_1_2_4_to_8 +#define png_set_gray_to_rgb my_png_set_gray_to_rgb +#define png_set_hIST my_png_set_hIST +#define png_set_iCCP my_png_set_iCCP +#define png_set_IHDR my_png_set_IHDR +#define png_set_interlace_handling my_png_set_interlace_handling +#define png_set_invalid my_png_set_invalid +#define png_set_invert_alpha my_png_set_invert_alpha +#define png_set_invert_mono my_png_set_invert_mono +#define png_set_keep_unknown_chunks my_png_set_keep_unknown_chunks +#define png_set_mem_fn my_png_set_mem_fn +#define png_set_mmx_thresholds my_png_set_mmx_thresholds +#define png_set_next_frame_fcTL my_png_set_next_frame_fcTL +#define png_set_oFFs my_png_set_oFFs +#define png_set_packing my_png_set_packing +#define png_set_packswap my_png_set_packswap +#define png_set_palette_to_rgb my_png_set_palette_to_rgb +#define png_set_pCAL my_png_set_pCAL +#define png_set_pHYs my_png_set_pHYs +#define png_set_PLTE my_png_set_PLTE +#define png_set_progressive_frame_fn my_png_set_progressive_frame_fn +#define png_set_progressive_read_fn my_png_set_progressive_read_fn +#define png_set_read_fn my_png_set_read_fn +#define png_set_read_status_fn my_png_set_read_status_fn +#define png_set_read_user_chunk_fn my_png_set_read_user_chunk_fn +#define png_set_read_user_transform_fn my_png_set_read_user_transform_fn +#define png_set_rgb_to_gray my_png_set_rgb_to_gray +#define png_set_rgb_to_gray_fixed my_png_set_rgb_to_gray_fixed +#define png_set_rows my_png_set_rows +#define png_set_sBIT my_png_set_sBIT +#define png_set_sCAL my_png_set_sCAL +#define png_set_shift my_png_set_shift +#define png_set_sig_bytes my_png_set_sig_bytes +#define png_set_sPLT my_png_set_sPLT +#define png_set_sRGB my_png_set_sRGB +#define png_set_sRGB_gAMA_and_cHRM my_png_set_sRGB_gAMA_and_cHRM +#define png_set_strip_16 my_png_set_strip_16 +#define png_set_strip_alpha my_png_set_strip_alpha +#define png_set_strip_error_numbers my_png_set_strip_error_numbers +#define png_set_swap my_png_set_swap +#define png_set_swap_alpha my_png_set_swap_alpha +#define png_set_text my_png_set_text +#define png_set_text_2 my_png_set_text_2 +#define png_set_tIME my_png_set_tIME +#define png_set_tRNS my_png_set_tRNS +#define png_set_tRNS_to_alpha my_png_set_tRNS_to_alpha +#define png_set_unknown_chunk_location my_png_set_unknown_chunk_location +#define png_set_unknown_chunks my_png_set_unknown_chunks +#define png_set_user_limits my_png_set_user_limits +#define png_set_user_transform_info my_png_set_user_transform_info +#define png_set_write_fn my_png_set_write_fn +#define png_set_write_status_fn my_png_set_write_status_fn +#define png_set_write_user_transform_fn my_png_set_write_user_transform_fn +#define png_sig my_png_sig +#define png_sig_cmp my_png_sig_cmp +#define png_sPLT my_png_sPLT +#define png_sRGB my_png_sRGB +#define png_start_read_image my_png_start_read_image +#define png_tEXt my_png_tEXt +#define png_text_compress my_png_text_compress +#define png_tIME my_png_tIME +#define png_tRNS my_png_tRNS +#define png_warning my_png_warning +#define png_write_acTL my_png_write_acTL +#define png_write_bKGD my_png_write_bKGD +#define png_write_cHRM my_png_write_cHRM +#define png_write_cHRM_fixed my_png_write_cHRM_fixed +#define png_write_chunk my_png_write_chunk +#define png_write_chunk_data my_png_write_chunk_data +#define png_write_chunk_end my_png_write_chunk_end +#define png_write_chunk_start my_png_write_chunk_start +#define png_write_compressed_data_out my_png_write_compressed_data_out +#define png_write_data my_png_write_data +#define png_write_destroy my_png_write_destroy +#define png_write_end my_png_write_end +#define png_write_fcTL my_png_write_fcTL +#define png_write_filtered_row my_png_write_filtered_row +#define png_write_find_filter my_png_write_find_filter +#define png_write_finish_row my_png_write_finish_row +#define png_write_flush my_png_write_flush +#define png_write_frame_head my_png_write_frame_head +#define png_write_frame_tail my_png_write_frame_tail +#define png_write_gAMA my_png_write_gAMA +#define png_write_gAMA_fixed my_png_write_gAMA_fixed +#define png_write_hIST my_png_write_hIST +#define png_write_iCCP my_png_write_iCCP +#define png_write_IDAT my_png_write_IDAT +#define png_write_IEND my_png_write_IEND +#define png_write_IHDR my_png_write_IHDR +#define png_write_image my_png_write_image +#define png_write_info my_png_write_info +#define png_write_info_before_PLTE my_png_write_info_before_PLTE +#define png_write_init my_png_write_init +#define png_write_init_2 my_png_write_init_2 +#define png_write_init_3 my_png_write_init_3 +#define png_write_oFFs my_png_write_oFFs +#define png_write_pCAL my_png_write_pCAL +#define png_write_pHYs my_png_write_pHYs +#define png_write_PLTE my_png_write_PLTE +#define png_write_png my_png_write_png +#define png_write_reinit my_png_write_reinit +#define png_write_reset my_png_write_reset +#define png_write_row my_png_write_row +#define png_write_rows my_png_write_rows +#define png_write_sBIT my_png_write_sBIT +#define png_write_sCAL my_png_write_sCAL +#define png_write_sig my_png_write_sig +#define png_write_sPLT my_png_write_sPLT +#define png_write_sRGB my_png_write_sRGB +#define png_write_start_row my_png_write_start_row +#define png_write_tEXt my_png_write_tEXt +#define png_write_tIME my_png_write_tIME +#define png_write_tRNS my_png_write_tRNS +#define png_write_zTXt my_png_write_zTXt +#define png_zalloc my_png_zalloc +#define png_zfree my_png_zfree +#define png_zTXt my_png_zTXt +#define short_months my_short_months +#define twobppswaptable my_twobppswaptable +#define onebppswaptable my_onebppswaptable + +#endif diff --git a/kernel/kls_png/ksquirrel-libs-png/pngmem.c b/kernel/kls_png/ksquirrel-libs-png/pngmem.c new file mode 100644 index 0000000..248060f --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngmem.c @@ -0,0 +1,608 @@ + +/* pngmem.c - stub functions for memory allocation + * + * Last changed in libpng 1.2.13 November 13, 2006 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2006 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all memory allocation. Users who + * need special memory handling are expected to supply replacement + * functions for png_malloc() and png_free(), and to use + * png_create_read_struct_2() and png_create_write_struct_2() to + * identify the replacement functions. + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +/* Borland DOS special memory handler */ +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* if you change this, be sure to change the one in png.h also */ + +/* Allocate memory for a png_struct. The malloc and memset can be replaced + by a single call to calloc() if this is thought to improve performance. */ +png_voidp /* PRIVATE */ +png_create_struct(int type) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL)); +} + +/* Alternate version of png_create_struct, for use with user-defined malloc. */ +png_voidp /* PRIVATE */ +png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + else + return (png_get_copyright(NULL)); + +#ifdef PNG_USER_MEM_SUPPORTED + if(malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size); + } + else +#endif /* PNG_USER_MEM_SUPPORTED */ + struct_ptr = (png_voidp)farmalloc(size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + return (struct_ptr); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +#endif + if (struct_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + if(free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } +#endif /* PNG_USER_MEM_SUPPORTED */ + farfree (struct_ptr); + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * Borland seems to have a problem in DOS mode for exactly 64K. + * It gives you a segment with an offset of 8 (perhaps to store its + * memory stuff). zlib doesn't like this at all, so we have to + * detect and deal with it. This code should not be needed in + * Windows or OS/2 modes, and only in 16 bit mode. This code has + * been updated by Alexander Lehmann for version 0.89 to waste less + * memory. + * + * Note that we can't use png_size_t for the "size" declaration, + * since on some systems a png_size_t is a 16-bit quantity, and as a + * result, we would be truncating potentially larger memory requests + * (which should cause a fatal error) and introducing major problems. + */ + +png_voidp PNGAPI +png_malloc(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; + + if (png_ptr == NULL || size == 0) + return (NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + if(png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + else + ret = (png_malloc_default(png_ptr, size)); + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory!"); + return (ret); +} + +png_voidp PNGAPI +png_malloc_default(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || size == 0) + return (NULL); + +#ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { + png_warning(png_ptr, "Cannot Allocate > 64K"); + ret = NULL; + } + else +#endif + + if (size != (size_t)size) + ret = NULL; + else if (size == (png_uint_32)65536L) + { + if (png_ptr->offset_table == NULL) + { + /* try to see if we need to do any of this fancy stuff */ + ret = farmalloc(size); + if (ret == NULL || ((png_size_t)ret & 0xffff)) + { + int num_blocks; + png_uint_32 total_size; + png_bytep table; + int i; + png_byte huge * hptr; + + if (ret != NULL) + { + farfree(ret); + ret = NULL; + } + + if(png_ptr->zlib_window_bits > 14) + num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); + else + num_blocks = 1; + if (png_ptr->zlib_mem_level >= 7) + num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); + else + num_blocks++; + + total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16; + + table = farmalloc(total_size); + + if (table == NULL) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */ + else + png_warning(png_ptr, "Out Of Memory."); +#endif + return (NULL); + } + + if ((png_size_t)table & 0xfff0) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, + "Farmalloc didn't return normalized pointer"); + else + png_warning(png_ptr, + "Farmalloc didn't return normalized pointer"); +#endif + return (NULL); + } + + png_ptr->offset_table = table; + png_ptr->offset_table_ptr = farmalloc(num_blocks * + png_sizeof (png_bytep)); + + if (png_ptr->offset_table_ptr == NULL) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of memory."); /* Note "O" and "M" */ + else + png_warning(png_ptr, "Out Of memory."); +#endif + return (NULL); + } + + hptr = (png_byte huge *)table; + if ((png_size_t)hptr & 0xf) + { + hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); + hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */ + } + for (i = 0; i < num_blocks; i++) + { + png_ptr->offset_table_ptr[i] = (png_bytep)hptr; + hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */ + } + + png_ptr->offset_table_number = num_blocks; + png_ptr->offset_table_count = 0; + png_ptr->offset_table_count_free = 0; + } + } + + if (png_ptr->offset_table_count >= png_ptr->offset_table_number) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory."); /* Note "o" and "M" */ + else + png_warning(png_ptr, "Out of Memory."); +#endif + return (NULL); + } + + ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++]; + } + else + ret = farmalloc(size); + +#ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL) + { + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */ + else + png_warning(png_ptr, "Out of memory."); /* Note "o" and "m" */ + } +#endif + + return (ret); +} + +/* free a pointer allocated by png_malloc(). In the default + configuration, png_ptr is not used, but is passed in case it + is needed. If ptr is NULL, return without taking any action. */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + else png_free_default(png_ptr, ptr); +} + +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + + if(png_ptr == NULL) return; + + if (png_ptr->offset_table != NULL) + { + int i; + + for (i = 0; i < png_ptr->offset_table_count; i++) + { + if (ptr == png_ptr->offset_table_ptr[i]) + { + ptr = NULL; + png_ptr->offset_table_count_free++; + break; + } + } + if (png_ptr->offset_table_count_free == png_ptr->offset_table_count) + { + farfree(png_ptr->offset_table); + farfree(png_ptr->offset_table_ptr); + png_ptr->offset_table = NULL; + png_ptr->offset_table_ptr = NULL; + } + } + + if (ptr != NULL) + { + farfree(ptr); + } +} + +#else /* Not the Borland DOS special memory handler */ + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +png_voidp /* PRIVATE */ +png_create_struct(int type) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL)); +} + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +png_voidp /* PRIVATE */ +png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + else + return (NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + if(malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + return (struct_ptr); + } +#endif /* PNG_USER_MEM_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(__FLAT__) + struct_ptr = (png_voidp)farmalloc(size); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + struct_ptr = (png_voidp)halloc(size,1); +# else + struct_ptr = (png_voidp)malloc(size); +# endif +#endif + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + + return (struct_ptr); +} + + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + if (struct_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + if(free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } +#endif /* PNG_USER_MEM_SUPPORTED */ +#if defined(__TURBOC__) && !defined(__FLAT__) + farfree(struct_ptr); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(struct_ptr); +# else + free(struct_ptr); +# endif +#endif + } +} + +/* Allocate memory. For reasonable files, size should never exceed + 64K. However, zlib may allocate more then 64K if you don't tell + it not to. See zconf.h and png.h for more information. zlib does + need to allocate exactly 64K, so whatever you call here must + have the ability to do that. */ + +png_voidp PNGAPI +png_malloc(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr == NULL || size == 0) + return (NULL); + + if(png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + else + ret = (png_malloc_default(png_ptr, size)); + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory!"); + return (ret); +} + +png_voidp PNGAPI +png_malloc_default(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || size == 0) + return (NULL); + +#ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { +#ifndef PNG_USER_MEM_SUPPORTED + if(png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Cannot Allocate > 64K"); + else +#endif + return NULL; + } +#endif + + /* Check for overflow */ +#if defined(__TURBOC__) && !defined(__FLAT__) + if (size != (unsigned long)size) + ret = NULL; + else + ret = farmalloc(size); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + if (size != (unsigned long)size) + ret = NULL; + else + ret = halloc(size, 1); +# else + if (size != (size_t)size) + ret = NULL; + else + ret = malloc((size_t)size); +# endif +#endif + +#ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory"); +#endif + + return (ret); +} + +/* Free a pointer allocated by png_malloc(). If ptr is NULL, return + without taking any action. */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + else png_free_default(png_ptr, ptr); +} +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#endif /* PNG_USER_MEM_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(__FLAT__) + farfree(ptr); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(ptr); +# else + free(ptr); +# endif +#endif +} + +#endif /* Not Borland DOS special memory handler */ + +#if defined(PNG_1_0_X) +# define png_malloc_warn png_malloc +#else +/* This function was added at libpng version 1.2.3. The png_malloc_warn() + * function will set up png_malloc() to issue a png_warning and return NULL + * instead of issuing a png_error, if it fails to allocate the requested + * memory. + */ +png_voidp PNGAPI +png_malloc_warn(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ptr; + png_uint_32 save_flags; + if(png_ptr == NULL) return (NULL); + + save_flags=png_ptr->flags; + png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, size); + png_ptr->flags=save_flags; + return(ptr); +} +#endif + +png_voidp PNGAPI +png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2, + png_uint_32 length) +{ + png_size_t size; + + size = (png_size_t)length; + if ((png_uint_32)size != length) + png_error(png_ptr,"Overflow in png_memcpy_check."); + + return(png_memcpy (s1, s2, size)); +} + +png_voidp PNGAPI +png_memset_check (png_structp png_ptr, png_voidp s1, int value, + png_uint_32 length) +{ + png_size_t size; + + size = (png_size_t)length; + if ((png_uint_32)size != length) + png_error(png_ptr,"Overflow in png_memset_check."); + + return (png_memset (s1, value, size)); + +} + +#ifdef PNG_USER_MEM_SUPPORTED +/* This function is called when the application wants to use another method + * of allocating and freeing memory. + */ +void PNGAPI +png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr + malloc_fn, png_free_ptr free_fn) +{ + if(png_ptr != NULL) { + png_ptr->mem_ptr = mem_ptr; + png_ptr->malloc_fn = malloc_fn; + png_ptr->free_fn = free_fn; + } +} + +/* This function returns a pointer to the mem_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_mem_ptr(png_structp png_ptr) +{ + if(png_ptr == NULL) return (NULL); + return ((png_voidp)png_ptr->mem_ptr); +} +#endif /* PNG_USER_MEM_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pngpread.c b/kernel/kls_png/ksquirrel-libs-png/pngpread.c new file mode 100644 index 0000000..3dd0f06 --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngpread.c @@ -0,0 +1,1773 @@ + +/* pngpread.c - read a png file in push mode + * + * Last changed in libpng 1.2.20 September 8, 2007 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2007 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + +/* push model modes */ +#define PNG_READ_SIG_MODE 0 +#define PNG_READ_CHUNK_MODE 1 +#define PNG_READ_IDAT_MODE 2 +#define PNG_SKIP_MODE 3 +#define PNG_READ_tEXt_MODE 4 +#define PNG_READ_zTXt_MODE 5 +#define PNG_READ_DONE_MODE 6 +#define PNG_READ_iTXt_MODE 7 +#define PNG_ERROR_MODE 8 + +void PNGAPI +png_process_data(png_structp png_ptr, png_infop info_ptr, + png_bytep buffer, png_size_t buffer_size) +{ + if(png_ptr == NULL) return; + png_push_restore_buffer(png_ptr, buffer, buffer_size); + + while (png_ptr->buffer_size) + { + png_process_some_data(png_ptr, info_ptr); + } +} + +/* What we do with the incoming data depends on what we were previously + * doing before we ran out of data... + */ +void /* PRIVATE */ +png_process_some_data(png_structp png_ptr, png_infop info_ptr) +{ + if(png_ptr == NULL) return; + switch (png_ptr->process_mode) + { + case PNG_READ_SIG_MODE: + { + png_push_read_sig(png_ptr, info_ptr); + break; + } + case PNG_READ_CHUNK_MODE: + { + png_push_read_chunk(png_ptr, info_ptr); + break; + } + case PNG_READ_IDAT_MODE: + { + png_push_read_IDAT(png_ptr); + break; + } +#if defined(PNG_READ_tEXt_SUPPORTED) + case PNG_READ_tEXt_MODE: + { + png_push_read_tEXt(png_ptr, info_ptr); + break; + } +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + case PNG_READ_zTXt_MODE: + { + png_push_read_zTXt(png_ptr, info_ptr); + break; + } +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + case PNG_READ_iTXt_MODE: + { + png_push_read_iTXt(png_ptr, info_ptr); + break; + } +#endif + case PNG_SKIP_MODE: + { + png_push_crc_finish(png_ptr); + break; + } + default: + { + png_ptr->buffer_size = 0; + break; + } + } +} + +/* Read any remaining signature bytes from the stream and compare them with + * the correct PNG signature. It is possible that this routine is called + * with bytes already read from the signature, either because they have been + * checked by the calling application, or because of multiple calls to this + * routine. + */ +void /* PRIVATE */ +png_push_read_sig(png_structp png_ptr, png_infop info_ptr) +{ + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; + + if (png_ptr->buffer_size < num_to_check) + { + num_to_check = png_ptr->buffer_size; + } + + png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), + num_to_check); + png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes+num_to_check); + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + else + { + if (png_ptr->sig_bytes >= 8) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + } +} + +void /* PRIVATE */ +png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IHDR; + PNG_CONST PNG_IDAT; + PNG_CONST PNG_IEND; + PNG_CONST PNG_PLTE; +#if defined(PNG_READ_bKGD_SUPPORTED) + PNG_CONST PNG_bKGD; +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + PNG_CONST PNG_cHRM; +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + PNG_CONST PNG_gAMA; +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + PNG_CONST PNG_hIST; +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + PNG_CONST PNG_iCCP; +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + PNG_CONST PNG_iTXt; +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + PNG_CONST PNG_oFFs; +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + PNG_CONST PNG_pCAL; +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + PNG_CONST PNG_pHYs; +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + PNG_CONST PNG_sBIT; +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + PNG_CONST PNG_sCAL; +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + PNG_CONST PNG_sRGB; +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + PNG_CONST PNG_sPLT; +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + PNG_CONST PNG_tEXt; +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + PNG_CONST PNG_tIME; +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + PNG_CONST PNG_tRNS; +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + PNG_CONST PNG_zTXt; +#endif +#if defined(PNG_READ_APNG_SUPPORTED) + PNG_CONST PNG_acTL; + PNG_CONST PNG_fcTL; + PNG_CONST PNG_fdAT; +#endif +#endif /* PNG_USE_LOCAL_ARRAYS */ + /* First we make sure we have enough data for the 4 byte chunk name + * and the 4 byte chunk length before proceeding with decoding the + * chunk data. To fully decode each of these chunks, we also make + * sure we have enough data in the buffer for the 4 byte CRC at the + * end of every chunk (except IDAT, which is handled separately). + */ + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + } + +#if defined(PNG_READ_APNG_SUPPORTED) + if (png_ptr->num_frames_read > 0 && + png_ptr->num_frames_read < info_ptr->num_frames) + { + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + /* discard trailing IDATs for the first frame */ + if (png_ptr->mode & PNG_HAVE_fcTL || png_ptr->num_frames_read > 1) + png_error(png_ptr, "out of place IDAT"); + + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_crc_skip(png_ptr, png_ptr->push_length); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + return; + } + else if (!png_memcmp(png_ptr->chunk_name, png_fdAT, 4)) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + png_ensure_sequence_number(png_ptr, 4); + + if (!(png_ptr->mode & PNG_HAVE_fcTL)) + { + /* discard trailing fdATs for frames other than the first */ + if (png_ptr->num_frames_read < 2) + png_error(png_ptr, "out of place fdAT"); + + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_crc_skip(png_ptr, png_ptr->push_length); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + return; + } + else + { + /* frame data follows */ + png_ptr->idat_size = png_ptr->push_length - 4; + png_ptr->mode |= PNG_HAVE_IDAT; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + + return; + } + } + else if(!png_memcmp(png_ptr->chunk_name, png_fcTL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_read_reset(png_ptr); + png_ptr->mode &= ~PNG_HAVE_fcTL; + + png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length); + + if (!(png_ptr->mode & PNG_HAVE_fcTL)) + png_error(png_ptr, "missing required fcTL chunk"); + + png_read_reinit(png_ptr, info_ptr); + png_progressive_read_reset(png_ptr); + + if (png_ptr->frame_info_fn != NULL) + (*(png_ptr->frame_info_fn))(png_ptr, png_ptr->num_frames_read); + + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + + return; + } + else + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_warning(png_ptr, "Skipped (ignored) a chunk " + "between APNG chunks"); + png_push_crc_skip(png_ptr, png_ptr->push_length); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + return; + } + + return; + } +#endif /* PNG_READ_APNG_SUPPORTED */ + + if (!png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4)) + if(png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); + } + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); + + png_ptr->process_mode = PNG_READ_DONE_MODE; + png_push_have_end(png_ptr, info_ptr); + } +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + } + } +#endif + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); + } + else if (!png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4)) + { + /* If we reach an IDAT chunk, this means we have read all of the + * header chunks, and we can start reading the image (or if this + * is called after the image has been read - we have an error). + */ + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + { + if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + if (png_ptr->push_length == 0) + return; + + if (png_ptr->mode & PNG_AFTER_IDAT) + png_error(png_ptr, "Too many IDAT's found"); + } + +#if defined(PNG_READ_APNG_SUPPORTED) + png_have_info(png_ptr, info_ptr); +#endif + png_ptr->idat_size = png_ptr->push_length; + png_ptr->mode |= PNG_HAVE_IDAT; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + png_push_have_info(png_ptr, info_ptr); + png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; + png_ptr->zstream.next_out = png_ptr->row_buf; + return; + } +#if defined(PNG_READ_gAMA_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_bKGD_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_APNG_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_acTL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length); + } + else if (!png_memcmp(png_ptr->chunk_name, png_fcTL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length); + } + else if (!png_memcmp(png_ptr->chunk_name, png_fdAT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_fdAT(png_ptr, info_ptr, png_ptr->push_length); + } +#endif /* PNG_READ_APNG_SUPPORTED */ + else + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + } + + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; +} + +void /* PRIVATE */ +png_push_crc_skip(png_structp png_ptr, png_uint_32 skip) +{ + png_ptr->process_mode = PNG_SKIP_MODE; + png_ptr->skip_length = skip; +} + +void /* PRIVATE */ +png_push_crc_finish(png_structp png_ptr) +{ + if (png_ptr->skip_length && png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size) + save_size = (png_size_t)png_ptr->skip_length; + else + save_size = png_ptr->save_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->skip_length -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->skip_length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size) + save_size = (png_size_t)png_ptr->skip_length; + else + save_size = png_ptr->current_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->skip_length -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->skip_length) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } +} + +void PNGAPI +png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +{ + png_bytep ptr; + + if(png_ptr == NULL) return; + ptr = buffer; + if (png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->save_buffer_size) + save_size = length; + else + save_size = png_ptr->save_buffer_size; + + png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size); + length -= save_size; + ptr += save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->current_buffer_size) + save_size = length; + else + save_size = png_ptr->current_buffer_size; + + png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size); + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } +} + +void /* PRIVATE */ +png_push_save_buffer(png_structp png_ptr) +{ + if (png_ptr->save_buffer_size) + { + if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) + { + png_size_t i,istop; + png_bytep sp; + png_bytep dp; + + istop = png_ptr->save_buffer_size; + for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; + i < istop; i++, sp++, dp++) + { + *dp = *sp; + } + } + } + if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > + png_ptr->save_buffer_max) + { + png_size_t new_max; + png_bytep old_buffer; + + if (png_ptr->save_buffer_size > PNG_SIZE_MAX - + (png_ptr->current_buffer_size + 256)) + { + png_error(png_ptr, "Potential overflow of save_buffer"); + } + new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; + old_buffer = png_ptr->save_buffer; + png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr, + (png_uint_32)new_max); + png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); + png_free(png_ptr, old_buffer); + png_ptr->save_buffer_max = new_max; + } + if (png_ptr->current_buffer_size) + { + png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, + png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); + png_ptr->save_buffer_size += png_ptr->current_buffer_size; + png_ptr->current_buffer_size = 0; + } + png_ptr->save_buffer_ptr = png_ptr->save_buffer; + png_ptr->buffer_size = 0; +} + +void /* PRIVATE */ +png_push_restore_buffer(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + png_ptr->current_buffer = buffer; + png_ptr->current_buffer_size = buffer_length; + png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; + png_ptr->current_buffer_ptr = png_ptr->current_buffer; +} + +void /* PRIVATE */ +png_push_read_IDAT(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IDAT; +#if defined(PNG_READ_APNG_SUPPORTED) + PNG_fdAT; + PNG_IEND; +#endif +#endif + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 12) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + +#if defined(PNG_READ_APNG_SUPPORTED) + if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_fdAT, 4) + && png_ptr->num_frames_read > 0) + { + if (png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + if (png_ptr->frame_end_fn != NULL) + (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read); + png_ptr->num_frames_read++; + return; + } + else + { + if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + png_error(png_ptr, "Not enough image data"); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_warning(png_ptr, "Skipping (ignoring) a chunk between " + "APNG chunks"); + png_crc_finish(png_ptr, png_ptr->push_length); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + return; + } + } + else +#endif + if ( png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4) + && (png_ptr->num_frames_read == 0) ) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_error(png_ptr, "Not enough compressed data"); +#if defined(PNG_READ_APNG_SUPPORTED) + if (png_ptr->frame_end_fn != NULL) + (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read); + png_ptr->num_frames_read++; +#endif + return; + } + + png_ptr->idat_size = png_ptr->push_length; + +#if defined(PNG_READ_APNG_SUPPORTED) + if(png_ptr->num_frames_read > 0) + { + png_ensure_sequence_number(png_ptr, 4); + png_ptr->idat_size -= 4; + } +#endif + } + if (png_ptr->idat_size && png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size) + { + save_size = (png_size_t)png_ptr->idat_size; + /* check for overflow */ + if((png_uint_32)save_size != png_ptr->idat_size) + png_error(png_ptr, "save_size overflowed in pngpread"); + } + else + save_size = png_ptr->save_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); + png_ptr->idat_size -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->idat_size && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size) + { + save_size = (png_size_t)png_ptr->idat_size; + /* check for overflow */ + if((png_uint_32)save_size != png_ptr->idat_size) + png_error(png_ptr, "save_size overflowed in pngpread"); + } + else + save_size = png_ptr->current_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->idat_size -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->idat_size) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + png_ptr->mode |= PNG_AFTER_IDAT; + } +} + +void /* PRIVATE */ +png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + int ret; + + if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length) + png_error(png_ptr, "Extra compression data"); + + png_ptr->zstream.next_in = buffer; + png_ptr->zstream.avail_in = (uInt)buffer_length; + for(;;) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK) + { + if (ret == Z_STREAM_END) + { + if (png_ptr->zstream.avail_in) + png_error(png_ptr, "Extra compressed data"); + if (!(png_ptr->zstream.avail_out)) + { + png_push_process_row(png_ptr); + } + + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + else if (ret == Z_BUF_ERROR) + break; + else + png_error(png_ptr, "Decompression Error"); + } + if (!(png_ptr->zstream.avail_out)) + { + if (( +#if defined(PNG_READ_INTERLACING_SUPPORTED) + png_ptr->interlaced && png_ptr->pass > 6) || + (!png_ptr->interlaced && +#endif + png_ptr->row_number == png_ptr->num_rows)) + { + if (png_ptr->zstream.avail_in) + png_warning(png_ptr, "Too much data in IDAT chunks"); + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + png_push_process_row(png_ptr); + png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; + png_ptr->zstream.next_out = png_ptr->row_buf; + } + else + break; + } +} + +void /* PRIVATE */ +png_push_process_row(png_structp png_ptr) +{ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, + png_ptr->rowbytes + 1); + + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) + png_do_read_transformations(png_ptr); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) + /* blow up interlaced rows to full size */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) +/* old interface (pre-1.0.9): + png_do_read_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + switch (png_ptr->pass) + { + case 0: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 0; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); /* updates png_ptr->pass */ + } + if (png_ptr->pass == 2) /* pass 1 might be empty */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + if (png_ptr->pass == 4 && png_ptr->height <= 4) + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + if (png_ptr->pass == 6 && png_ptr->height <= 4) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + break; + } + case 1: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 1; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 2) /* skip top 4 generated rows */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + break; + } + case 2: + { + int i; + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 4) /* pass 3 might be empty */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + break; + } + case 3: + { + int i; + for (i = 0; i < 4 && png_ptr->pass == 3; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 4) /* skip top two generated rows */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + break; + } + case 4: + { + int i; + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 6) /* pass 5 might be empty */ + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + break; + } + case 5: + { + int i; + for (i = 0; i < 2 && png_ptr->pass == 5; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 6) /* skip top generated row */ + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + break; + } + case 6: + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + if (png_ptr->pass != 6) + break; + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + } + else +#endif + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } +} + +void /* PRIVATE */ +png_read_push_finish_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + + /* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h + PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; + */ +#endif + + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + png_memset_check(png_ptr, png_ptr->prev_row, 0, + png_ptr->rowbytes + 1); + do + { + png_ptr->pass++; + if ((png_ptr->pass == 1 && png_ptr->width < 5) || + (png_ptr->pass == 3 && png_ptr->width < 3) || + (png_ptr->pass == 5 && png_ptr->width < 2)) + png_ptr->pass++; + + if (png_ptr->pass > 7) + png_ptr->pass--; + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); + } +} + +#if defined(PNG_READ_tEXt_SUPPORTED) +void /* PRIVATE */ +png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place tEXt"); + info_ptr = info_ptr; /* to quiet some compiler warnings */ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(length+1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_tEXt_MODE; +} + +void /* PRIVATE */ +png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + else + text_size = png_ptr->current_text_left; + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#if defined(PNG_MAX_MALLOC_64K) + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* empty loop */ ; + + if (text != key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, + (png_uint_32)png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; +#endif + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + png_ptr->current_text = NULL; + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk."); + } +} +#endif + +#if defined(PNG_READ_zTXt_SUPPORTED) +void /* PRIVATE */ +png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place zTXt"); + info_ptr = info_ptr; /* to quiet some compiler warnings */ + } + +#ifdef PNG_MAX_MALLOC_64K + /* We can't handle zTXt chunks > 64K, since we don't have enough space + * to be able to store the uncompressed data. Actually, the threshold + * is probably around 32K, but it isn't as definite as 64K is. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_push_crc_skip(png_ptr, length); + return; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(length+1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_zTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + else + text_size = png_ptr->current_text_left; + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + png_size_t text_size, key_size; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* empty loop */ ; + + /* zTXt can't have zero text */ + if (text == key + png_ptr->current_text_size) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */ + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + png_ptr->zstream.next_in = (png_bytep )text; + png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - + (text - key)); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + key_size = text - key; + text_size = 0; + text = NULL; + ret = Z_STREAM_END; + + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) + { + if (text == NULL) + { + text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out + + key_size + 1)); + png_memcpy(text + key_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + png_memcpy(text, key, key_size); + text_size = key_size + png_ptr->zbuf_size - + png_ptr->zstream.avail_out; + *(text + text_size) = '\0'; + } + else + { + png_charp tmp; + + tmp = text; + text = (png_charp)png_malloc(png_ptr, text_size + + (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out + + 1)); + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + png_memcpy(text + text_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = '\0'; + } + if (ret != Z_STREAM_END) + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else + { + break; + } + + if (ret == Z_STREAM_END) + break; + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + if (ret != Z_STREAM_END) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + + png_ptr->current_text = NULL; + png_free(png_ptr, key); + key = text; + text += key_size; + + text_ptr = (png_textp)png_malloc(png_ptr, + (png_uint_32)png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; +#endif + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk."); + } +} +#endif + +#if defined(PNG_READ_iTXt_SUPPORTED) +void /* PRIVATE */ +png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place iTXt"); + info_ptr = info_ptr; /* to quiet some compiler warnings */ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(length+1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_iTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) +{ + + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + else + text_size = png_ptr->current_text_left; + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp key; + int comp_flag; + png_charp lang; + png_charp lang_key; + png_charp text; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#if defined(PNG_MAX_MALLOC_64K) + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (lang = key; *lang; lang++) + /* empty loop */ ; + + if (lang != key + png_ptr->current_text_size) + lang++; + + comp_flag = *lang++; + lang++; /* skip comp_type, always zero */ + + for (lang_key = lang; *lang_key; lang_key++) + /* empty loop */ ; + lang_key++; /* skip NUL separator */ + + for (text = lang_key; *text; text++) + /* empty loop */ ; + + if (text != key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, + (png_uint_32)png_sizeof(png_text)); + text_ptr->compression = comp_flag + 2; + text_ptr->key = key; + text_ptr->lang = lang; + text_ptr->lang_key = lang_key; + text_ptr->text = text; + text_ptr->text_length = 0; + text_ptr->itxt_length = png_strlen(text); + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_ptr->current_text = NULL; + + png_free(png_ptr, text_ptr); + if (ret) + png_warning(png_ptr, "Insufficient memory to store iTXt chunk."); + } +} +#endif + +/* This function is called when we haven't found a handler for this + * chunk. If there isn't a problem with the chunk itself (ie a bad chunk + * name or a critical chunk), the chunk is (currently) silently ignored. + */ +void /* PRIVATE */ +png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + png_uint_32 skip=0; + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + + info_ptr = info_ptr; /* to quiet some compiler warnings */ + } + +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) + { +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + png_strncpy((png_charp)png_ptr->unknown_chunk.name, + (png_charp)png_ptr->chunk_name, + png_sizeof((png_charp)png_ptr->chunk_name)); + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); + png_ptr->unknown_chunk.size = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + if(png_ptr->read_user_chunk_fn != NULL) + { + /* callback to user unknown chunk handler */ + int ret; + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } +#else + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); +#endif + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + else +#endif + skip=length; + png_push_crc_skip(png_ptr, skip); +} + +void /* PRIVATE */ +png_push_have_info(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->info_fn != NULL) + (*(png_ptr->info_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_end(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->end_fn != NULL) + (*(png_ptr->end_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_row(png_structp png_ptr, png_bytep row) +{ + if (png_ptr->row_fn != NULL) + (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, + (int)png_ptr->pass); +} + +void PNGAPI +png_progressive_combine_row (png_structp png_ptr, + png_bytep old_row, png_bytep new_row) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST int FARDATA png_pass_dsp_mask[7] = + {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; +#endif + if(png_ptr == NULL) return; + if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ + png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); +} + +void PNGAPI +png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn) +{ + if(png_ptr == NULL) return; + png_ptr->info_fn = info_fn; + png_ptr->row_fn = row_fn; + png_ptr->end_fn = end_fn; + + png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); +} + +#if defined(PNG_READ_APNG_SUPPORTED) +void PNGAPI +png_set_progressive_frame_fn(png_structp png_ptr, + png_progressive_frame_ptr frame_info_fn, + png_progressive_frame_ptr frame_end_fn) +{ + png_ptr->frame_info_fn = frame_info_fn; + png_ptr->frame_end_fn = frame_end_fn; +} +#endif + +png_voidp PNGAPI +png_get_progressive_ptr(png_structp png_ptr) +{ + if(png_ptr == NULL) return (NULL); + return png_ptr->io_ptr; +} +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pngread.c b/kernel/kls_png/ksquirrel-libs-png/pngread.c new file mode 100644 index 0000000..285c18d --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngread.c @@ -0,0 +1,1604 @@ + +/* pngread.c - read a PNG file + * + * Last changed in libpng 1.2.19 August 19, 2007 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2007 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file contains routines that an application calls directly to + * read a PNG file or stream. + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(PNG_READ_SUPPORTED) + +/* Create a PNG structure for reading, and allocate any memory needed. */ +png_structp PNGAPI +png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn) +{ + +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); +} + +/* Alternate create PNG structure for reading, and allocate any memory needed. */ +png_structp PNGAPI +png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + + png_structp png_ptr; + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + + int i; + + png_debug(1, "in png_create_read_struct\n"); +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif + if (png_ptr == NULL) + return (NULL); + + /* added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max=PNG_USER_WIDTH_MAX; + png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; +#endif + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_ptr->jmpbuf)) +#endif + { + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf=NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, + (png_free_ptr)free_fn, (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + return (NULL); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); +#endif +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif + + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + i=0; + do + { + if(user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[80]; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "Incompatible libpng version in application and library"); + } + } + + /* initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + switch (inflateInit(&png_ptr->zstream)) + { + case Z_OK: /* Do nothing */ break; + case Z_MEM_ERROR: + case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break; + case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break; + default: png_error(png_ptr, "Unknown zlib error"); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); + +#ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then encounter + a png_error() will longjmp here. Since the jmpbuf is then meaningless we + abort instead of returning. */ +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) + PNG_ABORT(); + png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); +#else + if (setjmp(png_ptr->jmpbuf)) + PNG_ABORT(); +#endif +#endif + return (png_ptr); +} + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +/* Initialize PNG structure for reading, and allocate any memory needed. + This interface is deprecated in favour of the png_create_read_struct(), + and it will disappear as of libpng-1.3.0. */ +void PNGAPI +png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size, png_size_t png_info_size) +{ + /* We only come here via pre-1.0.12-compiled applications */ + if(png_ptr == NULL) return; +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + if(png_sizeof(png_struct) > png_struct_size || + png_sizeof(png_info) > png_info_size) + { + char msg[80]; + png_ptr->warning_fn=NULL; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); + } +#endif + if(png_sizeof(png_struct) > png_struct_size) + { + png_ptr->error_fn=NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "The png struct allocated by the application for reading is too small."); + } + if(png_sizeof(png_info) > png_info_size) + { + png_ptr->error_fn=NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "The info struct allocated by application for reading is too small."); + } + png_read_init_3(&png_ptr, user_png_ver, png_struct_size); +} +#endif /* PNG_1_0_X || PNG_1_2_X */ + +void PNGAPI +png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* to save current jump buffer */ +#endif + + int i=0; + + png_structp png_ptr=*ptr_ptr; + + if(png_ptr == NULL) return; + + do + { + if(user_png_ver[i] != png_libpng_ver[i]) + { +#ifdef PNG_LEGACY_SUPPORTED + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; +#else + png_ptr->warning_fn=NULL; + png_warning(png_ptr, + "Application uses deprecated png_read_init() and should be recompiled."); + break; +#endif + } + } while (png_libpng_ver[i++]); + + png_debug(1, "in png_read_init_3\n"); + +#ifdef PNG_SETJMP_SUPPORTED + /* save jump buffer and error functions */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); +#endif + + if(png_sizeof(png_struct) > png_struct_size) + { + png_destroy_struct(png_ptr); + *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); + png_ptr = *ptr_ptr; + } + + /* reset all variables to 0 */ + png_memset(png_ptr, 0, png_sizeof (png_struct)); + +#ifdef PNG_SETJMP_SUPPORTED + /* restore jump buffer */ + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); +#endif + + /* added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max=PNG_USER_WIDTH_MAX; + png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; +#endif + + /* initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + switch (inflateInit(&png_ptr->zstream)) + { + case Z_OK: /* Do nothing */ break; + case Z_MEM_ERROR: + case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break; + case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break; + default: png_error(png_ptr, "Unknown zlib error"); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); +} + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. This has been + * changed in v0.90 to allow reading a file that already has the magic + * bytes read from the stream. You can tell libpng how many bytes have + * been read from the beginning of the stream (up to the maximum of 8) + * via png_set_sig_bytes(), and we will only check the remaining bytes + * here. The application can then have access to the signature bytes we + * read if it is determined that this isn't a valid PNG file. + */ +void PNGAPI +png_read_info(png_structp png_ptr, png_infop info_ptr) +{ + if(png_ptr == NULL) return; + png_debug(1, "in png_read_info\n"); + /* If we haven't checked all of the PNG signature bytes, do so now. */ + if (png_ptr->sig_bytes < 8) + { + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; + + png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); + png_ptr->sig_bytes = 8; + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + if (num_checked < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; + } + + for(;;) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IHDR; + PNG_CONST PNG_IDAT; + PNG_CONST PNG_IEND; + PNG_CONST PNG_PLTE; +#if defined(PNG_READ_bKGD_SUPPORTED) + PNG_CONST PNG_bKGD; +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + PNG_CONST PNG_cHRM; +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + PNG_CONST PNG_gAMA; +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + PNG_CONST PNG_hIST; +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + PNG_CONST PNG_iCCP; +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + PNG_CONST PNG_iTXt; +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + PNG_CONST PNG_oFFs; +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + PNG_CONST PNG_pCAL; +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + PNG_CONST PNG_pHYs; +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + PNG_CONST PNG_sBIT; +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + PNG_CONST PNG_sCAL; +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + PNG_CONST PNG_sPLT; +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + PNG_CONST PNG_sRGB; +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + PNG_CONST PNG_tEXt; +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + PNG_CONST PNG_tIME; +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + PNG_CONST PNG_tRNS; +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + PNG_CONST PNG_zTXt; +#endif +#if defined(PNG_READ_APNG_SUPPORTED) + PNG_CONST PNG_acTL; + PNG_CONST PNG_fcTL; + PNG_CONST PNG_fdAT; +#endif +#endif /* PNG_USE_LOCAL_ARRAYS */ + png_byte chunk_length[4]; + png_uint_32 length; + + png_read_data(png_ptr, chunk_length, 4); + length = png_get_uint_31(png_ptr,chunk_length); + + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + + png_debug2(0, "Reading %s chunk, length=%lu.\n", png_ptr->chunk_name, + length); + + /* This should be a binary subdivision search or a hash for + * matching the chunk name rather than a linear search. + */ + if (!png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4)) + if(png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + break; + } + } +#endif + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + +#if defined(PNG_READ_APNG_SUPPORTED) + png_have_info(png_ptr, info_ptr); +#endif + png_ptr->idat_size = length; + png_ptr->mode |= PNG_HAVE_IDAT; + break; + } +#if defined(PNG_READ_bKGD_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_APNG_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_acTL, 4)) + png_handle_acTL(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_fcTL, 4)) + png_handle_fcTL(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_fdAT, 4)) + png_handle_fdAT(png_ptr, info_ptr, length); +#endif + else + png_handle_unknown(png_ptr, info_ptr, length); + } +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +#if defined(PNG_READ_APNG_SUPPORTED) +void PNGAPI +png_read_frame_head(png_structp png_ptr, png_infop info_ptr) +{ + png_byte have_chunk_after_DAT; /* after IDAT or after fdAT */ + + png_debug(0, "Reading frame head\n"); + + if (!(png_ptr->mode & PNG_HAVE_acTL)) + png_error(png_ptr, "attempt to png_read_frame_head() but " + "no acTL present"); + + /* do nothing for the main IDAT */ + if (png_ptr->num_frames_read == 0) + return; + + png_crc_finish(png_ptr, 0); /* CRC from last IDAT or fdAT chunk */ + + png_read_reset(png_ptr); + png_ptr->mode &= ~PNG_HAVE_fcTL; + + have_chunk_after_DAT = 0; + for (;;) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IDAT; + PNG_fdAT; + PNG_fcTL; +#endif + png_byte chunk_length[4]; + png_uint_32 length; + + png_read_data(png_ptr, chunk_length, 4); + length = png_get_uint_31(png_ptr, chunk_length); + + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + /* discard trailing IDATs for the first frame */ + if (have_chunk_after_DAT || png_ptr->num_frames_read > 1) + png_error(png_ptr, "png_read_frame_head(): out of place IDAT"); + png_crc_finish(png_ptr, length); + } + else if (!png_memcmp(png_ptr->chunk_name, png_fcTL, 4)) + { + png_handle_fcTL(png_ptr, info_ptr, length); + have_chunk_after_DAT = 1; + } + else if (!png_memcmp(png_ptr->chunk_name, png_fdAT, 4)) + { + png_ensure_sequence_number(png_ptr, length); + + /* discard trailing fdATs for frames other than the first */ + if (!have_chunk_after_DAT && png_ptr->num_frames_read > 1) + png_crc_finish(png_ptr, length - 4); + else if(png_ptr->mode & PNG_HAVE_fcTL) + { + png_ptr->idat_size = length - 4; + png_ptr->mode |= PNG_HAVE_IDAT; + + break; + } + else + png_error(png_ptr, "png_read_frame_head(): out of place fdAT"); + } + else + { + png_warning(png_ptr, "Skipped (ignored) a chunk " + "between APNG chunks"); + png_crc_finish(png_ptr, length); + } + } +} +#endif /* PNG_READ_APNG_SUPPORTED */ + +/* optional call to update the users info_ptr structure */ +void PNGAPI +png_read_update_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_update_info\n"); + if(png_ptr == NULL) return; + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + else + png_warning(png_ptr, + "Ignoring extra png_read_update_info() call; row buffer not reallocated"); + png_read_transform_info(png_ptr, info_ptr); +} + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Initialize palette, background, etc, after transformations + * are set, but before any reading takes place. This allows + * the user to obtain a gamma-corrected palette, for example. + * If the user doesn't call this, we will do it ourselves. + */ +void PNGAPI +png_start_read_image(png_structp png_ptr) +{ + png_debug(1, "in png_start_read_image\n"); + if(png_ptr == NULL) return; + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +void PNGAPI +png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IDAT; +#if defined(PNG_READ_APNG_SUPPORTED) + PNG_CONST PNG_fdAT; + PNG_CONST PNG_IEND; +#endif + PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, + 0xff}; + PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; +#endif + int ret; + if(png_ptr == NULL) return; + png_debug2(1, "in png_read_row (row %lu, pass %d)\n", + png_ptr->row_number, png_ptr->pass); + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* check for transforms that have been set but were defined out */ +#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && !defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined."); +#endif + } + +#if defined(PNG_READ_INTERLACING_SUPPORTED) + /* if interlaced and we do not need a new row, combine row and return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + if (dsp_row != NULL && (png_ptr->row_number & 4)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 3: + if ((png_ptr->row_number & 3) || png_ptr->width < 3) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 4: + if ((png_ptr->row_number & 3) != 2) + { + if (dsp_row != NULL && (png_ptr->row_number & 2)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 1) || png_ptr->width < 2) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 6: + if (!(png_ptr->row_number & 1)) + { + png_read_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "Invalid attempt to read row data"); + + png_ptr->zstream.next_out = png_ptr->row_buf; + png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; + do + { + if (!(png_ptr->zstream.avail_in)) + { + png_uint_32 bytes_to_skip = 0; + + while (!png_ptr->idat_size || bytes_to_skip != 0) + { + png_byte chunk_length[4]; + + png_crc_finish(png_ptr, bytes_to_skip); + bytes_to_skip = 0; + + png_read_data(png_ptr, chunk_length, 4); + png_ptr->idat_size = png_get_uint_31(png_ptr,chunk_length); + + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + +#if defined(PNG_READ_APNG_SUPPORTED) + if (png_ptr->num_frames_read == 0) + { +#endif + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); +#if defined(PNG_READ_APNG_SUPPORTED) + } + else + { + if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + png_error(png_ptr, "Not enough image data"); + if (png_memcmp(png_ptr->chunk_name, png_fdAT, 4)) + { + png_warning(png_ptr, "Skipped (ignored) a chunk " + "between APNG chunks"); + bytes_to_skip = png_ptr->idat_size; + continue; + } + + png_ensure_sequence_number(png_ptr, png_ptr->idat_size); + + png_ptr->idat_size -= 4; + } +#endif + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, + (png_size_t)png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) + { + if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_error(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; +#if defined(PNG_READ_APNG_SUPPORTED) + png_ptr->num_frames_read++; +#endif + break; + } + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression error"); + + } while (png_ptr->zstream.avail_out); + + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + if(png_ptr->row_buf[0]) + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, + png_ptr->rowbytes + 1); + +#if defined(PNG_MNG_FEATURES_SUPPORTED) + if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) + png_do_read_transformations(png_ptr); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) + /* blow up interlaced rows to full size */ + if (png_ptr->interlaced && + (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) +/* old interface (pre-1.0.9): + png_do_read_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + if (row != NULL) + png_combine_row(png_ptr, row, + png_pass_mask[png_ptr->pass]); + } + else +#endif + { + if (row != NULL) + png_combine_row(png_ptr, row, 0xff); + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 0xff); + } + png_read_finish_row(png_ptr); + + if (png_ptr->read_row_fn != NULL) + (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. If the image is interlaced, + * and png_set_interlace_handling() has been called, the rows need to + * contain the contents of the rows from the previous pass. If the + * image has alpha or transparency, and png_handle_alpha()[*] has been + * called, the rows contents must be initialized to the contents of the + * screen. + * + * "row" holds the actual image, and pixels are placed in it + * as they arrive. If the image is displayed after each pass, it will + * appear to "sparkle" in. "display_row" can be used to display a + * "chunky" progressive image, with finer detail added as it becomes + * available. If you do not want this "chunky" display, you may pass + * NULL for display_row. If you do not want the sparkle display, and + * you have not called png_handle_alpha(), you may pass NULL for rows. + * If you have called png_handle_alpha(), and the image has either an + * alpha channel or a transparency chunk, you must provide a buffer for + * rows. In this case, you do not have to provide a display_row buffer + * also, but you may. If the image is not interlaced, or if you have + * not called png_set_interlace_handling(), the display_row buffer will + * be ignored, so pass NULL to it. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ + +void PNGAPI +png_read_rows(png_structp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows) +{ + png_uint_32 i; + png_bytepp rp; + png_bytepp dp; + + png_debug(1, "in png_read_rows\n"); + if(png_ptr == NULL) return; + rp = row; + dp = display_row; + if (rp != NULL && dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp++; + png_bytep dptr = *dp++; + + png_read_row(png_ptr, rptr, dptr); + } + else if(rp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp; + png_read_row(png_ptr, rptr, png_bytep_NULL); + rp++; + } + else if(dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep dptr = *dp; + png_read_row(png_ptr, png_bytep_NULL, dptr); + dp++; + } +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read the entire image. If the image has an alpha channel or a tRNS + * chunk, and you have called png_handle_alpha()[*], you will need to + * initialize the image to the current image that PNG will be overlaying. + * We set the num_rows again here, in case it was incorrectly set in + * png_read_start_row() by a call to png_read_update_info() or + * png_start_read_image() if png_set_interlace_handling() wasn't called + * prior to either of these functions like it should have been. You can + * only call this function once. If you desire to have an image for + * each pass of a interlaced image, use png_read_rows() instead. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ +void PNGAPI +png_read_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i,image_height; + int pass, j; + png_bytepp rp; + + png_debug(1, "in png_read_image\n"); + if(png_ptr == NULL) return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + pass = png_set_interlace_handling(png_ptr); +#else + if (png_ptr->interlaced) + png_error(png_ptr, + "Cannot read interlaced image -- interlace handler disabled."); + pass = 1; +#endif + + + image_height=png_ptr->height; + png_ptr->num_rows = image_height; /* Make sure this is set correctly */ + + for (j = 0; j < pass; j++) + { + rp = image; + for (i = 0; i < image_height; i++) + { + png_read_row(png_ptr, *rp, png_bytep_NULL); + rp++; + } + } +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. Will not read past the end of the + * file, will verify the end is accurate, and will read any comments + * or time information at the end of the file, if info is not NULL. + */ +void PNGAPI +png_read_end(png_structp png_ptr, png_infop info_ptr) +{ + png_byte chunk_length[4]; + png_uint_32 length; + + png_debug(1, "in png_read_end\n"); + if(png_ptr == NULL) return; + png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */ + + do + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IHDR; + PNG_CONST PNG_IDAT; + PNG_CONST PNG_IEND; + PNG_CONST PNG_PLTE; +#if defined(PNG_READ_bKGD_SUPPORTED) + PNG_CONST PNG_bKGD; +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + PNG_CONST PNG_cHRM; +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + PNG_CONST PNG_gAMA; +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + PNG_CONST PNG_hIST; +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + PNG_CONST PNG_iCCP; +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + PNG_CONST PNG_iTXt; +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + PNG_CONST PNG_oFFs; +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + PNG_CONST PNG_pCAL; +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + PNG_CONST PNG_pHYs; +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + PNG_CONST PNG_sBIT; +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + PNG_CONST PNG_sCAL; +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + PNG_CONST PNG_sPLT; +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + PNG_CONST PNG_sRGB; +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + PNG_CONST PNG_tEXt; +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + PNG_CONST PNG_tIME; +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + PNG_CONST PNG_tRNS; +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + PNG_CONST PNG_zTXt; +#endif +#if defined(PNG_READ_APNG_SUPPORTED) + PNG_CONST PNG_acTL; + PNG_CONST PNG_fcTL; + PNG_CONST PNG_fdAT; +#endif +#endif /* PNG_USE_LOCAL_ARRAYS */ + + png_read_data(png_ptr, chunk_length, 4); + length = png_get_uint_31(png_ptr,chunk_length); + + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + + png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name); + + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_error(png_ptr, "Too many IDAT's found"); + } + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + } +#endif + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + /* Zero length IDATs are legal after the last IDAT has been + * read, but not after other chunks have been read. + */ + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_error(png_ptr, "Too many IDAT's found"); + png_crc_finish(png_ptr, length); + } + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); +#if defined(PNG_READ_bKGD_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_APNG_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_acTL, 4)) + png_handle_acTL(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_fcTL, 4)) + png_handle_fcTL(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_fdAT, 4)) + png_handle_fdAT(png_ptr, info_ptr, length); +#endif + else + png_handle_unknown(png_ptr, info_ptr, length); + } while (!(png_ptr->mode & PNG_HAVE_IEND)); +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +/* free all memory used by the read */ +void PNGAPI +png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, + png_infopp end_info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL, end_info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; + png_voidp mem_ptr; +#endif + + png_debug(1, "in png_destroy_read_struct\n"); + if (png_ptr_ptr != NULL) + png_ptr = *png_ptr_ptr; + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (end_info_ptr_ptr != NULL) + end_info_ptr = *end_info_ptr_ptr; + +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + + png_read_destroy(png_ptr, info_ptr, end_info_ptr); + + if (info_ptr != NULL) + { +#if defined(PNG_TEXT_SUPPORTED) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1); +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (end_info_ptr != NULL) + { +#if defined(PNG_READ_TEXT_SUPPORTED) + png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1); +#endif +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)end_info_ptr); +#endif + *end_info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + +/* free all memory used by the read (old method) */ +void /* PRIVATE */ +png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_read_destroy\n"); + if (info_ptr != NULL) + png_info_destroy(png_ptr, info_ptr); + + if (end_info_ptr != NULL) + png_info_destroy(png_ptr, end_info_ptr); + + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->prev_row); +#if defined(PNG_READ_DITHER_SUPPORTED) + png_free(png_ptr, png_ptr->palette_lookup); + png_free(png_ptr, png_ptr->dither_index); +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) + png_free(png_ptr, png_ptr->gamma_table); +#endif +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + png_free(png_ptr, png_ptr->gamma_from_1); + png_free(png_ptr, png_ptr->gamma_to_1); +#endif +#ifdef PNG_FREE_ME_SUPPORTED + if (png_ptr->free_me & PNG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->free_me &= ~PNG_FREE_PLTE; +#else + if (png_ptr->flags & PNG_FLAG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; +#endif +#if defined(PNG_tRNS_SUPPORTED) || \ + defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) +#ifdef PNG_FREE_ME_SUPPORTED + if (png_ptr->free_me & PNG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans); + png_ptr->free_me &= ~PNG_FREE_TRNS; +#else + if (png_ptr->flags & PNG_FLAG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans); + png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; +#endif +#endif +#if defined(PNG_READ_hIST_SUPPORTED) +#ifdef PNG_FREE_ME_SUPPORTED + if (png_ptr->free_me & PNG_FREE_HIST) + png_free(png_ptr, png_ptr->hist); + png_ptr->free_me &= ~PNG_FREE_HIST; +#else + if (png_ptr->flags & PNG_FLAG_FREE_HIST) + png_free(png_ptr, png_ptr->hist); + png_ptr->flags &= ~PNG_FLAG_FREE_HIST; +#endif +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (png_ptr->gamma_16_table != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_table[i]); + } + png_free(png_ptr, png_ptr->gamma_16_table); + } +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_from_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_from_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_from_1); + } + if (png_ptr->gamma_16_to_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_to_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_to_1); + } +#endif +#endif +#if defined(PNG_TIME_RFC1123_SUPPORTED) + png_free(png_ptr, png_ptr->time_buffer); +#endif + + inflateEnd(&png_ptr->zstream); +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_free(png_ptr, png_ptr->save_buffer); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +#ifdef PNG_TEXT_SUPPORTED + png_free(png_ptr, png_ptr->current_text); +#endif /* PNG_TEXT_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + + /* Save the important info out of the png_struct, in case it is + * being used again. + */ +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof (png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); +#endif + +} + +void PNGAPI +png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn) +{ + if(png_ptr == NULL) return; + png_ptr->read_row_fn = read_row_fn; +} + + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +#if defined(PNG_INFO_IMAGE_SUPPORTED) +void PNGAPI +png_read_png(png_structp png_ptr, png_infop info_ptr, + int transforms, + voidp params) +{ + int row; + + if(png_ptr == NULL) return; +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) + /* invert the alpha channel from opacity to transparency + */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + + /* png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). + */ + png_read_info(png_ptr, info_ptr); + if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) + png_error(png_ptr,"Image is too high to process with png_read_png()"); + + /* -------------- image transformations start here ------------------- */ + +#if defined(PNG_READ_16_TO_8_SUPPORTED) + /* tell libpng to strip 16 bit/color files down to 8 bits per color + */ + if (transforms & PNG_TRANSFORM_STRIP_16) + png_set_strip_16(png_ptr); +#endif + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) + /* Strip alpha bytes from the input data without combining with + * the background (not recommended). + */ + if (transforms & PNG_TRANSFORM_STRIP_ALPHA) + png_set_strip_alpha(png_ptr); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) + /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). + */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) + /* Expand paletted colors into true RGB triplets + * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel + * Expand paletted or RGB images with transparency to full alpha + * channels so the data will be available as RGBA quartets. + */ + if (transforms & PNG_TRANSFORM_EXPAND) + if ((png_ptr->bit_depth < 8) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || + (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) + png_set_expand(png_ptr); +#endif + + /* We don't handle background color or gamma transformation or dithering. + */ + +#if defined(PNG_READ_INVERT_SUPPORTED) + /* invert monochrome files to have 0 as white and 1 as black + */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) + { + png_color_8p sig_bit; + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + png_set_shift(png_ptr, sig_bit); + } +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) + /* flip the RGB pixels to BGR (or RGBA to BGRA) + */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) + /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) + */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) + /* swap bytes of 16 bit files to least significant byte first + */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + + /* We don't handle adding filler bytes */ + + /* Optional call to gamma correct and add the background to the palette + * and update info structure. REQUIRED if you are expecting libpng to + * update the palette for you (i.e., you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* -------------- image transformations end here ------------------- */ + +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); +#endif + if(info_ptr->row_pointers == NULL) + { + info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, + info_ptr->height * png_sizeof(png_bytep)); +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_ROWS; +#endif + for (row = 0; row < (int)info_ptr->height; row++) + { + info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr)); + } + } + + png_read_image(png_ptr, info_ptr->row_pointers); + info_ptr->valid |= PNG_INFO_IDAT; + + /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); + + transforms = transforms; /* quiet compiler warnings */ + params = params; + +} +#endif /* PNG_INFO_IMAGE_SUPPORTED */ +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pngrio.c b/kernel/kls_png/ksquirrel-libs-png/pngrio.c new file mode 100644 index 0000000..7d2522f --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngrio.c @@ -0,0 +1,167 @@ + +/* pngrio.c - functions for data input + * + * Last changed in libpng 1.2.13 November 13, 2006 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2006 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all input. Users who need + * special handling are expected to write a function that has the same + * arguments as this and performs a similar function, but that possibly + * has a different input method. Note that you shouldn't change this + * function, but rather write a replacement function and then make + * libpng use it at run time with png_set_read_fn(...). + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(PNG_READ_SUPPORTED) + +/* Read the data from whatever input you are using. The default routine + reads from a file pointer. Note that this routine sometimes gets called + with very small lengths, so you should implement some kind of simple + buffering if you are using unbuffered reads. This should never be asked + to read more then 64K on a 16 bit machine. */ +void /* PRIVATE */ +png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_debug1(4,"reading %d bytes\n", (int)length); + if (png_ptr->read_data_fn != NULL) + (*(png_ptr->read_data_fn))(png_ptr, data, length); + else + png_error(png_ptr, "Call to NULL read function"); +} + +#if !defined(PNG_NO_STDIO) +/* This is the function that does the actual reading of data. If you are + not reading from a standard C stream, you should create a replacement + read_data function and use it at run time with png_set_read_fn(), rather + than changing the library. */ +#ifndef USE_FAR_KEYWORD +void PNGAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + if(png_ptr == NULL) return; + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ +#if defined(_WIN32_WCE) + if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) + check = 0; +#else + check = (png_size_t)fread(data, (png_size_t)1, length, + (png_FILE_p)png_ptr->io_ptr); +#endif + + if (check != length) + png_error(png_ptr, "Read Error"); +} +#else +/* this is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void PNGAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + int check; + png_byte *n_data; + png_FILE_p io_ptr; + + if(png_ptr == NULL) return; + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)n_data == data) + { +#if defined(_WIN32_WCE) + if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) + check = 0; +#else + check = fread(n_data, 1, length, io_ptr); +#endif + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + do + { + read = MIN(NEAR_BUF_SIZE, remaining); +#if defined(_WIN32_WCE) + if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) ) + err = 0; +#else + err = fread(buf, (png_size_t)1, read, io_ptr); +#endif + png_memcpy(data, buf, read); /* copy far buffer to near buffer */ + if(err != read) + break; + else + check += err; + data += read; + remaining -= read; + } + while (remaining != 0); + } + if ((png_uint_32)check != (png_uint_32)length) + png_error(png_ptr, "read Error"); +} +#endif +#endif + +/* This function allows the application to supply a new input function + for libpng if standard C streams aren't being used. + + This function takes as its arguments: + png_ptr - pointer to a png input data structure + io_ptr - pointer to user supplied structure containing info about + the input functions. May be NULL. + read_data_fn - pointer to a new input function that takes as its + arguments a pointer to a png_struct, a pointer to + a location where input data can be stored, and a 32-bit + unsigned int that is the number of bytes to be read. + To exit and output any fatal error messages the new write + function should call png_error(png_ptr, "Error msg"). */ +void PNGAPI +png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn) +{ + if(png_ptr == NULL) return; + png_ptr->io_ptr = io_ptr; + +#if !defined(PNG_NO_STDIO) + if (read_data_fn != NULL) + png_ptr->read_data_fn = read_data_fn; + else + png_ptr->read_data_fn = png_default_read_data; +#else + png_ptr->read_data_fn = read_data_fn; +#endif + + /* It is an error to write to a read device */ + if (png_ptr->write_data_fn != NULL) + { + png_ptr->write_data_fn = NULL; + png_warning(png_ptr, + "It's an error to set both read_data_fn and write_data_fn in the "); + png_warning(png_ptr, + "same structure. Resetting write_data_fn to NULL."); + } + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) + png_ptr->output_flush_fn = NULL; +#endif +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pngrtran.c b/kernel/kls_png/ksquirrel-libs-png/pngrtran.c new file mode 100644 index 0000000..97f12e6 --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngrtran.c @@ -0,0 +1,4284 @@ + +/* pngrtran.c - transforms the data in a row for PNG readers + * + * Last changed in libpng 1.2.19 August 19, 2007 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2007 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file contains functions optionally called by an application + * in order to tell libpng how to handle data when reading a PNG. + * Transformations that are used in both reading and writing are + * in pngtrans.c. + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(PNG_READ_SUPPORTED) + +/* Set the action on getting a CRC error for an ancillary or critical chunk. */ +void PNGAPI +png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) +{ + png_debug(1, "in png_set_crc_action\n"); + /* Tell libpng how we react to CRC errors in critical chunks */ + if(png_ptr == NULL) return; + switch (crit_action) + { + case PNG_CRC_NO_CHANGE: /* leave setting as is */ + break; + case PNG_CRC_WARN_USE: /* warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; + break; + case PNG_CRC_QUIET_USE: /* quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | + PNG_FLAG_CRC_CRITICAL_IGNORE; + break; + case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */ + png_warning(png_ptr, "Can't discard critical data on CRC error."); + case PNG_CRC_ERROR_QUIT: /* error/quit */ + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + break; + } + + switch (ancil_action) + { + case PNG_CRC_NO_CHANGE: /* leave setting as is */ + break; + case PNG_CRC_WARN_USE: /* warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; + break; + case PNG_CRC_QUIET_USE: /* quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | + PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + case PNG_CRC_ERROR_QUIT: /* error/quit */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + case PNG_CRC_WARN_DISCARD: /* warn/discard data */ + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + break; + } +} + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) +/* handle alpha and tRNS via a background color */ +void PNGAPI +png_set_background(png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma) +{ + png_debug(1, "in png_set_background\n"); + if(png_ptr == NULL) return; + if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) + { + png_warning(png_ptr, "Application must supply a known background gamma"); + return; + } + + png_ptr->transformations |= PNG_BACKGROUND; + png_memcpy(&(png_ptr->background), background_color, + png_sizeof(png_color_16)); + png_ptr->background_gamma = (float)background_gamma; + png_ptr->background_gamma_type = (png_byte)(background_gamma_code); + png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); +} +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +/* strip 16 bit depth files to 8 bit depth */ +void PNGAPI +png_set_strip_16(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_16\n"); + if(png_ptr == NULL) return; + png_ptr->transformations |= PNG_16_TO_8; +} +#endif + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +void PNGAPI +png_set_strip_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_alpha\n"); + if(png_ptr == NULL) return; + png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; +} +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +/* Dither file to 8 bit. Supply a palette, the current number + * of elements in the palette, the maximum number of elements + * allowed, and a histogram if possible. If the current number + * of colors is greater then the maximum number, the palette will be + * modified to fit in the maximum number. "full_dither" indicates + * whether we need a dithering cube set up for RGB images, or if we + * simply are reducing the number of colors in a paletted image. + */ + +typedef struct png_dsort_struct +{ + struct png_dsort_struct FAR * next; + png_byte left; + png_byte right; +} png_dsort; +typedef png_dsort FAR * png_dsortp; +typedef png_dsort FAR * FAR * png_dsortpp; + +void PNGAPI +png_set_dither(png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_uint_16p histogram, + int full_dither) +{ + png_debug(1, "in png_set_dither\n"); + if(png_ptr == NULL) return; + png_ptr->transformations |= PNG_DITHER; + + if (!full_dither) + { + int i; + + png_ptr->dither_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof (png_byte))); + for (i = 0; i < num_palette; i++) + png_ptr->dither_index[i] = (png_byte)i; + } + + if (num_palette > maximum_colors) + { + if (histogram != NULL) + { + /* This is easy enough, just throw out the least used colors. + Perhaps not the best solution, but good enough. */ + + int i; + + /* initialize an array to sort colors */ + png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof (png_byte))); + + /* initialize the dither_sort array */ + for (i = 0; i < num_palette; i++) + png_ptr->dither_sort[i] = (png_byte)i; + + /* Find the least used palette entries by starting a + bubble sort, and running it until we have sorted + out enough colors. Note that we don't care about + sorting all the colors, just finding which are + least used. */ + + for (i = num_palette - 1; i >= maximum_colors; i--) + { + int done; /* to stop early if the list is pre-sorted */ + int j; + + done = 1; + for (j = 0; j < i; j++) + { + if (histogram[png_ptr->dither_sort[j]] + < histogram[png_ptr->dither_sort[j + 1]]) + { + png_byte t; + + t = png_ptr->dither_sort[j]; + png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1]; + png_ptr->dither_sort[j + 1] = t; + done = 0; + } + } + if (done) + break; + } + + /* swap the palette around, and set up a table, if necessary */ + if (full_dither) + { + int j = num_palette; + + /* put all the useful colors within the max, but don't + move the others */ + for (i = 0; i < maximum_colors; i++) + { + if ((int)png_ptr->dither_sort[i] >= maximum_colors) + { + do + j--; + while ((int)png_ptr->dither_sort[j] >= maximum_colors); + palette[i] = palette[j]; + } + } + } + else + { + int j = num_palette; + + /* move all the used colors inside the max limit, and + develop a translation table */ + for (i = 0; i < maximum_colors; i++) + { + /* only move the colors we need to */ + if ((int)png_ptr->dither_sort[i] >= maximum_colors) + { + png_color tmp_color; + + do + j--; + while ((int)png_ptr->dither_sort[j] >= maximum_colors); + + tmp_color = palette[j]; + palette[j] = palette[i]; + palette[i] = tmp_color; + /* indicate where the color went */ + png_ptr->dither_index[j] = (png_byte)i; + png_ptr->dither_index[i] = (png_byte)j; + } + } + + /* find closest color for those colors we are not using */ + for (i = 0; i < num_palette; i++) + { + if ((int)png_ptr->dither_index[i] >= maximum_colors) + { + int min_d, k, min_k, d_index; + + /* find the closest color to one we threw out */ + d_index = png_ptr->dither_index[i]; + min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); + for (k = 1, min_k = 0; k < maximum_colors; k++) + { + int d; + + d = PNG_COLOR_DIST(palette[d_index], palette[k]); + + if (d < min_d) + { + min_d = d; + min_k = k; + } + } + /* point to closest color */ + png_ptr->dither_index[i] = (png_byte)min_k; + } + } + } + png_free(png_ptr, png_ptr->dither_sort); + png_ptr->dither_sort=NULL; + } + else + { + /* This is much harder to do simply (and quickly). Perhaps + we need to go through a median cut routine, but those + don't always behave themselves with only a few colors + as input. So we will just find the closest two colors, + and throw out one of them (chosen somewhat randomly). + [We don't understand this at all, so if someone wants to + work on improving it, be our guest - AED, GRP] + */ + int i; + int max_d; + int num_new_palette; + png_dsortp t; + png_dsortpp hash; + + t=NULL; + + /* initialize palette index arrays */ + png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof (png_byte))); + png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof (png_byte))); + + /* initialize the sort array */ + for (i = 0; i < num_palette; i++) + { + png_ptr->index_to_palette[i] = (png_byte)i; + png_ptr->palette_to_index[i] = (png_byte)i; + } + + hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 * + png_sizeof (png_dsortp))); + for (i = 0; i < 769; i++) + hash[i] = NULL; +/* png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */ + + num_new_palette = num_palette; + + /* initial wild guess at how far apart the farthest pixel + pair we will be eliminating will be. Larger + numbers mean more areas will be allocated, Smaller + numbers run the risk of not saving enough data, and + having to do this all over again. + + I have not done extensive checking on this number. + */ + max_d = 96; + + while (num_new_palette > maximum_colors) + { + for (i = 0; i < num_new_palette - 1; i++) + { + int j; + + for (j = i + 1; j < num_new_palette; j++) + { + int d; + + d = PNG_COLOR_DIST(palette[i], palette[j]); + + if (d <= max_d) + { + + t = (png_dsortp)png_malloc_warn(png_ptr, + (png_uint_32)(png_sizeof(png_dsort))); + if (t == NULL) + break; + t->next = hash[d]; + t->left = (png_byte)i; + t->right = (png_byte)j; + hash[d] = t; + } + } + if (t == NULL) + break; + } + + if (t != NULL) + for (i = 0; i <= max_d; i++) + { + if (hash[i] != NULL) + { + png_dsortp p; + + for (p = hash[i]; p; p = p->next) + { + if ((int)png_ptr->index_to_palette[p->left] + < num_new_palette && + (int)png_ptr->index_to_palette[p->right] + < num_new_palette) + { + int j, next_j; + + if (num_new_palette & 0x01) + { + j = p->left; + next_j = p->right; + } + else + { + j = p->right; + next_j = p->left; + } + + num_new_palette--; + palette[png_ptr->index_to_palette[j]] + = palette[num_new_palette]; + if (!full_dither) + { + int k; + + for (k = 0; k < num_palette; k++) + { + if (png_ptr->dither_index[k] == + png_ptr->index_to_palette[j]) + png_ptr->dither_index[k] = + png_ptr->index_to_palette[next_j]; + if ((int)png_ptr->dither_index[k] == + num_new_palette) + png_ptr->dither_index[k] = + png_ptr->index_to_palette[j]; + } + } + + png_ptr->index_to_palette[png_ptr->palette_to_index + [num_new_palette]] = png_ptr->index_to_palette[j]; + png_ptr->palette_to_index[png_ptr->index_to_palette[j]] + = png_ptr->palette_to_index[num_new_palette]; + + png_ptr->index_to_palette[j] = (png_byte)num_new_palette; + png_ptr->palette_to_index[num_new_palette] = (png_byte)j; + } + if (num_new_palette <= maximum_colors) + break; + } + if (num_new_palette <= maximum_colors) + break; + } + } + + for (i = 0; i < 769; i++) + { + if (hash[i] != NULL) + { + png_dsortp p = hash[i]; + while (p) + { + t = p->next; + png_free(png_ptr, p); + p = t; + } + } + hash[i] = 0; + } + max_d += 96; + } + png_free(png_ptr, hash); + png_free(png_ptr, png_ptr->palette_to_index); + png_free(png_ptr, png_ptr->index_to_palette); + png_ptr->palette_to_index=NULL; + png_ptr->index_to_palette=NULL; + } + num_palette = maximum_colors; + } + if (png_ptr->palette == NULL) + { + png_ptr->palette = palette; + } + png_ptr->num_palette = (png_uint_16)num_palette; + + if (full_dither) + { + int i; + png_bytep distance; + int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + + PNG_DITHER_BLUE_BITS; + int num_red = (1 << PNG_DITHER_RED_BITS); + int num_green = (1 << PNG_DITHER_GREEN_BITS); + int num_blue = (1 << PNG_DITHER_BLUE_BITS); + png_size_t num_entries = ((png_size_t)1 << total_bits); + + png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr, + (png_uint_32)(num_entries * png_sizeof (png_byte))); + + png_memset(png_ptr->palette_lookup, 0, num_entries * + png_sizeof (png_byte)); + + distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + png_sizeof(png_byte))); + + png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); + + for (i = 0; i < num_palette; i++) + { + int ir, ig, ib; + int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); + int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); + int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); + + for (ir = 0; ir < num_red; ir++) + { + /* int dr = abs(ir - r); */ + int dr = ((ir > r) ? ir - r : r - ir); + int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS)); + + for (ig = 0; ig < num_green; ig++) + { + /* int dg = abs(ig - g); */ + int dg = ((ig > g) ? ig - g : g - ig); + int dt = dr + dg; + int dm = ((dr > dg) ? dr : dg); + int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); + + for (ib = 0; ib < num_blue; ib++) + { + int d_index = index_g | ib; + /* int db = abs(ib - b); */ + int db = ((ib > b) ? ib - b : b - ib); + int dmax = ((dm > db) ? dm : db); + int d = dmax + dt + db; + + if (d < (int)distance[d_index]) + { + distance[d_index] = (png_byte)d; + png_ptr->palette_lookup[d_index] = (png_byte)i; + } + } + } + } + } + + png_free(png_ptr, distance); + } +} +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) +/* Transform the image from the file_gamma to the screen_gamma. We + * only do transformations on images where the file_gamma and screen_gamma + * are not close reciprocals, otherwise it slows things down slightly, and + * also needlessly introduces small errors. + * + * We will turn off gamma transformation later if no semitransparent entries + * are present in the tRNS array for palette images. We can't do it here + * because we don't necessarily have the tRNS chunk yet. + */ +void PNGAPI +png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) +{ + png_debug(1, "in png_set_gamma\n"); + if(png_ptr == NULL) return; + if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) + png_ptr->transformations |= PNG_GAMMA; + png_ptr->gamma = (float)file_gamma; + png_ptr->screen_gamma = (float)scrn_gamma; +} +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) +/* Expand paletted images to RGB, expand grayscale images of + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks + * to alpha channels. + */ +void PNGAPI +png_set_expand(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand\n"); + if(png_ptr == NULL) return; + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); +#ifdef PNG_WARN_UNINITIALIZED_ROW + png_ptr->flags &= !(PNG_FLAG_ROW_INIT); +#endif +} + +/* GRR 19990627: the following three functions currently are identical + * to png_set_expand(). However, it is entirely reasonable that someone + * might wish to expand an indexed image to RGB but *not* expand a single, + * fully transparent palette entry to a full alpha channel--perhaps instead + * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace + * the transparent color with a particular RGB value, or drop tRNS entirely. + * IOW, a future version of the library may make the transformations flag + * a bit more fine-grained, with separate bits for each of these three + * functions. + * + * More to the point, these functions make it obvious what libpng will be + * doing, whereas "expand" can (and does) mean any number of things. + * + * GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified + * to expand only the sample depth but not to expand the tRNS to alpha. + */ + +/* Expand paletted images to RGB. */ +void PNGAPI +png_set_palette_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_palette_to_rgb\n"); + if(png_ptr == NULL) return; + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); +#ifdef PNG_WARN_UNINITIALIZED_ROW + png_ptr->flags &= !(PNG_FLAG_ROW_INIT); +#endif +} + +#if !defined(PNG_1_0_X) +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ +void PNGAPI +png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand_gray_1_2_4_to_8\n"); + if(png_ptr == NULL) return; + png_ptr->transformations |= PNG_EXPAND; +#ifdef PNG_WARN_UNINITIALIZED_ROW + png_ptr->flags &= !(PNG_FLAG_ROW_INIT); +#endif +} +#endif + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ +/* Deprecated as of libpng-1.2.9 */ +void PNGAPI +png_set_gray_1_2_4_to_8(png_structp png_ptr) +{ + png_debug(1, "in png_set_gray_1_2_4_to_8\n"); + if(png_ptr == NULL) return; + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); +} +#endif + + +/* Expand tRNS chunks to alpha channels. */ +void PNGAPI +png_set_tRNS_to_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_tRNS_to_alpha\n"); + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); +#ifdef PNG_WARN_UNINITIALIZED_ROW + png_ptr->flags &= !(PNG_FLAG_ROW_INIT); +#endif +} +#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +void PNGAPI +png_set_gray_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_gray_to_rgb\n"); + png_ptr->transformations |= PNG_GRAY_TO_RGB; +#ifdef PNG_WARN_UNINITIALIZED_ROW + png_ptr->flags &= !(PNG_FLAG_ROW_INIT); +#endif +} +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +#if defined(PNG_FLOATING_POINT_SUPPORTED) +/* Convert a RGB image to a grayscale of the same width. This allows us, + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. + */ + +void PNGAPI +png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, + double green) +{ + int red_fixed = (int)((float)red*100000.0 + 0.5); + int green_fixed = (int)((float)green*100000.0 + 0.5); + if(png_ptr == NULL) return; + png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed); +} +#endif + +void PNGAPI +png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, + png_fixed_point red, png_fixed_point green) +{ + png_debug(1, "in png_set_rgb_to_gray\n"); + if(png_ptr == NULL) return; + switch(error_action) + { + case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY; + break; + case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; + break; + case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; + } + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#if defined(PNG_READ_EXPAND_SUPPORTED) + png_ptr->transformations |= PNG_EXPAND; +#else + { + png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED."); + png_ptr->transformations &= ~PNG_RGB_TO_GRAY; + } +#endif + { + png_uint_16 red_int, green_int; + if(red < 0 || green < 0) + { + red_int = 6968; /* .212671 * 32768 + .5 */ + green_int = 23434; /* .715160 * 32768 + .5 */ + } + else if(red + green < 100000L) + { + red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); + green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); + } + else + { + png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); + red_int = 6968; + green_int = 23434; + } + png_ptr->rgb_to_gray_red_coeff = red_int; + png_ptr->rgb_to_gray_green_coeff = green_int; + png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(32768-red_int-green_int); + } +} +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +void PNGAPI +png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + read_user_transform_fn) +{ + png_debug(1, "in png_set_read_user_transform_fn\n"); + if(png_ptr == NULL) return; +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->read_user_transform_fn = read_user_transform_fn; +#endif +#ifdef PNG_LEGACY_SUPPORTED + if(read_user_transform_fn) + png_warning(png_ptr, + "This version of libpng does not support user transforms"); +#endif +} +#endif + +/* Initialize everything needed for the read. This includes modifying + * the palette. + */ +void /* PRIVATE */ +png_init_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_init_read_transformations\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if(png_ptr != NULL) +#endif + { +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \ + || defined(PNG_READ_GAMMA_SUPPORTED) + int color_type = png_ptr->color_type; +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + /* Detect gray background and attempt to enable optimization + * for gray --> RGB case */ + /* Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or + * RGB_ALPHA (in which case need_expand is superfluous anyway), the + * background color might actually be gray yet not be flagged as such. + * This is not a problem for the current code, which uses + * PNG_BACKGROUND_IS_GRAY only to decide when to do the + * png_do_gray_to_rgb() transformation. + */ + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + !(color_type & PNG_COLOR_MASK_COLOR)) + { + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + } else if ((png_ptr->transformations & PNG_BACKGROUND) && + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_GRAY_TO_RGB) && + png_ptr->background.red == png_ptr->background.green && + png_ptr->background.red == png_ptr->background.blue) + { + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + png_ptr->background.gray = png_ptr->background.red; + } +#endif + + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_EXPAND)) + { + if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ + { + /* expand background and tRNS chunks */ + switch (png_ptr->bit_depth) + { + case 1: + png_ptr->background.gray *= (png_uint_16)0xff; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_values.gray *= (png_uint_16)0xff; + png_ptr->trans_values.red = png_ptr->trans_values.green + = png_ptr->trans_values.blue = png_ptr->trans_values.gray; + } + break; + case 2: + png_ptr->background.gray *= (png_uint_16)0x55; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_values.gray *= (png_uint_16)0x55; + png_ptr->trans_values.red = png_ptr->trans_values.green + = png_ptr->trans_values.blue = png_ptr->trans_values.gray; + } + break; + case 4: + png_ptr->background.gray *= (png_uint_16)0x11; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_values.gray *= (png_uint_16)0x11; + png_ptr->trans_values.red = png_ptr->trans_values.green + = png_ptr->trans_values.blue = png_ptr->trans_values.gray; + } + break; + case 8: + case 16: + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + break; + } + } + else if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.red = + png_ptr->palette[png_ptr->background.index].red; + png_ptr->background.green = + png_ptr->palette[png_ptr->background.index].green; + png_ptr->background.blue = + png_ptr->palette[png_ptr->background.index].blue; + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_ALPHA) + { +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) +#endif + { + /* invert the alpha channel (in tRNS) unless the pixels are + going to be expanded, in which case leave it for later */ + int i,istop; + istop=(int)png_ptr->num_trans; + for (i=0; itrans[i] = (png_byte)(255 - png_ptr->trans[i]); + } + } +#endif + + } + } +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + png_ptr->background_1 = png_ptr->background; +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) + + if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0) + && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0) + < PNG_GAMMA_THRESHOLD)) + { + int i,k; + k=0; + for (i=0; inum_trans; i++) + { + if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff) + k=1; /* partial transparency is present */ + } + if (k == 0) + png_ptr->transformations &= (~PNG_GAMMA); + } + + if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) && + png_ptr->gamma != 0.0) + { + png_build_gamma_table(png_ptr); +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->transformations & PNG_BACKGROUND) + { + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + /* could skip if no transparency and + */ + png_color back, back_1; + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + double g, gs; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = 1.0; + break; + case PNG_BACKGROUND_GAMMA_FILE: + g = 1.0 / (png_ptr->gamma); + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + break; + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = 1.0 / (png_ptr->background_gamma); + gs = 1.0 / (png_ptr->background_gamma * + png_ptr->screen_gamma); + break; + default: + g = 1.0; /* back_1 */ + gs = 1.0; /* back */ + } + + if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD) + { + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + } + else + { + back.red = (png_byte)(pow( + (double)png_ptr->background.red/255, gs) * 255.0 + .5); + back.green = (png_byte)(pow( + (double)png_ptr->background.green/255, gs) * 255.0 + .5); + back.blue = (png_byte)(pow( + (double)png_ptr->background.blue/255, gs) * 255.0 + .5); + } + + back_1.red = (png_byte)(pow( + (double)png_ptr->background.red/255, g) * 255.0 + .5); + back_1.green = (png_byte)(pow( + (double)png_ptr->background.green/255, g) * 255.0 + .5); + back_1.blue = (png_byte)(pow( + (double)png_ptr->background.blue/255, g) * 255.0 + .5); + } + for (i = 0; i < num_palette; i++) + { + if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff) + { + if (png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else /* if (png_ptr->trans[i] != 0xff) */ + { + png_byte v, w; + + v = png_ptr->gamma_to_1[palette[i].red]; + png_composite(w, v, png_ptr->trans[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].green]; + png_composite(w, v, png_ptr->trans[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].blue]; + png_composite(w, v, png_ptr->trans[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } + /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ + else + /* color_type != PNG_COLOR_TYPE_PALETTE */ + { + double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); + double g = 1.0; + double gs = 1.0; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = 1.0; + break; + case PNG_BACKGROUND_GAMMA_FILE: + g = 1.0 / (png_ptr->gamma); + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + break; + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = 1.0 / (png_ptr->background_gamma); + gs = 1.0 / (png_ptr->background_gamma * + png_ptr->screen_gamma); + break; + } + + png_ptr->background_1.gray = (png_uint_16)(pow( + (double)png_ptr->background.gray / m, g) * m + .5); + png_ptr->background.gray = (png_uint_16)(pow( + (double)png_ptr->background.gray / m, gs) * m + .5); + + if ((png_ptr->background.red != png_ptr->background.green) || + (png_ptr->background.red != png_ptr->background.blue) || + (png_ptr->background.red != png_ptr->background.gray)) + { + /* RGB or RGBA with color background */ + png_ptr->background_1.red = (png_uint_16)(pow( + (double)png_ptr->background.red / m, g) * m + .5); + png_ptr->background_1.green = (png_uint_16)(pow( + (double)png_ptr->background.green / m, g) * m + .5); + png_ptr->background_1.blue = (png_uint_16)(pow( + (double)png_ptr->background.blue / m, g) * m + .5); + png_ptr->background.red = (png_uint_16)(pow( + (double)png_ptr->background.red / m, gs) * m + .5); + png_ptr->background.green = (png_uint_16)(pow( + (double)png_ptr->background.green / m, gs) * m + .5); + png_ptr->background.blue = (png_uint_16)(pow( + (double)png_ptr->background.blue / m, gs) * m + .5); + } + else + { + /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ + png_ptr->background_1.red = png_ptr->background_1.green + = png_ptr->background_1.blue = png_ptr->background_1.gray; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + } + } + } + else + /* transformation does not include PNG_BACKGROUND */ +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + else +#endif +#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */ +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + /* No GAMMA transformation */ + if ((png_ptr->transformations & PNG_BACKGROUND) && + (color_type == PNG_COLOR_TYPE_PALETTE)) + { + int i; + int istop = (int)png_ptr->num_trans; + png_color back; + png_colorp palette = png_ptr->palette; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < istop; i++) + { + if (png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else if (png_ptr->trans[i] != 0xff) + { + /* The png_composite() macro is defined in png.h */ + png_composite(palette[i].red, palette[i].red, + png_ptr->trans[i], back.red); + png_composite(palette[i].green, palette[i].green, + png_ptr->trans[i], back.green); + png_composite(palette[i].blue, palette[i].blue, + png_ptr->trans[i], back.blue); + } + } + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + +#if defined(PNG_READ_SHIFT_SUPPORTED) + if ((png_ptr->transformations & PNG_SHIFT) && + (color_type == PNG_COLOR_TYPE_PALETTE)) + { + png_uint_16 i; + png_uint_16 istop = png_ptr->num_palette; + int sr = 8 - png_ptr->sig_bit.red; + int sg = 8 - png_ptr->sig_bit.green; + int sb = 8 - png_ptr->sig_bit.blue; + + if (sr < 0 || sr > 8) + sr = 0; + if (sg < 0 || sg > 8) + sg = 0; + if (sb < 0 || sb > 8) + sb = 0; + for (i = 0; i < istop; i++) + { + png_ptr->palette[i].red >>= sr; + png_ptr->palette[i].green >>= sg; + png_ptr->palette[i].blue >>= sb; + } + } +#endif /* PNG_READ_SHIFT_SUPPORTED */ + } +#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \ + && !defined(PNG_READ_BACKGROUND_SUPPORTED) + if(png_ptr) + return; +#endif +} + +/* Modify the info structure to reflect the transformations. The + * info should be updated so a PNG file could be written with it, + * assuming the transformations result in valid PNG data. + */ +void /* PRIVATE */ +png_read_transform_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_transform_info\n"); +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (png_ptr->transformations & PNG_EXPAND) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND_tRNS)) + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + else + info_ptr->color_type = PNG_COLOR_TYPE_RGB; + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + else + { + if (png_ptr->num_trans) + { + if (png_ptr->transformations & PNG_EXPAND_tRNS) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + else + info_ptr->color_type |= PNG_COLOR_MASK_COLOR; + } + if (info_ptr->bit_depth < 8) + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + } +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->transformations & PNG_BACKGROUND) + { + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; + info_ptr->num_trans = 0; + info_ptr->background = png_ptr->background; + } +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (png_ptr->transformations & PNG_GAMMA) + { +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->gamma = png_ptr->gamma; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = png_ptr->int_gamma; +#endif + } +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) + if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16)) + info_ptr->bit_depth = 8; +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + info_ptr->color_type |= PNG_COLOR_MASK_COLOR; +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) + if (png_ptr->transformations & PNG_DITHER) + { + if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && + png_ptr->palette_lookup && info_ptr->bit_depth == 8) + { + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; + } + } +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) + if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) + info_ptr->bit_depth = 8; +#endif + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + else + info_ptr->channels = 1; + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) + if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; +#endif + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + +#if defined(PNG_READ_FILLER_SUPPORTED) + /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ + if ((png_ptr->transformations & PNG_FILLER) && + ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) + { + info_ptr->channels++; + /* if adding a true alpha channel not just filler */ +#if !defined(PNG_1_0_X) + if (png_ptr->transformations & PNG_ADD_ALPHA) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; +#endif + } +#endif + +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ +defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + if(png_ptr->transformations & PNG_USER_TRANSFORM) + { + if(info_ptr->bit_depth < png_ptr->user_transform_depth) + info_ptr->bit_depth = png_ptr->user_transform_depth; + if(info_ptr->channels < png_ptr->user_transform_channels) + info_ptr->channels = png_ptr->user_transform_channels; + } +#endif + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * + info_ptr->bit_depth); + + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,info_ptr->width); + +#if !defined(PNG_READ_EXPAND_SUPPORTED) + if(png_ptr) + return; +#endif +} + +/* Transform the row. The order of transformations is significant, + * and is very touchy. If you add a transformation, take care to + * decide how it fits in with the other transformations here. + */ +void /* PRIVATE */ +png_do_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_read_transformations\n"); + if (png_ptr->row_buf == NULL) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[50]; + + png_snprintf2(msg, 50, + "NULL row buffer for row %ld, pass %d", png_ptr->row_number, + png_ptr->pass); + png_error(png_ptr, msg); +#else + png_error(png_ptr, "NULL row buffer"); +#endif + } +#ifdef PNG_WARN_UNINITIALIZED_ROW + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + /* Application has failed to call either png_read_start_image() + * or png_read_update_info() after setting transforms that expand + * pixels. This check added to libpng-1.2.19 */ +#if (PNG_WARN_UNINITIALIZED_ROW==1) + png_error(png_ptr, "Uninitialized row"); +#else + png_warning(png_ptr, "Uninitialized row"); +#endif +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) + { + png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette, png_ptr->trans, png_ptr->num_trans); + } + else + { + if (png_ptr->num_trans && + (png_ptr->transformations & PNG_EXPAND_tRNS)) + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_values)); + else + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + NULL); + } + } +#endif + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) + if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)); +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + { + int rgb_error = + png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1); + if(rgb_error) + { + png_ptr->rgb_to_gray_status=1; + if((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_WARN) + png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + if((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_ERR) + png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + } + } +#endif + +/* +From Andreas Dilger e-mail to png-implement, 26 March 1998: + + In most cases, the "simple transparency" should be done prior to doing + gray-to-RGB, or you will have to test 3x as many bytes to check if a + pixel is transparent. You would also need to make sure that the + transparency information is upgraded to RGB. + + To summarize, the current flow is: + - Gray + simple transparency -> compare 1 or 2 gray bytes and composite + with background "in place" if transparent, + convert to RGB if necessary + - Gray + alpha -> composite with gray background and remove alpha bytes, + convert to RGB if necessary + + To support RGB backgrounds for gray images we need: + - Gray + simple transparency -> convert to RGB + simple transparency, compare + 3 or 6 bytes and composite with background + "in place" if transparent (3x compare/pixel + compared to doing composite with gray bkgrnd) + - Gray + alpha -> convert to RGB + alpha, composite with background and + remove alpha bytes (3x float operations/pixel + compared with composite on gray background) + + Greg's change will do this. The reason it wasn't done before is for + performance, as this increases the per-pixel operations. If we would check + in advance if the background was gray or RGB, and position the gray-to-RGB + transform appropriately, then it would save a lot of work/time. + */ + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + /* if gray -> RGB, do so now only if background is non-gray; else do later + * for performance reasons */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if ((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0 ) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) + png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_values), &(png_ptr->background) +#if defined(PNG_READ_GAMMA_SUPPORTED) + , &(png_ptr->background_1), + png_ptr->gamma_table, png_ptr->gamma_from_1, + png_ptr->gamma_to_1, png_ptr->gamma_16_table, + png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, + png_ptr->gamma_shift +#endif +); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) + if ((png_ptr->transformations & PNG_GAMMA) && +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + !((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && +#endif + (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) + png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->gamma_table, png_ptr->gamma_16_table, + png_ptr->gamma_shift); +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) + if (png_ptr->transformations & PNG_16_TO_8) + png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) + if (png_ptr->transformations & PNG_DITHER) + { + png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette_lookup, png_ptr->dither_index); + if(png_ptr->row_info.rowbytes == (png_uint_32)0) + png_error(png_ptr, "png_do_dither returned rowbytes=0"); + } +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + /* if gray -> RGB, do so now only if we did not do so above */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->filler, png_ptr->flags); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if(png_ptr->read_user_transform_fn != NULL) + (*(png_ptr->read_user_transform_fn)) /* user read transform function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_uint_32 rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if(png_ptr->user_transform_depth) + png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; + if(png_ptr->user_transform_channels) + png_ptr->row_info.channels = png_ptr->user_transform_channels; +#endif + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + } +#endif + +} + +#if defined(PNG_READ_PACK_SUPPORTED) +/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, + * without changing the actual values. Thus, if you had a row with + * a bit depth of 1, you would end up with bytes that only contained + * the numbers 0 or 1. If you would rather they contain 0 and 255, use + * png_do_shift() after this. + */ +void /* PRIVATE */ +png_do_unpack(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_unpack\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && row_info->bit_depth < 8) +#else + if (row_info->bit_depth < 8) +#endif + { + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + switch (row_info->bit_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x01); + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + case 2: + { + + png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x03); + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + case 4: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x0f); + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift = 4; + + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_width * row_info->channels; + } +} +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) +/* Reverse the effects of png_do_shift. This routine merely shifts the + * pixels back to their significant bits values. Thus, if you have + * a row of bit depth 8, but only 5 are significant, this will shift + * the values back to 0 through 31. + */ +void /* PRIVATE */ +png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) +{ + png_debug(1, "in png_do_unshift\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && sig_bits != NULL && +#endif + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift[4]; + int channels = 0; + int c; + png_uint_16 value = 0; + png_uint_32 row_width = row_info->width; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift[channels++] = row_info->bit_depth - sig_bits->red; + shift[channels++] = row_info->bit_depth - sig_bits->green; + shift[channels++] = row_info->bit_depth - sig_bits->blue; + } + else + { + shift[channels++] = row_info->bit_depth - sig_bits->gray; + } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift[channels++] = row_info->bit_depth - sig_bits->alpha; + } + + for (c = 0; c < channels; c++) + { + if (shift[c] <= 0) + shift[c] = 0; + else + value = 1; + } + + if (!value) + return; + + switch (row_info->bit_depth) + { + case 2: + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (bp = row, i = 0; i < istop; i++) + { + *bp >>= 1; + *bp++ &= 0x55; + } + break; + } + case 4: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | + (png_byte)((int)0xf >> shift[0])); + + for (i = 0; i < istop; i++) + { + *bp >>= shift[0]; + *bp++ &= mask; + } + break; + } + case 8: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_width * channels; + + for (i = 0; i < istop; i++) + { + *bp++ >>= shift[i%channels]; + } + break; + } + case 16: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_width; + + for (i = 0; i < istop; i++) + { + value = (png_uint_16)((*bp << 8) + *(bp + 1)); + value >>= shift[i%channels]; + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + break; + } + } + } +} +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +/* chop rows of bit depth 16 down to 8 */ +void /* PRIVATE */ +png_do_chop(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_chop\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && row_info->bit_depth == 16) +#else + if (row_info->bit_depth == 16) +#endif + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + png_uint_32 istop = row_info->width * row_info->channels; + + for (i = 0; i> 8)) >> 8; + * + * Approximate calculation with shift/add instead of multiply/divide: + * *dp = ((((png_uint_32)(*sp) << 8) | + * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; + * + * What we actually do to avoid extra shifting and conversion: + */ + + *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); +#else + /* Simply discard the low order byte */ + *dp = *sp; +#endif + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_info->width * row_info->channels; + } +} +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_swap_alpha\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + /* This converts from RRGGBBAA to AARRGGBB */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + /* This converts from GGAA to AAGG */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } + } +} +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_invert_alpha\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This inverts the alpha channel in RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=3; + dp=sp; + } + } + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=6; + dp=sp; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This inverts the alpha channel in GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = *(--sp); + } + } + /* This inverts the alpha channel in GGAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); +/* + *(--dp) = *(--sp); + *(--dp) = *(--sp); +*/ + sp-=2; + dp=sp; + } + } + } + } +} +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) +/* Add filler channel if we have RGB color */ +void /* PRIVATE */ +png_do_read_filler(png_row_infop row_info, png_bytep row, + png_uint_32 filler, png_uint_32 flags) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_byte hi_filler = (png_byte)((filler>>8) & 0xff); + png_byte lo_filler = (png_byte)(filler & 0xff); + + png_debug(1, "in png_do_read_filler\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if(row_info->bit_depth == 8) + { + /* This changes the data from G to GX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + /* This changes the data from G to XG */ + else + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + } + else if(row_info->bit_depth == 16) + { + /* This changes the data from GG to GGXX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + /* This changes the data from GG to XXGG */ + else + { + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + } /* COLOR_TYPE == GRAY */ + else if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if(row_info->bit_depth == 8) + { + /* This changes the data from RGB to RGBX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + /* This changes the data from RGB to XRGB */ + else + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + else if(row_info->bit_depth == 16) + { + /* This changes the data from RRGGBB to RRGGBBXX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + /* This changes the data from RRGGBB to XXRRGGBB */ + else + { + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + } + } /* COLOR_TYPE == RGB */ +} +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +/* expand grayscale files to RGB, with or without alpha */ +void /* PRIVATE */ +png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_gray_to_rgb\n"); + if (row_info->bit_depth >= 8 && +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + !(row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + (png_size_t)row_width - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + else + { + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + else + { + png_bytep sp = row + (png_size_t)row_width * 4 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + row_info->channels += (png_byte)2; + row_info->color_type |= PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } +} +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +/* reduce RGB files to grayscale, with or without alpha + * using the equation given in Poynton's ColorFAQ at + * + * Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net + * + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + * + * We approximate this with + * + * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B + * + * which can be expressed with integers as + * + * Y = (6969 * R + 23434 * G + 2365 * B)/32768 + * + * The calculation is to be done in a linear colorspace. + * + * Other integer coefficents can be used via png_set_rgb_to_gray(). + */ +int /* PRIVATE */ +png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) + +{ + png_uint_32 i; + + png_uint_32 row_width = row_info->width; + int rgb_error = 0; + + png_debug(1, "in png_do_rgb_to_gray\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if(red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1[ + (rc*red+gc*green+bc*blue)>>15]; + } + else + *(dp++) = *(sp-1); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if(red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15); + } + else + *(dp++) = *(sp-1); + } + } + } + + else /* RGB bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if(red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 + + bc*blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if(red != green || red != blue) + rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + } + } + } + } + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if(red != green || red != blue) + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1 + [(rc*red + gc*green + bc*blue)>>15]; + *(dp++) = *(sp++); /* alpha */ + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if(red != green || red != blue) + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = *(sp++); /* alpha */ + } + } + } + else /* RGBA bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if(red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc * red_1 + + gc * green_1 + bc * blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + if(red != green || red != blue) + rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + } + } + row_info->channels -= (png_byte)2; + row_info->color_type &= ~PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } + return rgb_error; +} +#endif + +/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth + * large of png_color. This lets grayscale images be treated as + * paletted. Most useful for gamma correction and simplification + * of code. + */ +void PNGAPI +png_build_grayscale_palette(int bit_depth, png_colorp palette) +{ + int num_palette; + int color_inc; + int i; + int v; + + png_debug(1, "in png_do_build_grayscale_palette\n"); + if (palette == NULL) + return; + + switch (bit_depth) + { + case 1: + num_palette = 2; + color_inc = 0xff; + break; + case 2: + num_palette = 4; + color_inc = 0x55; + break; + case 4: + num_palette = 16; + color_inc = 0x11; + break; + case 8: + num_palette = 256; + color_inc = 1; + break; + default: + num_palette = 0; + color_inc = 0; + break; + } + + for (i = 0, v = 0; i < num_palette; i++, v += color_inc) + { + palette[i].red = (png_byte)v; + palette[i].green = (png_byte)v; + palette[i].blue = (png_byte)v; + } +} + +/* This function is currently unused. Do we really need it? */ +#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED) +void /* PRIVATE */ +png_correct_palette(png_structp png_ptr, png_colorp palette, + int num_palette) +{ + png_debug(1, "in png_correct_palette\n"); +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) + if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND)) + { + png_color back, back_1; + + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + double g; + + g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma); + + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN || + fabs(g - 1.0) < PNG_GAMMA_THRESHOLD) + { + back.red = png_ptr->background.red; + back.green = png_ptr->background.green; + back.blue = png_ptr->background.blue; + } + else + { + back.red = + (png_byte)(pow((double)png_ptr->background.red/255, g) * + 255.0 + 0.5); + back.green = + (png_byte)(pow((double)png_ptr->background.green/255, g) * + 255.0 + 0.5); + back.blue = + (png_byte)(pow((double)png_ptr->background.blue/255, g) * + 255.0 + 0.5); + } + + g = 1.0 / png_ptr->background_gamma; + + back_1.red = + (png_byte)(pow((double)png_ptr->background.red/255, g) * + 255.0 + 0.5); + back_1.green = + (png_byte)(pow((double)png_ptr->background.green/255, g) * + 255.0 + 0.5); + back_1.blue = + (png_byte)(pow((double)png_ptr->background.blue/255, g) * + 255.0 + 0.5); + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_uint_32 i; + + for (i = 0; i < (png_uint_32)num_palette; i++) + { + if (i < png_ptr->num_trans && png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff) + { + png_byte v, w; + + v = png_ptr->gamma_to_1[png_ptr->palette[i].red]; + png_composite(w, v, png_ptr->trans[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[png_ptr->palette[i].green]; + png_composite(w, v, png_ptr->trans[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[png_ptr->palette[i].blue]; + png_composite(w, v, png_ptr->trans[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } + else + { + int i; + + for (i = 0; i < num_palette; i++) + { + if (palette[i].red == (png_byte)png_ptr->trans_values.gray) + { + palette[i] = back; + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } + } + else +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (png_ptr->transformations & PNG_GAMMA) + { + int i; + + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + else +#endif +#endif +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->transformations & PNG_BACKGROUND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_color back; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < (int)png_ptr->num_trans; i++) + { + if (png_ptr->trans[i] == 0) + { + palette[i].red = back.red; + palette[i].green = back.green; + palette[i].blue = back.blue; + } + else if (png_ptr->trans[i] != 0xff) + { + png_composite(palette[i].red, png_ptr->palette[i].red, + png_ptr->trans[i], back.red); + png_composite(palette[i].green, png_ptr->palette[i].green, + png_ptr->trans[i], back.green); + png_composite(palette[i].blue, png_ptr->palette[i].blue, + png_ptr->trans[i], back.blue); + } + } + } + else /* assume grayscale palette (what else could it be?) */ + { + int i; + + for (i = 0; i < num_palette; i++) + { + if (i == (png_byte)png_ptr->trans_values.gray) + { + palette[i].red = (png_byte)png_ptr->background.red; + palette[i].green = (png_byte)png_ptr->background.green; + palette[i].blue = (png_byte)png_ptr->background.blue; + } + } + } + } +#endif +} +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) +/* Replace any alpha or transparency with the supplied background color. + * "background" is already in the screen gamma, while "background_1" is + * at a gamma of 1.0. Paletted files have already been taken care of. + */ +void /* PRIVATE */ +png_do_background(png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background +#if defined(PNG_READ_GAMMA_SUPPORTED) + , png_color_16p background_1, + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, + png_uint_16pp gamma_16_to_1, int gamma_shift +#endif + ) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + int shift; + + png_debug(1, "in png_do_background\n"); + if (background != NULL && +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || + (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_GRAY: + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x01) + == trans_values->gray) + { + *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 7; + sp++; + } + else + shift--; + } + break; + } + case 2: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_values->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x03); + png_byte g = (png_byte)((gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03); + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; + } + } + else +#endif + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_values->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; + } + } + break; + } + case 4: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_values->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x0f); + png_byte g = (png_byte)((gamma_table[p | + (p << 4)] >> 4) & 0x0f); + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; + } + } + else +#endif + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_values->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; + } + } + break; + } + case 8: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_values->gray) + { + *sp = (png_byte)background->gray; + } + else + { + *sp = gamma_table[*sp]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_values->gray) + { + *sp = (png_byte)background->gray; + } + } + } + break; + } + case 16: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_values->gray) + { + /* background is already in screen gamma */ + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + else + { + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_values->gray) + { + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + } + } + break; + } + } + break; + } + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_values->red && + *(sp + 1) == trans_values->green && + *(sp + 2) == trans_values->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_values->red && + *(sp + 1) == trans_values->green && + *(sp + 2) == trans_values->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); + if (r == trans_values->red && g == trans_values->green && + b == trans_values->blue) + { + /* background is already in screen gamma */ + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1)); + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); + + if (r == trans_values->red && g == trans_values->green && + b == trans_values->blue) + { + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + } + } + } + break; + } + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + { + *dp = gamma_table[*sp]; + } + else if (a == 0) + { + /* background is already in screen gamma */ + *dp = (png_byte)background->gray; + } + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->gray); + *dp = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_byte a = *(sp + 1); + + if (a == 0xff) + { + *dp = *sp; + } +#if defined(PNG_READ_GAMMA_SUPPORTED) + else if (a == 0) + { + *dp = (png_byte)background->gray; + } + else + { + png_composite(*dp, *sp, a, background_1->gray); + } +#else + *dp = (png_byte)background->gray; +#endif + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } +#if defined(PNG_READ_GAMMA_SUPPORTED) + else if (a == 0) +#else + else +#endif + { + /* background is already in screen gamma */ + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } +#if defined(PNG_READ_GAMMA_SUPPORTED) + else + { + png_uint_16 g, v, w; + + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, background_1->gray); + w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; + *dp = (png_byte)((w >> 8) & 0xff); + *(dp + 1) = (png_byte)(w & 0xff); + } +#endif + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + if (a == (png_uint_16)0xffff) + { + png_memcpy(dp, sp, 2); + } +#if defined(PNG_READ_GAMMA_SUPPORTED) + else if (a == 0) +#else + else +#endif + { + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } +#if defined(PNG_READ_GAMMA_SUPPORTED) + else + { + png_uint_16 g, v; + + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, background_1->gray); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } +#endif + } + } + } + break; + } + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = gamma_table[*sp]; + *(dp + 1) = gamma_table[*(sp + 1)]; + *(dp + 2) = gamma_table[*(sp + 2)]; + } + else if (a == 0) + { + /* background is already in screen gamma */ + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->red); + *dp = gamma_from_1[w]; + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, background_1->green); + *(dp + 1) = gamma_from_1[w]; + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, background_1->blue); + *(dp + 2) = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = *sp; + *(dp + 1) = *(sp + 1); + *(dp + 2) = *(sp + 2); + } + else if (a == 0) + { + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + else + { + png_composite(*dp, *sp, a, background->red); + png_composite(*(dp + 1), *(sp + 1), a, + background->green); + png_composite(*(dp + 2), *(sp + 2), a, + background->blue); + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + else if (a == 0) + { + /* background is already in screen gamma */ + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v, w, x; + + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, background_1->red); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *dp = (png_byte)((x >> 8) & 0xff); + *(dp + 1) = (png_byte)(x & 0xff); + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, background_1->green); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *(dp + 2) = (png_byte)((x >> 8) & 0xff); + *(dp + 3) = (png_byte)(x & 0xff); + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, background_1->blue); + x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; + *(dp + 4) = (png_byte)((x >> 8) & 0xff); + *(dp + 5) = (png_byte)(x & 0xff); + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) + { + png_memcpy(dp, sp, 6); + } + else if (a == 0) + { + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v; + + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + png_composite_16(v, r, a, background->red); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + png_composite_16(v, g, a, background->green); + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + png_composite_16(v, b, a, background->blue); + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + } + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; + row_info->channels--; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } + } +} +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) +/* Gamma correct the image, avoiding the alpha channel. Make sure + * you do this after you deal with the transparency issue on grayscale + * or RGB images. If your bit depth is 8, use gamma_table, if it + * is 16, use gamma_16_table and gamma_shift. Build these with + * build_gamma_table(). + */ +void /* PRIVATE */ +png_do_gamma(png_row_infop row_info, png_bytep row, + png_bytep gamma_table, png_uint_16pp gamma_16_table, + int gamma_shift) +{ + png_bytep sp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_gamma\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + ((row_info->bit_depth <= 8 && gamma_table != NULL) || + (row_info->bit_depth == 16 && gamma_16_table != NULL))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + sp++; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp += 2; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + case PNG_COLOR_TYPE_GRAY: + { + if (row_info->bit_depth == 2) + { + sp = row; + for (i = 0; i < row_width; i += 4) + { + int a = *sp & 0xc0; + int b = *sp & 0x30; + int c = *sp & 0x0c; + int d = *sp & 0x03; + + *sp = (png_byte)( + ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| + ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| + ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| + ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); + sp++; + } + } + if (row_info->bit_depth == 4) + { + sp = row; + for (i = 0; i < row_width; i += 2) + { + int msb = *sp & 0xf0; + int lsb = *sp & 0x0f; + + *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) + | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); + sp++; + } + } + else if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + } + } + else if (row_info->bit_depth == 16) + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + } + } +} +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) +/* Expands a palette row to an RGB or RGBA row depending + * upon whether you supply trans and num_trans. + */ +void /* PRIVATE */ +png_do_expand_palette(png_row_infop row_info, png_bytep row, + png_colorp palette, png_bytep trans, int num_trans) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand_palette\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 1; + else + *dp = 0; + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + case 2: + { + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)value; + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + case 4: + { + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((row_width & 0x01) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)value; + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift += 4; + + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + switch (row_info->bit_depth) + { + case 8: + { + if (trans != NULL) + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + + for (i = 0; i < row_width; i++) + { + if ((int)(*sp) >= num_trans) + *dp-- = 0xff; + else + *dp-- = trans[*sp]; + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + row_info->color_type = 6; + row_info->channels = 4; + } + else + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width * 3) - 1; + + for (i = 0; i < row_width; i++) + { + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + row_info->color_type = 2; + row_info->channels = 3; + } + break; + } + } + } +} + +/* If the bit depth < 8, it is expanded to 8. Also, if the already + * expanded transparency value is supplied, an alpha channel is built. + */ +void /* PRIVATE */ +png_do_expand(png_row_infop row_info, png_bytep row, + png_color_16p trans_value) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); + + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + gray = (png_uint_16)((gray&0x01)*0xff); + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 0xff; + else + *dp = 0; + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + case 2: + { + gray = (png_uint_16)((gray&0x03)*0x55); + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + case 4: + { + gray = (png_uint_16)((gray&0x0f)*0x11); + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift = 4; + + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (trans_value != NULL) + { + if (row_info->bit_depth == 8) + { + gray = gray & 0xff; + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*sp == gray) + *dp-- = 0; + else + *dp-- = 0xff; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + png_byte gray_high = (gray >> 8) & 0xff; + png_byte gray_low = gray & 0xff; + sp = row + row_info->rowbytes - 1; + dp = row + (row_info->rowbytes << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp-1) == gray_high && *(sp) == gray_low) + { + *dp-- = 0; + *dp-- = 0; + } + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) + { + if (row_info->bit_depth == 8) + { + png_byte red = trans_value->red & 0xff; + png_byte green = trans_value->green & 0xff; + png_byte blue = trans_value->blue & 0xff; + sp = row + (png_size_t)row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + *dp-- = 0; + else + *dp-- = 0xff; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + png_byte red_high = (trans_value->red > 8) & 0xff; + png_byte green_high = (trans_value->green > 8) & 0xff; + png_byte blue_high = (trans_value->blue > 8) & 0xff; + png_byte red_low = trans_value->red & 0xff; + png_byte green_low = trans_value->green & 0xff; + png_byte blue_low = trans_value->blue & 0xff; + sp = row + row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 5) == red_high && + *(sp - 4) == red_low && + *(sp - 3) == green_high && + *(sp - 2) == green_low && + *(sp - 1) == blue_high && + *(sp ) == blue_low) + { + *dp-- = 0; + *dp-- = 0; + } + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } + } +} +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +void /* PRIVATE */ +png_do_dither(png_row_infop row_info, png_bytep row, + png_bytep palette_lookup, png_bytep dither_lookup) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_dither\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB && + palette_lookup && row_info->bit_depth == 8) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + + /* this looks real messy, but the compiler will reduce + it down to a reasonable formula. For example, with + 5 bits per color, we get: + p = (((r >> 3) & 0x1f) << 10) | + (((g >> 3) & 0x1f) << 5) | + ((b >> 3) & 0x1f); + */ + p = (((r >> (8 - PNG_DITHER_RED_BITS)) & + ((1 << PNG_DITHER_RED_BITS) - 1)) << + (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | + (((g >> (8 - PNG_DITHER_GREEN_BITS)) & + ((1 << PNG_DITHER_GREEN_BITS) - 1)) << + (PNG_DITHER_BLUE_BITS)) | + ((b >> (8 - PNG_DITHER_BLUE_BITS)) & + ((1 << PNG_DITHER_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + palette_lookup != NULL && row_info->bit_depth == 8) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + sp++; + + p = (((r >> (8 - PNG_DITHER_RED_BITS)) & + ((1 << PNG_DITHER_RED_BITS) - 1)) << + (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | + (((g >> (8 - PNG_DITHER_GREEN_BITS)) & + ((1 << PNG_DITHER_GREEN_BITS) - 1)) << + (PNG_DITHER_BLUE_BITS)) | + ((b >> (8 - PNG_DITHER_BLUE_BITS)) & + ((1 << PNG_DITHER_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } + else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && + dither_lookup && row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + *sp = dither_lookup[*sp]; + } + } + } +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +#if defined(PNG_READ_GAMMA_SUPPORTED) +static PNG_CONST int png_gamma_shift[] = + {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00}; + +/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit + * tables, we don't make a full table if we are reducing to 8-bit in + * the future. Note also how the gamma_16 tables are segmented so that + * we don't need to allocate > 64K chunks for a full 16-bit table. + */ +void /* PRIVATE */ +png_build_gamma_table(png_structp png_ptr) +{ + png_debug(1, "in png_build_gamma_table\n"); + + if (png_ptr->bit_depth <= 8) + { + int i; + double g; + + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + else + g = 1.0; + + png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + } + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) + { + + g = 1.0 / (png_ptr->gamma); + + png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + } + + + png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + if(png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + else + g = png_ptr->gamma; /* probably doing rgb_to_gray */ + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + + } + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ + } + else + { + double g; + int i, j, shift, num; + int sig_bit; + png_uint_32 ig; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit = (int)png_ptr->sig_bit.red; + if ((int)png_ptr->sig_bit.green > sig_bit) + sig_bit = png_ptr->sig_bit.green; + if ((int)png_ptr->sig_bit.blue > sig_bit) + sig_bit = png_ptr->sig_bit.blue; + } + else + { + sig_bit = (int)png_ptr->sig_bit.gray; + } + + if (sig_bit > 0) + shift = 16 - sig_bit; + else + shift = 0; + + if (png_ptr->transformations & PNG_16_TO_8) + { + if (shift < (16 - PNG_MAX_GAMMA_8)) + shift = (16 - PNG_MAX_GAMMA_8); + } + + if (shift > 8) + shift = 8; + if (shift < 0) + shift = 0; + + png_ptr->gamma_shift = (png_byte)shift; + + num = (1 << (8 - shift)); + + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + else + g = 1.0; + + png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr, + (png_uint_32)(num * png_sizeof (png_uint_16p))); + + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) + { + double fin, fout; + png_uint_32 last, max; + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof (png_uint_16))); + } + + g = 1.0 / g; + last = 0; + for (i = 0; i < 256; i++) + { + fout = ((double)i + 0.5) / 256.0; + fin = pow(fout, g); + max = (png_uint_32)(fin * (double)((png_uint_32)num << 8)); + while (last <= max) + { + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] + [(int)(last >> (8 - shift))] = (png_uint_16)( + (png_uint_16)i | ((png_uint_16)i << 8)); + last++; + } + } + while (last < ((png_uint_32)num << 8)) + { + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] + [(int)(last >> (8 - shift))] = (png_uint_16)65535L; + last++; + } + } + else + { + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof (png_uint_16))); + + ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_table[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + } + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) + { + + g = 1.0 / (png_ptr->gamma); + + png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr, + (png_uint_32)(num * png_sizeof (png_uint_16p ))); + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof (png_uint_16))); + + ig = (((png_uint_32)i * + (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_to_1[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + + if(png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + else + g = png_ptr->gamma; /* probably doing rgb_to_gray */ + + png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr, + (png_uint_32)(num * png_sizeof (png_uint_16p))); + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof (png_uint_16))); + + ig = (((png_uint_32)i * + (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_from_1[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ + } +} +#endif +/* To do: install integer version of png_build_gamma_table here */ +#endif + +#if defined(PNG_MNG_FEATURES_SUPPORTED) +/* undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_read_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_intrapixel\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff); + *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); + png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); + png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); + png_uint_32 red = (png_uint_32)((s0+s1+65536L) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2+s1+65536L) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp+1) = (png_byte)(red & 0xff); + *(rp+4) = (png_byte)((blue >> 8) & 0xff); + *(rp+5) = (png_byte)(blue & 0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pngrutil.c b/kernel/kls_png/ksquirrel-libs-png/pngrutil.c new file mode 100644 index 0000000..899cdc4 --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngrutil.c @@ -0,0 +1,3392 @@ + +/* pngrutil.c - utilities to read a PNG file + * + * Last changed in libpng 1.2.19 August 19, 2007 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2007 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file contains routines that are only called from within + * libpng itself during the course of reading an image. + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(PNG_READ_SUPPORTED) + +#if defined(_WIN32_WCE) && (_WIN32_WCE<0x500) +# define WIN32_WCE_OLD +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +# if defined(WIN32_WCE_OLD) +/* strtod() function is not supported on WindowsCE */ +__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr) +{ + double result = 0; + int len; + wchar_t *str, *end; + + len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0); + str = (wchar_t *)png_malloc(png_ptr, len * sizeof(wchar_t)); + if ( NULL != str ) + { + MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len); + result = wcstod(str, &end); + len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL); + *endptr = (char *)nptr + (png_strlen(nptr) - len + 1); + png_free(png_ptr, str); + } + return result; +} +# else +# define png_strtod(p,a,b) strtod(a,b) +# endif +#endif + +png_uint_32 PNGAPI +png_get_uint_31(png_structp png_ptr, png_bytep buf) +{ + png_uint_32 i = png_get_uint_32(buf); + if (i > PNG_UINT_31_MAX) + png_error(png_ptr, "PNG unsigned integer out of range."); + return (i); +} +#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED +/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ +png_uint_32 PNGAPI +png_get_uint_32(png_bytep buf) +{ + png_uint_32 i = ((png_uint_32)(*buf) << 24) + + ((png_uint_32)(*(buf + 1)) << 16) + + ((png_uint_32)(*(buf + 2)) << 8) + + (png_uint_32)(*(buf + 3)); + + return (i); +} + +/* Grab a signed 32-bit integer from a buffer in big-endian format. The + * data is stored in the PNG file in two's complement format, and it is + * assumed that the machine format for signed integers is the same. */ +png_int_32 PNGAPI +png_get_int_32(png_bytep buf) +{ + png_int_32 i = ((png_int_32)(*buf) << 24) + + ((png_int_32)(*(buf + 1)) << 16) + + ((png_int_32)(*(buf + 2)) << 8) + + (png_int_32)(*(buf + 3)); + + return (i); +} + +/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ +png_uint_16 PNGAPI +png_get_uint_16(png_bytep buf) +{ + png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) + + (png_uint_16)(*(buf + 1))); + + return (i); +} +#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */ + +/* Read data, and (optionally) run it through the CRC. */ +void /* PRIVATE */ +png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) +{ + if(png_ptr == NULL) return; + png_read_data(png_ptr, buf, length); + png_calculate_crc(png_ptr, buf, length); +} + +/* Optionally skip data and then check the CRC. Depending on whether we + are reading a ancillary or critical chunk, and how the program has set + things up, we may calculate the CRC on the data and print a message. + Returns '1' if there was a CRC error, '0' otherwise. */ +int /* PRIVATE */ +png_crc_finish(png_structp png_ptr, png_uint_32 skip) +{ + png_size_t i; + png_size_t istop = png_ptr->zbuf_size; + + for (i = (png_size_t)skip; i > istop; i -= istop) + { + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + } + if (i) + { + png_crc_read(png_ptr, png_ptr->zbuf, i); + } + + if (png_crc_error(png_ptr)) + { + if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ + !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || + (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ + (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) + { + png_chunk_warning(png_ptr, "CRC error"); + } + else + { + png_chunk_error(png_ptr, "CRC error"); + } + return (1); + } + + return (0); +} + +/* Compare the CRC stored in the PNG file with that calculated by libpng from + the data it has read thus far. */ +int /* PRIVATE */ +png_crc_error(png_structp png_ptr) +{ + png_byte crc_bytes[4]; + png_uint_32 crc; + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + png_read_data(png_ptr, crc_bytes, 4); + + if (need_crc) + { + crc = png_get_uint_32(crc_bytes); + return ((int)(crc != png_ptr->crc)); + } + else + return (0); +} + +#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ + defined(PNG_READ_iCCP_SUPPORTED) +/* + * Decompress trailing data in a chunk. The assumption is that chunkdata + * points at an allocated area holding the contents of a chunk with a + * trailing compressed part. What we get back is an allocated area + * holding the original prefix part and an uncompressed version of the + * trailing part (the malloc area passed in is freed). + */ +png_charp /* PRIVATE */ +png_decompress_chunk(png_structp png_ptr, int comp_type, + png_charp chunkdata, png_size_t chunklength, + png_size_t prefix_size, png_size_t *newlength) +{ + static PNG_CONST char msg[] = "Error decoding compressed text"; + png_charp text; + png_size_t text_size; + + if (comp_type == PNG_COMPRESSION_TYPE_BASE) + { + int ret = Z_OK; + png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size); + png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + text_size = 0; + text = NULL; + + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_warning(png_ptr, png_ptr->zstream.msg); + else + png_warning(png_ptr, msg); + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + if (text == NULL) + { + text_size = prefix_size + png_sizeof(msg) + 1; + text = (png_charp)png_malloc_warn(png_ptr, text_size); + if (text == NULL) + { + png_free(png_ptr,chunkdata); + png_error(png_ptr,"Not enough memory to decompress chunk"); + } + png_memcpy(text, chunkdata, prefix_size); + } + + text[text_size - 1] = 0x00; + + /* Copy what we can of the error message into the text chunk */ + text_size = (png_size_t)(chunklength - (text - chunkdata) - 1); + text_size = png_sizeof(msg) > text_size ? text_size : + png_sizeof(msg); + png_memcpy(text + prefix_size, msg, text_size + 1); + break; + } + if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END) + { + if (text == NULL) + { + text_size = prefix_size + + png_ptr->zbuf_size - png_ptr->zstream.avail_out; + text = (png_charp)png_malloc_warn(png_ptr, text_size + 1); + if (text == NULL) + { + png_free(png_ptr,chunkdata); + png_error(png_ptr,"Not enough memory to decompress chunk."); + } + png_memcpy(text + prefix_size, png_ptr->zbuf, + text_size - prefix_size); + png_memcpy(text, chunkdata, prefix_size); + *(text + text_size) = 0x00; + } + else + { + png_charp tmp; + + tmp = text; + text = (png_charp)png_malloc_warn(png_ptr, + (png_uint_32)(text_size + + png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1)); + if (text == NULL) + { + png_free(png_ptr, tmp); + png_free(png_ptr, chunkdata); + png_error(png_ptr,"Not enough memory to decompress chunk.."); + } + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + png_memcpy(text + text_size, png_ptr->zbuf, + (png_ptr->zbuf_size - png_ptr->zstream.avail_out)); + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = 0x00; + } + if (ret == Z_STREAM_END) + break; + else + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + } + if (ret != Z_STREAM_END) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char umsg[52]; + + if (ret == Z_BUF_ERROR) + png_snprintf(umsg, 52, + "Buffer error in compressed datastream in %s chunk", + png_ptr->chunk_name); + else if (ret == Z_DATA_ERROR) + png_snprintf(umsg, 52, + "Data error in compressed datastream in %s chunk", + png_ptr->chunk_name); + else + png_snprintf(umsg, 52, + "Incomplete compressed datastream in %s chunk", + png_ptr->chunk_name); + png_warning(png_ptr, umsg); +#else + png_warning(png_ptr, + "Incomplete compressed datastream in chunk other than IDAT"); +#endif + text_size=prefix_size; + if (text == NULL) + { + text = (png_charp)png_malloc_warn(png_ptr, text_size+1); + if (text == NULL) + { + png_free(png_ptr, chunkdata); + png_error(png_ptr,"Not enough memory for text."); + } + png_memcpy(text, chunkdata, prefix_size); + } + *(text + text_size) = 0x00; + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + png_free(png_ptr, chunkdata); + chunkdata = text; + *newlength=text_size; + } + else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char umsg[50]; + + png_snprintf(umsg, 50, + "Unknown zTXt compression type %d", comp_type); + png_warning(png_ptr, umsg); +#else + png_warning(png_ptr, "Unknown zTXt compression type"); +#endif + + *(chunkdata + prefix_size) = 0x00; + *newlength=prefix_size; + } + + return chunkdata; +} +#endif + +/* read and check the IDHR chunk */ +void /* PRIVATE */ +png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[13]; + png_uint_32 width, height; + int bit_depth, color_type, compression_type, filter_type; + int interlace_type; + + png_debug(1, "in png_handle_IHDR\n"); + + if (png_ptr->mode & PNG_HAVE_IHDR) + png_error(png_ptr, "Out of place IHDR"); + + /* check the length */ + if (length != 13) + png_error(png_ptr, "Invalid IHDR chunk"); + + png_ptr->mode |= PNG_HAVE_IHDR; + + png_crc_read(png_ptr, buf, 13); + png_crc_finish(png_ptr, 0); + + width = png_get_uint_31(png_ptr, buf); + height = png_get_uint_31(png_ptr, buf + 4); + bit_depth = buf[8]; + color_type = buf[9]; + compression_type = buf[10]; + filter_type = buf[11]; + interlace_type = buf[12]; + +#if defined(PNG_READ_APNG_SUPPORTED) + png_ptr->first_frame_width = width; + png_ptr->first_frame_height = height; +#endif + + /* set internal variables */ + png_ptr->width = width; + png_ptr->height = height; + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->interlaced = (png_byte)interlace_type; + png_ptr->color_type = (png_byte)color_type; +#if defined(PNG_MNG_FEATURES_SUPPORTED) + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + + /* find number of channels */ + switch (png_ptr->color_type) + { + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_PALETTE: + png_ptr->channels = 1; + break; + case PNG_COLOR_TYPE_RGB: + png_ptr->channels = 3; + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_ptr->channels = 2; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + png_ptr->channels = 4; + break; + } + + /* set up other useful info */ + png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * + png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width); + png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth); + png_debug1(3,"channels = %d\n", png_ptr->channels); + png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes); + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, + color_type, interlace_type, compression_type, filter_type); +} + +/* read and check the palette */ +void /* PRIVATE */ +png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_color palette[PNG_MAX_PALETTE_LENGTH]; + int num, i; +#ifndef PNG_NO_POINTER_INDEXING + png_colorp pal_ptr; +#endif + + png_debug(1, "in png_handle_PLTE\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before PLTE"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid PLTE after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + png_error(png_ptr, "Duplicate PLTE chunk"); + + png_ptr->mode |= PNG_HAVE_PLTE; + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring PLTE chunk in grayscale PNG"); + png_crc_finish(png_ptr, length); + return; + } +#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_crc_finish(png_ptr, length); + return; + } +#endif + + if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) + { + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_warning(png_ptr, "Invalid palette chunk"); + png_crc_finish(png_ptr, length); + return; + } + else + { + png_error(png_ptr, "Invalid palette chunk"); + } + } + + num = (int)length / 3; + +#ifndef PNG_NO_POINTER_INDEXING + for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + pal_ptr->red = buf[0]; + pal_ptr->green = buf[1]; + pal_ptr->blue = buf[2]; + } +#else + for (i = 0; i < num; i++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + /* don't depend upon png_color being any order */ + palette[i].red = buf[0]; + palette[i].green = buf[1]; + palette[i].blue = buf[2]; + } +#endif + + /* If we actually NEED the PLTE chunk (ie for a paletted image), we do + whatever the normal CRC configuration tells us. However, if we + have an RGB image, the PLTE can be considered ancillary, so + we will act as though it is. */ +#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#endif + { + png_crc_finish(png_ptr, 0); + } +#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) + else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ + { + /* If we don't want to use the data from an ancillary chunk, + we have two options: an error abort, or a warning and we + ignore the data in this chunk (which should be OK, since + it's considered ancillary for a RGB or RGBA image). */ + if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) + { + if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) + { + png_chunk_error(png_ptr, "CRC error"); + } + else + { + png_chunk_warning(png_ptr, "CRC error"); + return; + } + } + /* Otherwise, we (optionally) emit a warning and use the chunk. */ + else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) + { + png_chunk_warning(png_ptr, "CRC error"); + } + } +#endif + + png_set_PLTE(png_ptr, info_ptr, palette, num); + +#if defined(PNG_READ_tRNS_SUPPORTED) + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + if (png_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); + png_ptr->num_trans = (png_uint_16)num; + } + if (info_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); + info_ptr->num_trans = (png_uint_16)num; + } + } + } +#endif + +} + +void /* PRIVATE */ +png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_debug(1, "in png_handle_IEND\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) + { + png_error(png_ptr, "No image in file"); + } + + png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); + + if (length != 0) + { + png_warning(png_ptr, "Incorrect IEND chunk length"); + } + png_crc_finish(png_ptr, length); + + info_ptr =info_ptr; /* quiet compiler warnings about unused info_ptr */ +} + +#if defined(PNG_READ_gAMA_SUPPORTED) +void /* PRIVATE */ +png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_fixed_point igamma; +#ifdef PNG_FLOATING_POINT_SUPPORTED + float file_gamma; +#endif + png_byte buf[4]; + + png_debug(1, "in png_handle_gAMA\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before gAMA"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid gAMA after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place gAMA chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) +#if defined(PNG_READ_sRGB_SUPPORTED) + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif + ) + { + png_warning(png_ptr, "Duplicate gAMA chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 4) + { + png_warning(png_ptr, "Incorrect gAMA chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 4); + if (png_crc_finish(png_ptr, 0)) + return; + + igamma = (png_fixed_point)png_get_uint_32(buf); + /* check for zero gamma */ + if (igamma == 0) + { + png_warning(png_ptr, + "Ignoring gAMA chunk with gamma=0"); + return; + } + +#if defined(PNG_READ_sRGB_SUPPORTED) + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); +#ifndef PNG_NO_CONSOLE_IO + fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma); +#endif + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + file_gamma = (float)igamma / (float)100000.0; +# ifdef PNG_READ_GAMMA_SUPPORTED + png_ptr->gamma = file_gamma; +# endif + png_set_gAMA(png_ptr, info_ptr, file_gamma); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_gAMA_fixed(png_ptr, info_ptr, igamma); +#endif +} +#endif + +#if defined(PNG_READ_sBIT_SUPPORTED) +void /* PRIVATE */ +png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[4]; + + png_debug(1, "in png_handle_sBIT\n"); + + buf[0] = buf[1] = buf[2] = buf[3] = 0; + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sBIT"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sBIT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + { + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sBIT chunk"); + } + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) + { + png_warning(png_ptr, "Duplicate sBIT chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 3; + else + truelen = (png_size_t)png_ptr->channels; + + if (length != truelen || length > 4) + { + png_warning(png_ptr, "Incorrect sBIT chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + if (png_crc_finish(png_ptr, 0)) + return; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[1]; + png_ptr->sig_bit.blue = buf[2]; + png_ptr->sig_bit.alpha = buf[3]; + } + else + { + png_ptr->sig_bit.gray = buf[0]; + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[0]; + png_ptr->sig_bit.blue = buf[0]; + png_ptr->sig_bit.alpha = buf[1]; + } + png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); +} +#endif + +#if defined(PNG_READ_cHRM_SUPPORTED) +void /* PRIVATE */ +png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[4]; +#ifdef PNG_FLOATING_POINT_SUPPORTED + float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; +#endif + png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, + int_y_green, int_x_blue, int_y_blue; + + png_uint_32 uint_x, uint_y; + + png_debug(1, "in png_handle_cHRM\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before cHRM"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid cHRM after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Missing PLTE before cHRM"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM) +#if defined(PNG_READ_sRGB_SUPPORTED) + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif + ) + { + png_warning(png_ptr, "Duplicate cHRM chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 32) + { + png_warning(png_ptr, "Incorrect cHRM chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 4); + uint_x = png_get_uint_32(buf); + + png_crc_read(png_ptr, buf, 4); + uint_y = png_get_uint_32(buf); + + if (uint_x > 80000L || uint_y > 80000L || + uint_x + uint_y > 100000L) + { + png_warning(png_ptr, "Invalid cHRM white point"); + png_crc_finish(png_ptr, 24); + return; + } + int_x_white = (png_fixed_point)uint_x; + int_y_white = (png_fixed_point)uint_y; + + png_crc_read(png_ptr, buf, 4); + uint_x = png_get_uint_32(buf); + + png_crc_read(png_ptr, buf, 4); + uint_y = png_get_uint_32(buf); + + if (uint_x + uint_y > 100000L) + { + png_warning(png_ptr, "Invalid cHRM red point"); + png_crc_finish(png_ptr, 16); + return; + } + int_x_red = (png_fixed_point)uint_x; + int_y_red = (png_fixed_point)uint_y; + + png_crc_read(png_ptr, buf, 4); + uint_x = png_get_uint_32(buf); + + png_crc_read(png_ptr, buf, 4); + uint_y = png_get_uint_32(buf); + + if (uint_x + uint_y > 100000L) + { + png_warning(png_ptr, "Invalid cHRM green point"); + png_crc_finish(png_ptr, 8); + return; + } + int_x_green = (png_fixed_point)uint_x; + int_y_green = (png_fixed_point)uint_y; + + png_crc_read(png_ptr, buf, 4); + uint_x = png_get_uint_32(buf); + + png_crc_read(png_ptr, buf, 4); + uint_y = png_get_uint_32(buf); + + if (uint_x + uint_y > 100000L) + { + png_warning(png_ptr, "Invalid cHRM blue point"); + png_crc_finish(png_ptr, 0); + return; + } + int_x_blue = (png_fixed_point)uint_x; + int_y_blue = (png_fixed_point)uint_y; + +#ifdef PNG_FLOATING_POINT_SUPPORTED + white_x = (float)int_x_white / (float)100000.0; + white_y = (float)int_y_white / (float)100000.0; + red_x = (float)int_x_red / (float)100000.0; + red_y = (float)int_y_red / (float)100000.0; + green_x = (float)int_x_green / (float)100000.0; + green_y = (float)int_y_green / (float)100000.0; + blue_x = (float)int_x_blue / (float)100000.0; + blue_y = (float)int_y_blue / (float)100000.0; +#endif + +#if defined(PNG_READ_sRGB_SUPPORTED) + if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) + { + if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); +#ifndef PNG_NO_CONSOLE_IO +#ifdef PNG_FLOATING_POINT_SUPPORTED + fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n", + white_x, white_y, red_x, red_y); + fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n", + green_x, green_y, blue_x, blue_y); +#else + fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n", + int_x_white, int_y_white, int_x_red, int_y_red); + fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n", + int_x_green, int_y_green, int_x_blue, int_y_blue); +#endif +#endif /* PNG_NO_CONSOLE_IO */ + } + png_crc_finish(png_ptr, 0); + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_cHRM(png_ptr, info_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_cHRM_fixed(png_ptr, info_ptr, + int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, + int_y_green, int_x_blue, int_y_blue); +#endif + if (png_crc_finish(png_ptr, 0)) + return; +} +#endif + +#if defined(PNG_READ_sRGB_SUPPORTED) +void /* PRIVATE */ +png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + int intent; + png_byte buf[1]; + + png_debug(1, "in png_handle_sRGB\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sRGB"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sRGB after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sRGB chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + { + png_warning(png_ptr, "Duplicate sRGB chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 1) + { + png_warning(png_ptr, "Incorrect sRGB chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 1); + if (png_crc_finish(png_ptr, 0)) + return; + + intent = buf[0]; + /* check for bad intent */ + if (intent >= PNG_sRGB_INTENT_LAST) + { + png_warning(png_ptr, "Unknown sRGB intent"); + return; + } + +#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)) + { + png_fixed_point igamma; +#ifdef PNG_FIXED_POINT_SUPPORTED + igamma=info_ptr->int_gamma; +#else +# ifdef PNG_FLOATING_POINT_SUPPORTED + igamma=(png_fixed_point)(info_ptr->gamma * 100000.); +# endif +#endif + if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); +#ifndef PNG_NO_CONSOLE_IO +# ifdef PNG_FIXED_POINT_SUPPORTED + fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma); +# else +# ifdef PNG_FLOATING_POINT_SUPPORTED + fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma); +# endif +# endif +#endif + } + } +#endif /* PNG_READ_gAMA_SUPPORTED */ + +#ifdef PNG_READ_cHRM_SUPPORTED +#ifdef PNG_FIXED_POINT_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); + } +#endif /* PNG_FIXED_POINT_SUPPORTED */ +#endif /* PNG_READ_cHRM_SUPPORTED */ + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent); +} +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#if defined(PNG_READ_iCCP_SUPPORTED) +void /* PRIVATE */ +png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_charp chunkdata; + png_byte compression_type; + png_bytep pC; + png_charp profile; + png_uint_32 skip = 0; + png_uint_32 profile_size, profile_length; + png_size_t slength, prefix_length, data_length; + + png_debug(1, "in png_handle_iCCP\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iCCP"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid iCCP after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place iCCP chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)) + { + png_warning(png_ptr, "Duplicate iCCP chunk"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "iCCP chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, chunkdata); + return; + } + + chunkdata[slength] = 0x00; + + for (profile = chunkdata; *profile; profile++) + /* empty loop to find end of name */ ; + + ++profile; + + /* there should be at least one zero (the compression type byte) + following the separator, and we should be on it */ + if ( profile >= chunkdata + slength - 1) + { + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "Malformed iCCP chunk"); + return; + } + + /* compression_type should always be zero */ + compression_type = *profile++; + if (compression_type) + { + png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); + compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8 + wrote nonzero) */ + } + + prefix_length = profile - chunkdata; + chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata, + slength, prefix_length, &data_length); + + profile_length = data_length - prefix_length; + + if ( prefix_length > data_length || profile_length < 4) + { + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "Profile size field missing from iCCP chunk"); + return; + } + + /* Check the profile_size recorded in the first 32 bits of the ICC profile */ + pC = (png_bytep)(chunkdata+prefix_length); + profile_size = ((*(pC ))<<24) | + ((*(pC+1))<<16) | + ((*(pC+2))<< 8) | + ((*(pC+3)) ); + + if(profile_size < profile_length) + profile_length = profile_size; + + if(profile_size > profile_length) + { + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "Ignoring truncated iCCP profile."); + return; + } + + png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type, + chunkdata + prefix_length, profile_length); + png_free(png_ptr, chunkdata); +} +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#if defined(PNG_READ_sPLT_SUPPORTED) +void /* PRIVATE */ +png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_bytep chunkdata; + png_bytep entry_start; + png_sPLT_t new_palette; +#ifdef PNG_NO_POINTER_INDEXING + png_sPLT_entryp pp; +#endif + int data_length, entry_size, i; + png_uint_32 skip = 0; + png_size_t slength; + + png_debug(1, "in png_handle_sPLT\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sPLT"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sPLT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "sPLT chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + chunkdata = (png_bytep)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, chunkdata); + return; + } + + chunkdata[slength] = 0x00; + + for (entry_start = chunkdata; *entry_start; entry_start++) + /* empty loop to find end of name */ ; + ++entry_start; + + /* a sample depth should follow the separator, and we should be on it */ + if (entry_start > chunkdata + slength - 2) + { + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "malformed sPLT chunk"); + return; + } + + new_palette.depth = *entry_start++; + entry_size = (new_palette.depth == 8 ? 6 : 10); + data_length = (slength - (entry_start - chunkdata)); + + /* integrity-check the data length */ + if (data_length % entry_size) + { + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "sPLT chunk has bad length"); + return; + } + + new_palette.nentries = (png_int_32) ( data_length / entry_size); + if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX / + png_sizeof(png_sPLT_entry))) + { + png_warning(png_ptr, "sPLT chunk too long"); + return; + } + new_palette.entries = (png_sPLT_entryp)png_malloc_warn( + png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); + if (new_palette.entries == NULL) + { + png_warning(png_ptr, "sPLT chunk requires too much memory"); + return; + } + +#ifndef PNG_NO_POINTER_INDEXING + for (i = 0; i < new_palette.nentries; i++) + { + png_sPLT_entryp pp = new_palette.entries + i; + + if (new_palette.depth == 8) + { + pp->red = *entry_start++; + pp->green = *entry_start++; + pp->blue = *entry_start++; + pp->alpha = *entry_start++; + } + else + { + pp->red = png_get_uint_16(entry_start); entry_start += 2; + pp->green = png_get_uint_16(entry_start); entry_start += 2; + pp->blue = png_get_uint_16(entry_start); entry_start += 2; + pp->alpha = png_get_uint_16(entry_start); entry_start += 2; + } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#else + pp = new_palette.entries; + for (i = 0; i < new_palette.nentries; i++) + { + + if (new_palette.depth == 8) + { + pp[i].red = *entry_start++; + pp[i].green = *entry_start++; + pp[i].blue = *entry_start++; + pp[i].alpha = *entry_start++; + } + else + { + pp[i].red = png_get_uint_16(entry_start); entry_start += 2; + pp[i].green = png_get_uint_16(entry_start); entry_start += 2; + pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; + pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; + } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#endif + + /* discard all chunk data except the name and stash that */ + new_palette.name = (png_charp)chunkdata; + + png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); + + png_free(png_ptr, chunkdata); + png_free(png_ptr, new_palette.entries); +} +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#if defined(PNG_READ_tRNS_SUPPORTED) +void /* PRIVATE */ +png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; + int bit_mask; + + png_debug(1, "in png_handle_tRNS\n"); + + /* For non-indexed color, mask off any bits in the tRNS value that + * exceed the bit depth. Some creators were writing extra bits there. + * This is not needed for indexed color. */ + bit_mask = (1 << png_ptr->bit_depth) - 1; + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tRNS"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid tRNS after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_warning(png_ptr, "Duplicate tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + png_byte buf[2]; + + if (length != 2) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 2); + png_ptr->num_trans = 1; + png_ptr->trans_values.gray = png_get_uint_16(buf) & bit_mask; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_byte buf[6]; + + if (length != 6) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + png_crc_read(png_ptr, buf, (png_size_t)length); + png_ptr->num_trans = 1; + png_ptr->trans_values.red = png_get_uint_16(buf) & bit_mask; + png_ptr->trans_values.green = png_get_uint_16(buf + 2) & bit_mask; + png_ptr->trans_values.blue = png_get_uint_16(buf + 4) & bit_mask; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + /* Should be an error, but we can cope with it. */ + png_warning(png_ptr, "Missing PLTE before tRNS"); + } + if (length > (png_uint_32)png_ptr->num_palette || + length > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + if (length == 0) + { + png_warning(png_ptr, "Zero length tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + png_crc_read(png_ptr, readbuf, (png_size_t)length); + png_ptr->num_trans = (png_uint_16)length; + } + else + { + png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_crc_finish(png_ptr, 0)) + { + png_ptr->num_trans = 0; + return; + } + + png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, + &(png_ptr->trans_values)); +} +#endif + +#if defined(PNG_READ_bKGD_SUPPORTED) +void /* PRIVATE */ +png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[6]; + + png_debug(1, "in png_handle_bKGD\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before bKGD"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid bKGD after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before bKGD"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) + { + png_warning(png_ptr, "Duplicate bKGD chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 1; + else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + truelen = 6; + else + truelen = 2; + + if (length != truelen) + { + png_warning(png_ptr, "Incorrect bKGD chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + if (png_crc_finish(png_ptr, 0)) + return; + + /* We convert the index value into RGB components so that we can allow + * arbitrary RGB values for background when we have transparency, and + * so it is easy to determine the RGB values of the background color + * from the info_ptr struct. */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.index = buf[0]; + if(info_ptr->num_palette) + { + if(buf[0] > info_ptr->num_palette) + { + png_warning(png_ptr, "Incorrect bKGD chunk index value"); + return; + } + png_ptr->background.red = + (png_uint_16)png_ptr->palette[buf[0]].red; + png_ptr->background.green = + (png_uint_16)png_ptr->palette[buf[0]].green; + png_ptr->background.blue = + (png_uint_16)png_ptr->palette[buf[0]].blue; + } + } + else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ + { + png_ptr->background.red = + png_ptr->background.green = + png_ptr->background.blue = + png_ptr->background.gray = png_get_uint_16(buf); + } + else + { + png_ptr->background.red = png_get_uint_16(buf); + png_ptr->background.green = png_get_uint_16(buf + 2); + png_ptr->background.blue = png_get_uint_16(buf + 4); + } + + png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background)); +} +#endif + +#if defined(PNG_READ_hIST_SUPPORTED) +void /* PRIVATE */ +png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + unsigned int num, i; + png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_hIST\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before hIST"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid hIST after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before hIST"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) + { + png_warning(png_ptr, "Duplicate hIST chunk"); + png_crc_finish(png_ptr, length); + return; + } + + num = length / 2 ; + if (num != (unsigned int) png_ptr->num_palette || num > + (unsigned int) PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect hIST chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + for (i = 0; i < num; i++) + { + png_byte buf[2]; + + png_crc_read(png_ptr, buf, 2); + readbuf[i] = png_get_uint_16(buf); + } + + if (png_crc_finish(png_ptr, 0)) + return; + + png_set_hIST(png_ptr, info_ptr, readbuf); +} +#endif + +#if defined(PNG_READ_pHYs_SUPPORTED) +void /* PRIVATE */ +png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_uint_32 res_x, res_y; + int unit_type; + + png_debug(1, "in png_handle_pHYs\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pHYs"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pHYs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_warning(png_ptr, "Duplicate pHYs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect pHYs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + if (png_crc_finish(png_ptr, 0)) + return; + + res_x = png_get_uint_32(buf); + res_y = png_get_uint_32(buf + 4); + unit_type = buf[8]; + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); +} +#endif + +#if defined(PNG_READ_oFFs_SUPPORTED) +void /* PRIVATE */ +png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_int_32 offset_x, offset_y; + int unit_type; + + png_debug(1, "in png_handle_oFFs\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before oFFs"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid oFFs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_warning(png_ptr, "Duplicate oFFs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect oFFs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + if (png_crc_finish(png_ptr, 0)) + return; + + offset_x = png_get_int_32(buf); + offset_y = png_get_int_32(buf + 4); + unit_type = buf[8]; + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); +} +#endif + +#if defined(PNG_READ_pCAL_SUPPORTED) +/* read the pCAL chunk (described in the PNG Extensions document) */ +void /* PRIVATE */ +png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_charp purpose; + png_int_32 X0, X1; + png_byte type, nparams; + png_charp buf, units, endptr; + png_charpp params; + png_size_t slength; + int i; + + png_debug(1, "in png_handle_pCAL\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pCAL"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) + { + png_warning(png_ptr, "Duplicate pCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n", + length + 1); + purpose = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (purpose == NULL) + { + png_warning(png_ptr, "No memory for pCAL purpose."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)purpose, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, purpose); + return; + } + + purpose[slength] = 0x00; /* null terminate the last string */ + + png_debug(3, "Finding end of pCAL purpose string\n"); + for (buf = purpose; *buf; buf++) + /* empty loop */ ; + + endptr = purpose + slength; + + /* We need to have at least 12 bytes after the purpose string + in order to get the parameter information. */ + if (endptr <= buf + 12) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, purpose); + return; + } + + png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n"); + X0 = png_get_int_32((png_bytep)buf+1); + X1 = png_get_int_32((png_bytep)buf+5); + type = buf[9]; + nparams = buf[10]; + units = buf + 11; + + png_debug(3, "Checking pCAL equation type and number of parameters\n"); + /* Check that we have the right number of parameters for known + equation types. */ + if ((type == PNG_EQUATION_LINEAR && nparams != 2) || + (type == PNG_EQUATION_BASE_E && nparams != 3) || + (type == PNG_EQUATION_ARBITRARY && nparams != 3) || + (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) + { + png_warning(png_ptr, "Invalid pCAL parameters for equation type"); + png_free(png_ptr, purpose); + return; + } + else if (type >= PNG_EQUATION_LAST) + { + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + } + + for (buf = units; *buf; buf++) + /* Empty loop to move past the units string. */ ; + + png_debug(3, "Allocating pCAL parameters array\n"); + params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams + *png_sizeof(png_charp))) ; + if (params == NULL) + { + png_free(png_ptr, purpose); + png_warning(png_ptr, "No memory for pCAL params."); + return; + } + + /* Get pointers to the start of each parameter string. */ + for (i = 0; i < (int)nparams; i++) + { + buf++; /* Skip the null string terminator from previous parameter. */ + + png_debug1(3, "Reading pCAL parameter %d\n", i); + for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++) + /* Empty loop to move past each parameter string */ ; + + /* Make sure we haven't run out of data yet */ + if (buf > endptr) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, purpose); + png_free(png_ptr, params); + return; + } + } + + png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams, + units, params); + + png_free(png_ptr, purpose); + png_free(png_ptr, params); +} +#endif + +#if defined(PNG_READ_sCAL_SUPPORTED) +/* read the sCAL chunk */ +void /* PRIVATE */ +png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_charp buffer, ep; +#ifdef PNG_FLOATING_POINT_SUPPORTED + double width, height; + png_charp vp; +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_charp swidth, sheight; +#endif +#endif + png_size_t slength; + + png_debug(1, "in png_handle_sCAL\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sCAL"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) + { + png_warning(png_ptr, "Duplicate sCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n", + length + 1); + buffer = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (buffer == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk"); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)buffer, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, buffer); + return; + } + + buffer[slength] = 0x00; /* null terminate the last string */ + + ep = buffer + 1; /* skip unit byte */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + width = png_strtod(png_ptr, ep, &vp); + if (*vp) + { + png_warning(png_ptr, "malformed width string in sCAL chunk"); + return; + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); + if (swidth == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk width"); + return; + } + png_memcpy(swidth, ep, (png_size_t)png_strlen(ep)); +#endif +#endif + + for (ep = buffer; *ep; ep++) + /* empty loop */ ; + ep++; + +#ifdef PNG_FLOATING_POINT_SUPPORTED + height = png_strtod(png_ptr, ep, &vp); + if (*vp) + { + png_warning(png_ptr, "malformed height string in sCAL chunk"); + return; + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); + if (swidth == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk height"); + return; + } + png_memcpy(sheight, ep, (png_size_t)png_strlen(ep)); +#endif +#endif + + if (buffer + slength < ep +#ifdef PNG_FLOATING_POINT_SUPPORTED + || width <= 0. || height <= 0. +#endif + ) + { + png_warning(png_ptr, "Invalid sCAL data"); + png_free(png_ptr, buffer); +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); + png_free(png_ptr, sheight); +#endif + return; + } + + +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight); +#endif +#endif + + png_free(png_ptr, buffer); +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); + png_free(png_ptr, sheight); +#endif +} +#endif + +#if defined(PNG_READ_tIME_SUPPORTED) +void /* PRIVATE */ +png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[7]; + png_time mod_time; + + png_debug(1, "in png_handle_tIME\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Out of place tIME chunk"); + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) + { + png_warning(png_ptr, "Duplicate tIME chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + if (length != 7) + { + png_warning(png_ptr, "Incorrect tIME chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 7); + if (png_crc_finish(png_ptr, 0)) + return; + + mod_time.second = buf[6]; + mod_time.minute = buf[5]; + mod_time.hour = buf[4]; + mod_time.day = buf[3]; + mod_time.month = buf[2]; + mod_time.year = png_get_uint_16(buf); + + png_set_tIME(png_ptr, info_ptr, &mod_time); +} +#endif + +#if defined(PNG_READ_tEXt_SUPPORTED) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp key; + png_charp text; + png_uint_32 skip = 0; + png_size_t slength; + int ret; + + png_debug(1, "in png_handle_tEXt\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tEXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + key = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (key == NULL) + { + png_warning(png_ptr, "No memory to process text chunk."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)key, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, key); + return; + } + + key[slength] = 0x00; + + for (text = key; *text; text++) + /* empty loop to find end of key */ ; + + if (text != key + slength) + text++; + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)png_sizeof(png_text)); + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process text chunk."); + png_free(png_ptr, key); + return; + } + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; +#endif + text_ptr->text = text; + text_ptr->text_length = png_strlen(text); + + ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + if (ret) + png_warning(png_ptr, "Insufficient memory to process text chunk."); +} +#endif + +#if defined(PNG_READ_zTXt_SUPPORTED) +/* note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp chunkdata; + png_charp text; + int comp_type; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_zTXt\n"); + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before zTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + there is no hard and fast rule to tell us where to stop. */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr,"zTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (chunkdata == NULL) + { + png_warning(png_ptr,"Out of memory processing zTXt chunk."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)chunkdata, slength); + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, chunkdata); + return; + } + + chunkdata[slength] = 0x00; + + for (text = chunkdata; *text; text++) + /* empty loop */ ; + + /* zTXt must have some text after the chunkdataword */ + if (text == chunkdata + slength - 1) + { + png_warning(png_ptr, "Truncated zTXt chunk"); + png_free(png_ptr, chunkdata); + return; + } + else + { + comp_type = *(++text); + if (comp_type != PNG_TEXT_COMPRESSION_zTXt) + { + png_warning(png_ptr, "Unknown compression type in zTXt chunk"); + comp_type = PNG_TEXT_COMPRESSION_zTXt; + } + text++; /* skip the compression_method byte */ + } + prefix_len = text - chunkdata; + + chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata, + (png_size_t)length, prefix_len, &data_len); + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)png_sizeof(png_text)); + if (text_ptr == NULL) + { + png_warning(png_ptr,"Not enough memory to process zTXt chunk."); + png_free(png_ptr, chunkdata); + return; + } + text_ptr->compression = comp_type; + text_ptr->key = chunkdata; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; +#endif + text_ptr->text = chunkdata + prefix_len; + text_ptr->text_length = data_len; + + ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, chunkdata); + if (ret) + png_error(png_ptr, "Insufficient memory to store zTXt chunk."); +} +#endif + +#if defined(PNG_READ_iTXt_SUPPORTED) +/* note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp chunkdata; + png_charp key, lang, text, lang_key; + int comp_flag; + int comp_type = 0; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_iTXt\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + there is no hard and fast rule to tell us where to stop. */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr,"iTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (chunkdata == NULL) + { + png_warning(png_ptr, "No memory to process iTXt chunk."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)chunkdata, slength); + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, chunkdata); + return; + } + + chunkdata[slength] = 0x00; + + for (lang = chunkdata; *lang; lang++) + /* empty loop */ ; + lang++; /* skip NUL separator */ + + /* iTXt must have a language tag (possibly empty), two compression bytes, + translated keyword (possibly empty), and possibly some text after the + keyword */ + + if (lang >= chunkdata + slength - 3) + { + png_warning(png_ptr, "Truncated iTXt chunk"); + png_free(png_ptr, chunkdata); + return; + } + else + { + comp_flag = *lang++; + comp_type = *lang++; + } + + for (lang_key = lang; *lang_key; lang_key++) + /* empty loop */ ; + lang_key++; /* skip NUL separator */ + + for (text = lang_key; *text; text++) + /* empty loop */ ; + text++; /* skip NUL separator */ + if (text >= chunkdata + slength) + { + png_warning(png_ptr, "Malformed iTXt chunk"); + png_free(png_ptr, chunkdata); + return; + } + + prefix_len = text - chunkdata; + + key=chunkdata; + if (comp_flag) + chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata, + (size_t)length, prefix_len, &data_len); + else + data_len=png_strlen(chunkdata + prefix_len); + text_ptr = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)png_sizeof(png_text)); + if (text_ptr == NULL) + { + png_warning(png_ptr,"Not enough memory to process iTXt chunk."); + png_free(png_ptr, chunkdata); + return; + } + text_ptr->compression = (int)comp_flag + 1; + text_ptr->lang_key = chunkdata+(lang_key-key); + text_ptr->lang = chunkdata+(lang-key); + text_ptr->itxt_length = data_len; + text_ptr->text_length = 0; + text_ptr->key = chunkdata; + text_ptr->text = chunkdata + prefix_len; + + ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, chunkdata); + if (ret) + png_error(png_ptr, "Insufficient memory to store iTXt chunk."); +} +#endif + +#if defined(PNG_READ_APNG_SUPPORTED) +void /* PRIVATE */ +png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte data[8]; + png_uint_32 num_frames; + png_uint_32 num_plays; + png_uint_32 didSet; + + png_debug(1, "in png_handle_acTL\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + { + png_error(png_ptr, "Missing IHDR before acTL"); + } + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid acTL after IDAT skipped"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_acTL) + { + png_warning(png_ptr, "Duplicate acTL skipped"); + png_crc_finish(png_ptr, length); + return; + } + else if (length != 8) + { + png_warning(png_ptr, "acTL with invalid length skipped"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, data, 8); + png_crc_finish(png_ptr, 0); + + num_frames = png_get_uint_31(png_ptr, data); + num_plays = png_get_uint_31(png_ptr, data + 4); + + /* the set function will do error checking on num_frames */ + didSet = png_set_acTL(png_ptr, info_ptr, num_frames, num_plays); + if(didSet) + png_ptr->mode |= PNG_HAVE_acTL; +} + +void /* PRIVATE */ +png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte data[22]; + png_uint_32 width; + png_uint_32 height; + png_uint_32 x_offset; + png_uint_32 y_offset; + png_uint_16 delay_num; + png_uint_16 delay_den; + png_byte dispose_op; + png_byte blend_op; + + png_debug(1, "in png_handle_fcTL\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + { + png_error(png_ptr, "Missing IHDR before fcTL"); + } + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + /* for any frames other then the first this message may be misleading, + * but correct. PNG_HAVE_IDAT is unset before the frame head is read + * i can't think of a better message */ + png_warning(png_ptr, "Invalid fcTL after IDAT skipped"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_fcTL) + { + png_warning(png_ptr, "Duplicate fcTL within one frame skipped"); + png_crc_finish(png_ptr, length); + return; + } + else if (length != 26) + { + png_warning(png_ptr, "fcTL with invalid length skipped"); + png_crc_finish(png_ptr, length); + return; + } + + png_ensure_sequence_number(png_ptr, length); + + png_crc_read(png_ptr, data, 22); + png_crc_finish(png_ptr, 0); + + width = png_get_uint_31(png_ptr, data); + height = png_get_uint_31(png_ptr, data + 4); + x_offset = png_get_uint_31(png_ptr, data + 8); + y_offset = png_get_uint_31(png_ptr, data + 12); + delay_num = png_get_uint_16(data + 16); + delay_den = png_get_uint_16(data + 18); + dispose_op = data[20]; + blend_op = data[21]; + + if (png_ptr->num_frames_read == 0 && (x_offset != 0 || y_offset != 0)) + png_error(png_ptr, "fcTL for the first frame must have zero offset"); + if (png_ptr->num_frames_read == 0 && + (width != info_ptr->width || height != info_ptr->height)) + png_error(png_ptr, "size in first frame's fcTL must match " + "the size in IHDR"); + + /* the set function will do more error checking */ + png_set_next_frame_fcTL(png_ptr, info_ptr, width, height, + x_offset, y_offset, delay_num, delay_den, + dispose_op, blend_op); + + png_read_reinit(png_ptr, info_ptr); + + png_ptr->mode |= PNG_HAVE_fcTL; +} + +void /* PRIVATE */ +png_have_info(png_structp png_ptr, png_infop info_ptr) +{ + if((info_ptr->valid & PNG_INFO_acTL) && !(info_ptr->valid & PNG_INFO_fcTL)) + { + png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; + info_ptr->num_frames++; + } +} + +void /* PRIVATE */ +png_handle_fdAT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_ensure_sequence_number(png_ptr, length); + + /* This function is only called from png_read_end(), png_read_info(), + * and png_push_read_chunk() which means that: + * - the user doesn't want to read this frame + * - or this is an out-of-place fdAT + * in either case it is safe to ignore the chunk with a warning */ + png_warning(png_ptr, "ignoring fdAT chunk"); + png_crc_finish(png_ptr, length - 4); +} + +void /* PRIVATE */ +png_ensure_sequence_number(png_structp png_ptr, png_uint_32 length) +{ + png_byte data[4]; + png_uint_32 sequence_number; + + if (length < 4) + png_error(png_ptr, "invalid fcTL or fdAT chunk found"); + + png_crc_read(png_ptr, data, 4); + sequence_number = png_get_uint_31(png_ptr, data); + + if (sequence_number != png_ptr->next_seq_num) + png_error(png_ptr, "fcTL or fdAT chunk with out-of-order sequence " + "number found"); + + png_ptr->next_seq_num++; +} +#endif /* PNG_READ_APNG_SUPPORTED */ + +/* This function is called when we haven't found a handler for a + chunk. If there isn't a problem with the chunk itself (ie bad + chunk name, CRC, or a critical chunk), the chunk is silently ignored + -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which + case it will be saved away to be written out later. */ +void /* PRIVATE */ +png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_uint_32 skip = 0; + + png_debug(1, "in png_handle_unknown\n"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IDAT; +#endif + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */ + png_ptr->mode |= PNG_AFTER_IDAT; + } + + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + } + +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) || + (png_ptr->read_user_chunk_fn != NULL)) + { +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + png_strncpy((png_charp)png_ptr->unknown_chunk.name, + (png_charp)png_ptr->chunk_name, + png_sizeof((png_charp)png_ptr->chunk_name)); + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); + png_ptr->unknown_chunk.size = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + if(png_ptr->read_user_chunk_fn != NULL) + { + /* callback to user unknown chunk handler */ + int ret; + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } +#else + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); +#endif + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + else +#endif + skip = length; + + png_crc_finish(png_ptr, skip); + +#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED) + info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */ +#endif +} + +/* This function is called to verify that a chunk name is valid. + This function can't have the "critical chunk check" incorporated + into it, since in the future we will need to be able to call user + functions to handle unknown critical chunks after we check that + the chunk name itself is valid. */ + +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) + +void /* PRIVATE */ +png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name) +{ + png_debug(1, "in png_check_chunk_name\n"); + if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || + isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) + { + png_chunk_error(png_ptr, "invalid chunk type"); + } +} + +/* Combines the row recently read in with the existing pixels in the + row. This routine takes care of alpha and transparency if requested. + This routine also handles the two methods of progressive display + of interlaced images, depending on the mask value. + The mask value describes which pixels are to be combined with + the row. The pattern always repeats every 8 pixels, so just 8 + bits are needed. A one indicates the pixel is to be combined, + a zero indicates the pixel is to be skipped. This is in addition + to any alpha or transparency value associated with the pixel. If + you want all pixels to be combined, pass 0xff (255) in mask. */ + +void /* PRIVATE */ +png_combine_row(png_structp png_ptr, png_bytep row, int mask) +{ + png_debug(1,"in png_combine_row\n"); + if (mask == 0xff) + { + png_memcpy(row, png_ptr->row_buf + 1, + PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); + } + else + { + switch (png_ptr->row_info.pixel_depth) + { + case 1: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_inc, s_start, s_end; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 7; + s_inc = 1; + } + else +#endif + { + s_start = 7; + s_end = 0; + s_inc = -1; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + int value; + + value = (*sp >> shift) & 0x01; + *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + case 2: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 6; + s_inc = 2; + } + else +#endif + { + s_start = 6; + s_end = 0; + s_inc = -2; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0x03; + *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + case 4: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 4; + s_inc = 4; + } + else +#endif + { + s_start = 4; + s_end = 0; + s_inc = -4; + } + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0xf; + *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + default: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + png_byte m = 0x80; + + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + png_memcpy(dp, sp, pixel_bytes); + } + + sp += pixel_bytes; + dp += pixel_bytes; + + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + } + } +} + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* OLD pre-1.0.9 interface: +void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, + png_uint_32 transformations) + */ +void /* PRIVATE */ +png_do_read_interlace(png_structp png_ptr) +{ + png_row_infop row_info = &(png_ptr->row_info); + png_bytep row = png_ptr->row_buf + 1; + int pass = png_ptr->pass; + png_uint_32 transformations = png_ptr->transformations; +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + /* offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +#endif + + png_debug(1,"in png_do_read_interlace\n"); + if (row != NULL && row_info != NULL) + { + png_uint_32 final_width; + + final_width = row_info->width * png_pass_inc[pass]; + + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_byte v; + png_uint_32 i; + int j; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (int)((row_info->width + 7) & 0x07); + dshift = (int)((final_width + 7) & 0x07); + s_start = 7; + s_end = 0; + s_inc = -1; + } + else +#endif + { + sshift = 7 - (int)((row_info->width + 7) & 0x07); + dshift = 7 - (int)((final_width + 7) & 0x07); + s_start = 0; + s_end = 7; + s_inc = 1; + } + + for (i = 0; i < row_info->width; i++) + { + v = (png_byte)((*sp >> sshift) & 0x01); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + case 2: + { + png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); + png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_uint_32 i; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 3) & 0x03) << 1); + dshift = (int)(((final_width + 3) & 0x03) << 1); + s_start = 6; + s_end = 0; + s_inc = -2; + } + else +#endif + { + sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); + dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); + s_start = 0; + s_end = 6; + s_inc = 2; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v; + int j; + + v = (png_byte)((*sp >> sshift) & 0x03); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + case 4: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + int jstop = png_pass_inc[pass]; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 1) & 0x01) << 2); + dshift = (int)(((final_width + 1) & 0x01) << 2); + s_start = 4; + s_end = 0; + s_inc = -4; + } + else +#endif + { + sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); + dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); + s_start = 0; + s_end = 4; + s_inc = 4; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v = (png_byte)((*sp >> sshift) & 0xf); + int j; + + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + default: + { + png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes; + png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + + int jstop = png_pass_inc[pass]; + png_uint_32 i; + + for (i = 0; i < row_info->width; i++) + { + png_byte v[8]; + int j; + + png_memcpy(v, sp, pixel_bytes); + for (j = 0; j < jstop; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + sp -= pixel_bytes; + } + break; + } + } + row_info->width = final_width; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width); + } +#if !defined(PNG_READ_PACKSWAP_SUPPORTED) + transformations = transformations; /* silence compiler warning */ +#endif +} +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + +void /* PRIVATE */ +png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, + png_bytep prev_row, int filter) +{ + png_debug(1, "in png_read_filter_row\n"); + png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter); + switch (filter) + { + case PNG_FILTER_VALUE_NONE: + break; + case PNG_FILTER_VALUE_SUB: + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + png_bytep lp = row; + + for (i = bpp; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_UP: + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_bytep rp = row; + png_bytep pp = prev_row; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_AVG: + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop = row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) / 2 )) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *lp++) / 2 ) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_PAETH: + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_bytep cp = prev_row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop=row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) /* use leftover rp,pp */ + { + int a, b, c, pa, pb, pc, p; + + a = *lp++; + b = *pp++; + c = *cp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + /* + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; + */ + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *rp = (png_byte)(((int)(*rp) + p) & 0xff); + rp++; + } + break; + } + default: + png_warning(png_ptr, "Ignoring bad adaptive filter type"); + *row=0; + break; + } +} + +void /* PRIVATE */ +png_read_finish_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + png_debug(1, "in png_read_finish_row\n"); + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + png_memset_check(png_ptr, png_ptr->prev_row, 0, + png_ptr->rowbytes + 1); + do + { + png_ptr->pass++; + if (png_ptr->pass >= 7) + break; + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + if (!(png_ptr->num_rows)) + continue; + } + else /* if (png_ptr->transformations & PNG_INTERLACE) */ + break; + } while (png_ptr->iwidth == 0); + + if (png_ptr->pass < 7) + return; + } + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IDAT; +#endif + char extra; + int ret; + + png_ptr->zstream.next_out = (Byte *)&extra; + png_ptr->zstream.avail_out = (uInt)1; + for(;;) + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_byte chunk_length[4]; + + png_crc_finish(png_ptr, 0); + + png_read_data(png_ptr, chunk_length, 4); + png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) + { + if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_warning(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression Error"); + + if (!(png_ptr->zstream.avail_out)) + { + png_warning(png_ptr, "Extra compressed data."); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + + } + png_ptr->zstream.avail_out = 0; + } + + if (png_ptr->idat_size || png_ptr->zstream.avail_in) + png_warning(png_ptr, "Extra compression data"); + + inflateReset(&png_ptr->zstream); + + png_ptr->mode |= PNG_AFTER_IDAT; +} + +void /* PRIVATE */ +png_read_start_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int max_pixel_depth; + png_uint_32 row_bytes; + + png_debug(1, "in png_read_start_row\n"); + png_ptr->zstream.avail_in = 0; + png_init_read_transformations(png_ptr); + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + else + png_ptr->num_rows = png_ptr->height; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1; + + png_ptr->irowbytes = (png_size_t)row_bytes; + if((png_uint_32)png_ptr->irowbytes != row_bytes) + png_error(png_ptr, "Rowbytes overflow in png_read_start_row"); + } + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->iwidth = png_ptr->width; + png_ptr->irowbytes = png_ptr->rowbytes + 1; + } + max_pixel_depth = png_ptr->pixel_depth; + +#if defined(PNG_READ_PACK_SUPPORTED) + if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) + max_pixel_depth = 8; +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans) + max_pixel_depth = 32; + else + max_pixel_depth = 24; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth < 8) + max_pixel_depth = 8; + if (png_ptr->num_trans) + max_pixel_depth *= 2; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (png_ptr->num_trans) + { + max_pixel_depth *= 4; + max_pixel_depth /= 3; + } + } + } +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & (PNG_FILLER)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + max_pixel_depth = 32; + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth <= 8) + max_pixel_depth = 16; + else + max_pixel_depth = 32; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (max_pixel_depth <= 32) + max_pixel_depth = 32; + else + max_pixel_depth = 64; + } + } +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + { + if ( +#if defined(PNG_READ_EXPAND_SUPPORTED) + (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || +#endif +#if defined(PNG_READ_FILLER_SUPPORTED) + (png_ptr->transformations & (PNG_FILLER)) || +#endif + png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (max_pixel_depth <= 16) + max_pixel_depth = 32; + else + max_pixel_depth = 64; + } + else + { + if (max_pixel_depth <= 8) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 32; + else + max_pixel_depth = 24; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 64; + else + max_pixel_depth = 48; + } + } +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ +defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if(png_ptr->transformations & PNG_USER_TRANSFORM) + { + int user_pixel_depth=png_ptr->user_transform_depth* + png_ptr->user_transform_channels; + if(user_pixel_depth > max_pixel_depth) + max_pixel_depth=user_pixel_depth; + } +#endif + + /* align the width on the next larger 8 pixels. Mainly used + for interlacing */ + row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); + /* calculate the maximum bytes needed, adding a byte and a pixel + for safety's sake */ + row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) + + 1 + ((max_pixel_depth + 7) >> 3); +#ifdef PNG_MAX_MALLOC_64K + if (row_bytes > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + if (png_ptr->big_row_buf == NULL) + png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64); + if (png_ptr->row_buf == NULL) + png_ptr->row_buf = png_ptr->big_row_buf+32; + +#ifdef PNG_MAX_MALLOC_64K + if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1)) + png_error(png_ptr, "Row has too many bytes to allocate in memory."); + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)( + png_ptr->rowbytes + 1)); + + png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + png_debug1(3, "width = %lu,\n", png_ptr->width); + png_debug1(3, "height = %lu,\n", png_ptr->height); + png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth); + png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows); + png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes); + png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes); + + png_ptr->flags |= PNG_FLAG_ROW_INIT; +} + +#if defined(PNG_READ_APNG_SUPPORTED) +/* This function is to be called after the main IDAT set has been read and + * before a new IDAT is read. It resets some parts of png_ptr + * to make them usable by the read functions again */ +void /* PRIVATE */ +png_read_reset(png_structp png_ptr) +{ + png_ptr->mode &= ~PNG_HAVE_IDAT; + png_ptr->mode &= ~PNG_AFTER_IDAT; + png_ptr->row_number = 0; + png_ptr->pass = 0; + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + +void /* PRIVATE */ +png_read_reinit(png_structp png_ptr, png_infop info_ptr) +{ + png_ptr->width = info_ptr->next_frame_width; + png_ptr->height = info_ptr->next_frame_height; + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width); +} + +/* same as png_read_reset() but for the progressive reader */ +void /* PRIVATE */ +png_progressive_read_reset(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* start of interlace block */ + const int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + const int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + const int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + const int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; +#endif + png_uint_32 row_bytes; + + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + else + png_ptr->num_rows = png_ptr->height; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1; + + png_ptr->irowbytes = (png_size_t)row_bytes; + if((png_uint_32)png_ptr->irowbytes != row_bytes) + png_error(png_ptr, "png_progressive_read_reset(): Rowbytes " + "overflow"); + } + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->iwidth = png_ptr->width; + png_ptr->irowbytes = png_ptr->rowbytes + 1; + } + + png_ptr->flags &= ~PNG_FLAG_ZLIB_FINISHED; + if (inflateReset(&(png_ptr->zstream)) != Z_OK) + png_error(png_ptr, "inflateReset failed"); + png_ptr->zstream.avail_in = 0; + png_ptr->zstream.next_in = 0; + png_ptr->zstream.next_out = png_ptr->row_buf; + png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; +} +#endif /* PNG_READ_APNG_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pngset.c b/kernel/kls_png/ksquirrel-libs-png/pngset.c new file mode 100644 index 0000000..b16af79 --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngset.c @@ -0,0 +1,1383 @@ + +/* pngset.c - storage of image information into info struct + * + * Last changed in libpng 1.2.17 May 15, 2007 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2007 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * The functions here are used during reads to store data from the file + * into the info struct, and during writes to store application data + * into the info struct for writing into the file. This abstracts the + * info struct and allows us to change the structure in the future. + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +#if defined(PNG_bKGD_SUPPORTED) +void PNGAPI +png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background) +{ + png_debug1(1, "in %s storage function\n", "bKGD"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16)); + info_ptr->valid |= PNG_INFO_bKGD; +} +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_cHRM(png_structp png_ptr, png_infop info_ptr, + double white_x, double white_y, double red_x, double red_y, + double green_x, double green_y, double blue_x, double blue_y) +{ + png_debug1(1, "in %s storage function\n", "cHRM"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (white_x < 0.0 || white_y < 0.0 || + red_x < 0.0 || red_y < 0.0 || + green_x < 0.0 || green_y < 0.0 || + blue_x < 0.0 || blue_y < 0.0) + { + png_warning(png_ptr, + "Ignoring attempt to set negative chromaticity value"); + return; + } + if (white_x > 21474.83 || white_y > 21474.83 || + red_x > 21474.83 || red_y > 21474.83 || + green_x > 21474.83 || green_y > 21474.83 || + blue_x > 21474.83 || blue_y > 21474.83) + { + png_warning(png_ptr, + "Ignoring attempt to set chromaticity value exceeding 21474.83"); + return; + } + + info_ptr->x_white = (float)white_x; + info_ptr->y_white = (float)white_y; + info_ptr->x_red = (float)red_x; + info_ptr->y_red = (float)red_y; + info_ptr->x_green = (float)green_x; + info_ptr->y_green = (float)green_y; + info_ptr->x_blue = (float)blue_x; + info_ptr->y_blue = (float)blue_y; +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5); + info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5); + info_ptr->int_x_red = (png_fixed_point)( red_x*100000.+0.5); + info_ptr->int_y_red = (png_fixed_point)( red_y*100000.+0.5); + info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5); + info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5); + info_ptr->int_x_blue = (png_fixed_point)( blue_x*100000.+0.5); + info_ptr->int_y_blue = (png_fixed_point)( blue_y*100000.+0.5); +#endif + info_ptr->valid |= PNG_INFO_cHRM; +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + png_debug1(1, "in %s storage function\n", "cHRM"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (white_x < 0 || white_y < 0 || + red_x < 0 || red_y < 0 || + green_x < 0 || green_y < 0 || + blue_x < 0 || blue_y < 0) + { + png_warning(png_ptr, + "Ignoring attempt to set negative chromaticity value"); + return; + } +#ifdef PNG_FLOATING_POINT_SUPPORTED + if (white_x > (double) PNG_UINT_31_MAX || + white_y > (double) PNG_UINT_31_MAX || + red_x > (double) PNG_UINT_31_MAX || + red_y > (double) PNG_UINT_31_MAX || + green_x > (double) PNG_UINT_31_MAX || + green_y > (double) PNG_UINT_31_MAX || + blue_x > (double) PNG_UINT_31_MAX || + blue_y > (double) PNG_UINT_31_MAX) +#else + if (white_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || + white_y > (png_fixed_point) PNG_UINT_31_MAX/100000L || + red_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || + red_y > (png_fixed_point) PNG_UINT_31_MAX/100000L || + green_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || + green_y > (png_fixed_point) PNG_UINT_31_MAX/100000L || + blue_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || + blue_y > (png_fixed_point) PNG_UINT_31_MAX/100000L) +#endif + { + png_warning(png_ptr, + "Ignoring attempt to set chromaticity value exceeding 21474.83"); + return; + } + info_ptr->int_x_white = white_x; + info_ptr->int_y_white = white_y; + info_ptr->int_x_red = red_x; + info_ptr->int_y_red = red_y; + info_ptr->int_x_green = green_x; + info_ptr->int_y_green = green_y; + info_ptr->int_x_blue = blue_x; + info_ptr->int_y_blue = blue_y; +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->x_white = (float)(white_x/100000.); + info_ptr->y_white = (float)(white_y/100000.); + info_ptr->x_red = (float)( red_x/100000.); + info_ptr->y_red = (float)( red_y/100000.); + info_ptr->x_green = (float)(green_x/100000.); + info_ptr->y_green = (float)(green_y/100000.); + info_ptr->x_blue = (float)( blue_x/100000.); + info_ptr->y_blue = (float)( blue_y/100000.); +#endif + info_ptr->valid |= PNG_INFO_cHRM; +} +#endif +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) +{ + double gamma; + png_debug1(1, "in %s storage function\n", "gAMA"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Check for overflow */ + if (file_gamma > 21474.83) + { + png_warning(png_ptr, "Limiting gamma to 21474.83"); + gamma=21474.83; + } + else + gamma=file_gamma; + info_ptr->gamma = (float)gamma; +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = (int)(gamma*100000.+.5); +#endif + info_ptr->valid |= PNG_INFO_gAMA; + if(gamma == 0.0) + png_warning(png_ptr, "Setting gamma=0"); +} +#endif +void PNGAPI +png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point + int_gamma) +{ + png_fixed_point gamma; + + png_debug1(1, "in %s storage function\n", "gAMA"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (int_gamma > (png_fixed_point) PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Limiting gamma to 21474.83"); + gamma=PNG_UINT_31_MAX; + } + else + { + if (int_gamma < 0) + { + png_warning(png_ptr, "Setting negative gamma to zero"); + gamma=0; + } + else + gamma=int_gamma; + } +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->gamma = (float)(gamma/100000.); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = gamma; +#endif + info_ptr->valid |= PNG_INFO_gAMA; + if(gamma == 0) + png_warning(png_ptr, "Setting gamma=0"); +} +#endif + +#if defined(PNG_hIST_SUPPORTED) +void PNGAPI +png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist) +{ + int i; + + png_debug1(1, "in %s storage function\n", "hIST"); + if (png_ptr == NULL || info_ptr == NULL) + return; + if (info_ptr->num_palette <= 0 || info_ptr->num_palette + > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, + "Invalid palette size, hIST allocation skipped."); + return; + } + +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); +#endif + /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in version + 1.2.1 */ + png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr, + (png_uint_32)(PNG_MAX_PALETTE_LENGTH * png_sizeof (png_uint_16))); + if (png_ptr->hist == NULL) + { + png_warning(png_ptr, "Insufficient memory for hIST chunk data."); + return; + } + + for (i = 0; i < info_ptr->num_palette; i++) + png_ptr->hist[i] = hist[i]; + info_ptr->hist = png_ptr->hist; + info_ptr->valid |= PNG_INFO_hIST; + +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_HIST; +#else + png_ptr->flags |= PNG_FLAG_FREE_HIST; +#endif +} +#endif + +void PNGAPI +png_set_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + png_debug1(1, "in %s storage function\n", "IHDR"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* check for width and height valid values */ + if (width == 0 || height == 0) + png_error(png_ptr, "Image width or height is zero in IHDR"); +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (width > png_ptr->user_width_max || height > png_ptr->user_height_max) + png_error(png_ptr, "image size exceeds user limits in IHDR"); +#else + if (width > PNG_USER_WIDTH_MAX || height > PNG_USER_HEIGHT_MAX) + png_error(png_ptr, "image size exceeds user limits in IHDR"); +#endif + if (width > PNG_UINT_31_MAX || height > PNG_UINT_31_MAX) + png_error(png_ptr, "Invalid image size in IHDR"); + if ( width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + png_warning(png_ptr, "Width is too large for libpng to process pixels"); + + /* check other values */ + if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && + bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth in IHDR"); + + if (color_type < 0 || color_type == 1 || + color_type == 5 || color_type > 6) + png_error(png_ptr, "Invalid color type in IHDR"); + + if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || + ((color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) + png_error(png_ptr, "Invalid color type/bit depth combination in IHDR"); + + if (interlace_type >= PNG_INTERLACE_LAST) + png_error(png_ptr, "Unknown interlace method in IHDR"); + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + png_error(png_ptr, "Unknown compression method in IHDR"); + +#if defined(PNG_MNG_FEATURES_SUPPORTED) + /* Accept filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not read a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted) + png_warning(png_ptr,"MNG features are not allowed in a PNG datastream"); + if(filter_type != PNG_FILTER_TYPE_BASE) + { + if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA))) + png_error(png_ptr, "Unknown filter method in IHDR"); + if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) + png_warning(png_ptr, "Invalid filter method in IHDR"); + } +#else + if(filter_type != PNG_FILTER_TYPE_BASE) + png_error(png_ptr, "Unknown filter method in IHDR"); +#endif + + info_ptr->width = width; + info_ptr->height = height; + info_ptr->bit_depth = (png_byte)bit_depth; + info_ptr->color_type =(png_byte) color_type; + info_ptr->compression_type = (png_byte)compression_type; + info_ptr->filter_type = (png_byte)filter_type; + info_ptr->interlace_type = (png_byte)interlace_type; + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + else + info_ptr->channels = 1; + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); + + /* check for potential overflow */ + if (width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + info_ptr->rowbytes = (png_size_t)0; + else + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,width); + +#if defined(PNG_APNG_SUPPORTED) + /* for non-animated png. this may be overritten from an acTL chunk later */ + info_ptr->num_frames = 1; +#endif +} + +#if defined(PNG_oFFs_SUPPORTED) +void PNGAPI +png_set_oFFs(png_structp png_ptr, png_infop info_ptr, + png_int_32 offset_x, png_int_32 offset_y, int unit_type) +{ + png_debug1(1, "in %s storage function\n", "oFFs"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_offset = offset_x; + info_ptr->y_offset = offset_y; + info_ptr->offset_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_oFFs; +} +#endif + +#if defined(PNG_pCAL_SUPPORTED) +void PNGAPI +png_set_pCAL(png_structp png_ptr, png_infop info_ptr, + png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, + png_charp units, png_charpp params) +{ + png_uint_32 length; + int i; + + png_debug1(1, "in %s storage function\n", "pCAL"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + length = png_strlen(purpose) + 1; + png_debug1(3, "allocating purpose for info (%lu bytes)\n", length); + info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_purpose == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL purpose."); + return; + } + png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length); + + png_debug(3, "storing X0, X1, type, and nparams in info\n"); + info_ptr->pcal_X0 = X0; + info_ptr->pcal_X1 = X1; + info_ptr->pcal_type = (png_byte)type; + info_ptr->pcal_nparams = (png_byte)nparams; + + length = png_strlen(units) + 1; + png_debug1(3, "allocating units for info (%lu bytes)\n", length); + info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_units == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL units."); + return; + } + png_memcpy(info_ptr->pcal_units, units, (png_size_t)length); + + info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, + (png_uint_32)((nparams + 1) * png_sizeof(png_charp))); + if (info_ptr->pcal_params == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL params."); + return; + } + + info_ptr->pcal_params[nparams] = NULL; + + for (i = 0; i < nparams; i++) + { + length = png_strlen(params[i]) + 1; + png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i, length); + info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_params[i] == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL parameter."); + return; + } + png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length); + } + + info_ptr->valid |= PNG_INFO_pCAL; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_PCAL; +#endif +} +#endif + +#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_sCAL(png_structp png_ptr, png_infop info_ptr, + int unit, double width, double height) +{ + png_debug1(1, "in %s storage function\n", "sCAL"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->scal_unit = (png_byte)unit; + info_ptr->scal_pixel_width = width; + info_ptr->scal_pixel_height = height; + + info_ptr->valid |= PNG_INFO_sCAL; +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int unit, png_charp swidth, png_charp sheight) +{ + png_uint_32 length; + + png_debug1(1, "in %s storage function\n", "sCAL"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->scal_unit = (png_byte)unit; + + length = png_strlen(swidth) + 1; + png_debug1(3, "allocating unit for info (%d bytes)\n", length); + info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->scal_s_width == NULL) + { + png_warning(png_ptr, + "Memory allocation failed while processing sCAL."); + } + png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length); + + length = png_strlen(sheight) + 1; + png_debug1(3, "allocating unit for info (%d bytes)\n", length); + info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->scal_s_height == NULL) + { + png_free (png_ptr, info_ptr->scal_s_width); + png_warning(png_ptr, + "Memory allocation failed while processing sCAL."); + } + png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length); + + info_ptr->valid |= PNG_INFO_sCAL; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_SCAL; +#endif +} +#endif +#endif +#endif + +#if defined(PNG_pHYs_SUPPORTED) +void PNGAPI +png_set_pHYs(png_structp png_ptr, png_infop info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type) +{ + png_debug1(1, "in %s storage function\n", "pHYs"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_pixels_per_unit = res_x; + info_ptr->y_pixels_per_unit = res_y; + info_ptr->phys_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_pHYs; +} +#endif + +void PNGAPI +png_set_PLTE(png_structp png_ptr, png_infop info_ptr, + png_colorp palette, int num_palette) +{ + + png_debug1(1, "in %s storage function\n", "PLTE"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Invalid palette length"); + else + { + png_warning(png_ptr, "Invalid palette length"); + return; + } + } + + /* + * It may not actually be necessary to set png_ptr->palette here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); +#endif + + /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead + of num_palette entries, + in case of an invalid PNG file that has too-large sample values. */ + png_ptr->palette = (png_colorp)png_malloc(png_ptr, + PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color)); + png_memset(png_ptr->palette, 0, PNG_MAX_PALETTE_LENGTH * + png_sizeof(png_color)); + png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof (png_color)); + info_ptr->palette = png_ptr->palette; + info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; + +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_PLTE; +#else + png_ptr->flags |= PNG_FLAG_FREE_PLTE; +#endif + + info_ptr->valid |= PNG_INFO_PLTE; +} + +#if defined(PNG_sBIT_SUPPORTED) +void PNGAPI +png_set_sBIT(png_structp png_ptr, png_infop info_ptr, + png_color_8p sig_bit) +{ + png_debug1(1, "in %s storage function\n", "sBIT"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof (png_color_8)); + info_ptr->valid |= PNG_INFO_sBIT; +} +#endif + +#if defined(PNG_sRGB_SUPPORTED) +void PNGAPI +png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent) +{ + png_debug1(1, "in %s storage function\n", "sRGB"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->srgb_intent = (png_byte)intent; + info_ptr->valid |= PNG_INFO_sRGB; +} + +void PNGAPI +png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, + int intent) +{ +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED + float file_gamma; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_fixed_point int_file_gamma; +#endif +#endif +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED + float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, + int_green_y, int_blue_x, int_blue_y; +#endif +#endif + png_debug1(1, "in %s storage function\n", "sRGB_gAMA_and_cHRM"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_set_sRGB(png_ptr, info_ptr, intent); + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED + file_gamma = (float).45455; + png_set_gAMA(png_ptr, info_ptr, file_gamma); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + int_file_gamma = 45455L; + png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); +#endif +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FIXED_POINT_SUPPORTED + int_white_x = 31270L; + int_white_y = 32900L; + int_red_x = 64000L; + int_red_y = 33000L; + int_green_x = 30000L; + int_green_y = 60000L; + int_blue_x = 15000L; + int_blue_y = 6000L; + + png_set_cHRM_fixed(png_ptr, info_ptr, + int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, int_green_y, + int_blue_x, int_blue_y); +#endif +#ifdef PNG_FLOATING_POINT_SUPPORTED + white_x = (float).3127; + white_y = (float).3290; + red_x = (float).64; + red_y = (float).33; + green_x = (float).30; + green_y = (float).60; + blue_x = (float).15; + blue_y = (float).06; + + png_set_cHRM(png_ptr, info_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); +#endif +#endif +} +#endif + + +#if defined(PNG_iCCP_SUPPORTED) +void PNGAPI +png_set_iCCP(png_structp png_ptr, png_infop info_ptr, + png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen) +{ + png_charp new_iccp_name; + png_charp new_iccp_profile; + + png_debug1(1, "in %s storage function\n", "iCCP"); + if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) + return; + + new_iccp_name = (png_charp)png_malloc_warn(png_ptr, png_strlen(name)+1); + if (new_iccp_name == NULL) + { + png_warning(png_ptr, "Insufficient memory to process iCCP chunk."); + return; + } + png_strncpy(new_iccp_name, name, png_sizeof(new_iccp_name)); + new_iccp_profile = (png_charp)png_malloc_warn(png_ptr, proflen); + if (new_iccp_profile == NULL) + { + png_free (png_ptr, new_iccp_name); + png_warning(png_ptr, "Insufficient memory to process iCCP profile."); + return; + } + png_memcpy(new_iccp_profile, profile, (png_size_t)proflen); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); + + info_ptr->iccp_proflen = proflen; + info_ptr->iccp_name = new_iccp_name; + info_ptr->iccp_profile = new_iccp_profile; + /* Compression is always zero but is here so the API and info structure + * does not have to change if we introduce multiple compression types */ + info_ptr->iccp_compression = (png_byte)compression_type; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_ICCP; +#endif + info_ptr->valid |= PNG_INFO_iCCP; +} +#endif + +#if defined(PNG_TEXT_SUPPORTED) +void PNGAPI +png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, + int num_text) +{ + int ret; + ret=png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); + if (ret) + png_error(png_ptr, "Insufficient memory to store text"); +} + +int /* PRIVATE */ +png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, + int num_text) +{ + int i; + + png_debug1(1, "in %s storage function\n", (png_ptr->chunk_name[0] == '\0' ? + "text" : (png_const_charp)png_ptr->chunk_name)); + + if (png_ptr == NULL || info_ptr == NULL || num_text == 0) + return(0); + + /* Make sure we have enough space in the "text" array in info_struct + * to hold all of the incoming text_ptr objects. + */ + if (info_ptr->num_text + num_text > info_ptr->max_text) + { + if (info_ptr->text != NULL) + { + png_textp old_text; + int old_max; + + old_max = info_ptr->max_text; + info_ptr->max_text = info_ptr->num_text + num_text + 8; + old_text = info_ptr->text; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)(info_ptr->max_text * png_sizeof (png_text))); + if (info_ptr->text == NULL) + { + png_free(png_ptr, old_text); + return(1); + } + png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * + png_sizeof(png_text))); + png_free(png_ptr, old_text); + } + else + { + info_ptr->max_text = num_text + 8; + info_ptr->num_text = 0; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)(info_ptr->max_text * png_sizeof (png_text))); + if (info_ptr->text == NULL) + return(1); +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_TEXT; +#endif + } + png_debug1(3, "allocated %d entries for info_ptr->text\n", + info_ptr->max_text); + } + for (i = 0; i < num_text; i++) + { + png_size_t text_length,key_len; + png_size_t lang_len,lang_key_len; + png_textp textp = &(info_ptr->text[info_ptr->num_text]); + + if (text_ptr[i].key == NULL) + continue; + + key_len = png_strlen(text_ptr[i].key); + + if(text_ptr[i].compression <= 0) + { + lang_len = 0; + lang_key_len = 0; + } + else +#ifdef PNG_iTXt_SUPPORTED + { + /* set iTXt data */ + if (text_ptr[i].lang != NULL) + lang_len = png_strlen(text_ptr[i].lang); + else + lang_len = 0; + if (text_ptr[i].lang_key != NULL) + lang_key_len = png_strlen(text_ptr[i].lang_key); + else + lang_key_len = 0; + } +#else + { + png_warning(png_ptr, "iTXt chunk not supported."); + continue; + } +#endif + + if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') + { + text_length = 0; +#ifdef PNG_iTXt_SUPPORTED + if(text_ptr[i].compression > 0) + textp->compression = PNG_ITXT_COMPRESSION_NONE; + else +#endif + textp->compression = PNG_TEXT_COMPRESSION_NONE; + } + else + { + text_length = png_strlen(text_ptr[i].text); + textp->compression = text_ptr[i].compression; + } + + textp->key = (png_charp)png_malloc_warn(png_ptr, + (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4)); + if (textp->key == NULL) + return(1); + png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n", + (png_uint_32)(key_len + lang_len + lang_key_len + text_length + 4), + (int)textp->key); + + png_memcpy(textp->key, text_ptr[i].key, + (png_size_t)(key_len)); + *(textp->key+key_len) = '\0'; +#ifdef PNG_iTXt_SUPPORTED + if (text_ptr[i].compression > 0) + { + textp->lang=textp->key + key_len + 1; + png_memcpy(textp->lang, text_ptr[i].lang, lang_len); + *(textp->lang+lang_len) = '\0'; + textp->lang_key=textp->lang + lang_len + 1; + png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); + *(textp->lang_key+lang_key_len) = '\0'; + textp->text=textp->lang_key + lang_key_len + 1; + } + else +#endif + { +#ifdef PNG_iTXt_SUPPORTED + textp->lang=NULL; + textp->lang_key=NULL; +#endif + textp->text=textp->key + key_len + 1; + } + if(text_length) + png_memcpy(textp->text, text_ptr[i].text, + (png_size_t)(text_length)); + *(textp->text+text_length) = '\0'; + +#ifdef PNG_iTXt_SUPPORTED + if(textp->compression > 0) + { + textp->text_length = 0; + textp->itxt_length = text_length; + } + else +#endif + { + textp->text_length = text_length; +#ifdef PNG_iTXt_SUPPORTED + textp->itxt_length = 0; +#endif + } + info_ptr->num_text++; + png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text); + } + return(0); +} +#endif + +#if defined(PNG_tIME_SUPPORTED) +void PNGAPI +png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time) +{ + png_debug1(1, "in %s storage function\n", "tIME"); + if (png_ptr == NULL || info_ptr == NULL || + (png_ptr->mode & PNG_WROTE_tIME)) + return; + + png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof (png_time)); + info_ptr->valid |= PNG_INFO_tIME; +} +#endif + +#if defined(PNG_tRNS_SUPPORTED) +void PNGAPI +png_set_tRNS(png_structp png_ptr, png_infop info_ptr, + png_bytep trans, int num_trans, png_color_16p trans_values) +{ + png_debug1(1, "in %s storage function\n", "tRNS"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (trans != NULL) + { + /* + * It may not actually be necessary to set png_ptr->trans here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); +#endif + /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ + png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr, + (png_uint_32)PNG_MAX_PALETTE_LENGTH); + if (num_trans <= PNG_MAX_PALETTE_LENGTH) + png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans); +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_TRNS; +#else + png_ptr->flags |= PNG_FLAG_FREE_TRNS; +#endif + } + + if (trans_values != NULL) + { + png_memcpy(&(info_ptr->trans_values), trans_values, + png_sizeof(png_color_16)); + if (num_trans == 0) + num_trans = 1; + } + info_ptr->num_trans = (png_uint_16)num_trans; + info_ptr->valid |= PNG_INFO_tRNS; +} +#endif + +#if defined(PNG_sPLT_SUPPORTED) +void PNGAPI +png_set_sPLT(png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries) +{ + png_sPLT_tp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL) + return; + + np = (png_sPLT_tp)png_malloc_warn(png_ptr, + (info_ptr->splt_palettes_num + nentries) * png_sizeof(png_sPLT_t)); + if (np == NULL) + { + png_warning(png_ptr, "No memory for sPLT palettes."); + return; + } + + png_memcpy(np, info_ptr->splt_palettes, + info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes=NULL; + + for (i = 0; i < nentries; i++) + { + png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; + png_sPLT_tp from = entries + i; + + to->name = (png_charp)png_malloc_warn(png_ptr, + png_strlen(from->name) + 1); + if (to->name == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + } + /* TODO: use png_malloc_warn */ + png_strncpy(to->name, from->name, png_strlen(from->name)); + to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, + from->nentries * png_sizeof(png_sPLT_entry)); + /* TODO: use png_malloc_warn */ + png_memcpy(to->entries, from->entries, + from->nentries * png_sizeof(png_sPLT_entry)); + if (to->entries == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + png_free(png_ptr,to->name); + to->name = NULL; + } + to->nentries = from->nentries; + to->depth = from->depth; + } + + info_ptr->splt_palettes = np; + info_ptr->splt_palettes_num += nentries; + info_ptr->valid |= PNG_INFO_sPLT; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_SPLT; +#endif +} +#endif /* PNG_sPLT_SUPPORTED */ + +#if defined(PNG_APNG_SUPPORTED) +png_uint_32 PNGAPI +png_set_acTL(png_structp png_ptr, png_infop info_ptr, + png_uint_32 num_frames, png_uint_32 num_plays) +{ + png_debug1(1, "in %s storage function\n", "acTL"); + + if (png_ptr == NULL || info_ptr == NULL) + { + png_warning(png_ptr, + "Call to png_set_acTL() with NULL png_ptr " + "or info_ptr ignored"); + return (0); + } + if (num_frames == 0) + { + png_warning(png_ptr, + "Ignoring attempt to set acTL with num_frames zero"); + return (0); + } + if (num_frames > PNG_UINT_31_MAX) + { + png_warning(png_ptr, + "Ignoring attempt to set acTL with num_frames > 2^31-1"); + return (0); + } + if (num_plays > PNG_UINT_31_MAX) + { + png_warning(png_ptr, + "Ignoring attempt to set acTL with num_plays " + "> 2^31-1"); + return (0); + } + + info_ptr->num_frames = num_frames; + info_ptr->num_plays = num_plays; + + info_ptr->valid |= PNG_INFO_acTL; + + return (1); +} + +/* delay_num and delay_den can hold any values including zero */ +png_uint_32 PNGAPI +png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr, + png_uint_32 width, png_uint_32 height, + png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, + png_byte dispose_op, png_byte blend_op) +{ + png_debug1(1, "in %s storage function\n", "fcTL"); + + if (png_ptr == NULL || info_ptr == NULL) + { + png_warning(png_ptr, + "Call to png_set_fcTL() with NULL png_ptr or info_ptr " + "ignored"); + return (0); + } + + png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, + delay_num, delay_den, dispose_op, blend_op); + + info_ptr->next_frame_width = width; + info_ptr->next_frame_height = height; + info_ptr->next_frame_x_offset = x_offset; + info_ptr->next_frame_y_offset = y_offset; + info_ptr->next_frame_delay_num = delay_num; + info_ptr->next_frame_delay_den = delay_den; + info_ptr->next_frame_dispose_op = dispose_op; + info_ptr->next_frame_blend_op = blend_op; + + info_ptr->valid |= PNG_INFO_fcTL; + + return (1); +} + +void /* PRIVATE */ +png_ensure_fcTL_is_valid(png_structp png_ptr, + png_uint_32 width, png_uint_32 height, + png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, + png_byte dispose_op, png_byte blend_op) +{ + if (width + x_offset > png_ptr->first_frame_width || + height + y_offset > png_ptr->first_frame_height) + png_error(png_ptr, "dimensions of a frame are greater than" + "the ones in IHDR"); + if (width > PNG_UINT_31_MAX) + png_error(png_ptr, "invalid width in fcTL (> 2^31-1)"); + if (height > PNG_UINT_31_MAX) + png_error(png_ptr, "invalid height in fcTL (> 2^31-1)"); + if (x_offset > PNG_UINT_31_MAX) + png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)"); + if (y_offset > PNG_UINT_31_MAX) + png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)"); + + if (dispose_op != PNG_DISPOSE_OP_NONE && + dispose_op != PNG_DISPOSE_OP_BACKGROUND && + dispose_op != PNG_DISPOSE_OP_PREVIOUS) + png_error(png_ptr, "invalid dispose_op in fcTL"); + + if (blend_op != PNG_BLEND_OP_SOURCE && + blend_op != PNG_BLEND_OP_OVER) + png_error(png_ptr, "invalid blend_op in fcTL"); + + if (blend_op == PNG_BLEND_OP_OVER) { + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + png_error(png_ptr, "PNG_BLEND_OP_OVER is not valid for " + "color type 'greyscale without alpha'"); + else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) && + !(png_ptr->color_type & PNG_COLOR_MASK_ALPHA)) + png_error(png_ptr, "PNG_BLEND_OP_OVER is not valid for " + "color type 'truecolor without alpha'"); + } +} + +png_uint_32 PNGAPI +png_set_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr, + png_byte is_hidden) +{ + png_debug(1, "in png_first_frame_is_hidden()\n"); + + if (png_ptr == NULL) + return 0; + + if(is_hidden) + png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; + else + png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN; + + return 1; +} +#endif /* PNG_APNG_SUPPORTED */ + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +void PNGAPI +png_set_unknown_chunks(png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns) +{ + png_unknown_chunkp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) + return; + + np = (png_unknown_chunkp)png_malloc_warn(png_ptr, + (info_ptr->unknown_chunks_num + num_unknowns) * + png_sizeof(png_unknown_chunk)); + if (np == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk."); + return; + } + + png_memcpy(np, info_ptr->unknown_chunks, + info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk)); + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks=NULL; + + for (i = 0; i < num_unknowns; i++) + { + png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; + png_unknown_chunkp from = unknowns + i; + + png_strncpy((png_charp)to->name, (png_charp)from->name, 5); + to->data = (png_bytep)png_malloc_warn(png_ptr, from->size); + if (to->data == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk."); + } + else + { + png_memcpy(to->data, from->data, from->size); + to->size = from->size; + + /* note our location in the read or write sequence */ + to->location = (png_byte)(png_ptr->mode & 0xff); + } + } + + info_ptr->unknown_chunks = np; + info_ptr->unknown_chunks_num += num_unknowns; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_UNKN; +#endif +} +void PNGAPI +png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr, + int chunk, int location) +{ + if(png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk < + (int)info_ptr->unknown_chunks_num) + info_ptr->unknown_chunks[chunk].location = (png_byte)location; +} +#endif + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +void PNGAPI +png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted) +{ + /* This function is deprecated in favor of png_permit_mng_features() + and will be removed from libpng-1.3.0 */ + png_debug(1, "in png_permit_empty_plte, DEPRECATED.\n"); + if (png_ptr == NULL) + return; + png_ptr->mng_features_permitted = (png_byte) + ((png_ptr->mng_features_permitted & (~(PNG_FLAG_MNG_EMPTY_PLTE))) | + ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE))); +} +#endif +#endif + +#if defined(PNG_MNG_FEATURES_SUPPORTED) +png_uint_32 PNGAPI +png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) +{ + png_debug(1, "in png_permit_mng_features\n"); + if (png_ptr == NULL) + return (png_uint_32)0; + png_ptr->mng_features_permitted = + (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); + return (png_uint_32)png_ptr->mng_features_permitted; +} +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +void PNGAPI +png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep + chunk_list, int num_chunks) +{ + png_bytep new_list, p; + int i, old_num_chunks; + if (png_ptr == NULL) + return; + if (num_chunks == 0) + { + if(keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE) + png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + + if(keep == PNG_HANDLE_CHUNK_ALWAYS) + png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; + return; + } + if (chunk_list == NULL) + return; + old_num_chunks=png_ptr->num_chunk_list; + new_list=(png_bytep)png_malloc(png_ptr, + (png_uint_32)(5*(num_chunks+old_num_chunks))); + if(png_ptr->chunk_list != NULL) + { + png_memcpy(new_list, png_ptr->chunk_list, + (png_size_t)(5*old_num_chunks)); + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + } + png_memcpy(new_list+5*old_num_chunks, chunk_list, + (png_size_t)(5*num_chunks)); + for (p=new_list+5*old_num_chunks+4, i=0; inum_chunk_list=old_num_chunks+num_chunks; + png_ptr->chunk_list=new_list; +#ifdef PNG_FREE_ME_SUPPORTED + png_ptr->free_me |= PNG_FREE_LIST; +#endif +} +#endif + +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) +void PNGAPI +png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr, + png_user_chunk_ptr read_user_chunk_fn) +{ + png_debug(1, "in png_set_read_user_chunk_fn\n"); + if (png_ptr == NULL) + return; + png_ptr->read_user_chunk_fn = read_user_chunk_fn; + png_ptr->user_chunk_ptr = user_chunk_ptr; +} +#endif + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +void PNGAPI +png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) +{ + png_debug1(1, "in %s storage function\n", "rows"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if(info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + info_ptr->row_pointers = row_pointers; + if(row_pointers) + info_ptr->valid |= PNG_INFO_IDAT; +} +#endif + +#ifdef PNG_WRITE_SUPPORTED +void PNGAPI +png_set_compression_buffer_size(png_structp png_ptr, png_uint_32 size) +{ + if (png_ptr == NULL) + return; + if(png_ptr->zbuf) + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf_size = (png_size_t)size; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; +} +#endif + +void PNGAPI +png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) +{ + if (png_ptr && info_ptr) + info_ptr->valid &= ~(mask); +} + + +#ifndef PNG_1_0_X +#ifdef PNG_ASSEMBLER_CODE_SUPPORTED +/* function was added to libpng 1.2.0 and should always exist by default */ +void PNGAPI +png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags) +{ +/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */ + if (png_ptr != NULL) + png_ptr->asm_flags = 0; +} + +/* this function was added to libpng 1.2.0 */ +void PNGAPI +png_set_mmx_thresholds (png_structp png_ptr, + png_byte mmx_bitdepth_threshold, + png_uint_32 mmx_rowbytes_threshold) +{ +/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */ + if (png_ptr == NULL) + return; +} +#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* this function was added to libpng 1.2.6 */ +void PNGAPI +png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max, + png_uint_32 user_height_max) +{ + /* Images with dimensions larger than these limits will be + * rejected by png_set_IHDR(). To accept any PNG datastream + * regardless of dimensions, set both limits to 0x7ffffffL. + */ + if(png_ptr == NULL) return; + png_ptr->user_width_max = user_width_max; + png_ptr->user_height_max = user_height_max; +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + +#endif /* ?PNG_1_0_X */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pngtest.c b/kernel/kls_png/ksquirrel-libs-png/pngtest.c new file mode 100644 index 0000000..3981a49 --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngtest.c @@ -0,0 +1,1551 @@ + +/* pngtest.c - a simple test program to test libpng + * + * Last changed in libpng 1.2.6 - August 15, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2004 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This program reads in a PNG image, writes it out again, and then + * compares the two files. If the files are identical, this shows that + * the basic chunk handling, filtering, and (de)compression code is working + * properly. It does not currently test all of the transforms, although + * it probably should. + * + * The program will report "FAIL" in certain legitimate cases: + * 1) when the compression level or filter selection method is changed. + * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192. + * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks + * exist in the input file. + * 4) others not listed here... + * In these cases, it is best to check with another tool such as "pngcheck" + * to see what the differences between the two files are. + * + * If a filename is given on the command-line, then this file is used + * for the input, rather than the default "pngtest.png". This allows + * testing a wide variety of files easily. You can also test a number + * of files at once by typing "pngtest -m file1.png file2.png ..." + */ + +#include "png.h" + +#if defined(_WIN32_WCE) +# if _WIN32_WCE < 211 + __error__ (f|w)printf functions are not supported on old WindowsCE.; +# endif +# include +# include +# define READFILE(file, data, length, check) \ + if (ReadFile(file, data, length, &check,NULL)) check = 0 +# define WRITEFILE(file, data, length, check)) \ + if (WriteFile(file, data, length, &check, NULL)) check = 0 +# define FCLOSE(file) CloseHandle(file) +#else +# include +# include +# define READFILE(file, data, length, check) \ + check=(png_size_t)fread(data,(png_size_t)1,length,file) +# define WRITEFILE(file, data, length, check) \ + check=(png_size_t)fwrite(data,(png_size_t)1, length, file) +# define FCLOSE(file) fclose(file) +#endif + +#if defined(PNG_NO_STDIO) +# if defined(_WIN32_WCE) + typedef HANDLE png_FILE_p; +# else + typedef FILE * png_FILE_p; +# endif +#endif + +/* Makes pngtest verbose so we can find problems (needs to be before png.h) */ +#ifndef PNG_DEBUG +# define PNG_DEBUG 0 +#endif + +#if !PNG_DEBUG +# define SINGLE_ROWBUF_ALLOC /* makes buffer overruns easier to nail */ +#endif + +/* Turn on CPU timing +#define PNGTEST_TIMING +*/ + +#ifdef PNG_NO_FLOATING_POINT_SUPPORTED +#undef PNGTEST_TIMING +#endif + +#ifdef PNGTEST_TIMING +static float t_start, t_stop, t_decode, t_encode, t_misc; +#include +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) +static int tIME_chunk_present=0; +static char tIME_string[30] = "no tIME chunk present in file"; +#endif + +static int verbose = 0; + +int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname)); + +#ifdef __TURBOC__ +#include +#endif + +/* defined so I can write to a file on gui/windowing platforms */ +/* #define STDERR stderr */ +#define STDERR stdout /* for DOS */ + +/* example of using row callbacks to make a simple progress meter */ +static int status_pass=1; +static int status_dots_requested=0; +static int status_dots=1; + +/* In case a system header (e.g., on AIX) defined jmpbuf */ +#ifdef jmpbuf +# undef jmpbuf +#endif + +/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) png_ptr->jmpbuf +#endif + +void +#ifdef PNG_1_0_X +PNGAPI +#endif +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void +#ifdef PNG_1_0_X +PNGAPI +#endif +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if(png_ptr == NULL || row_number > PNG_UINT_31_MAX) return; + if(status_pass != pass) + { + fprintf(stdout,"\n Pass %d: ",pass); + status_pass = pass; + status_dots = 31; + } + status_dots--; + if(status_dots == 0) + { + fprintf(stdout, "\n "); + status_dots=30; + } + fprintf(stdout, "r"); +} + +void +#ifdef PNG_1_0_X +PNGAPI +#endif +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void +#ifdef PNG_1_0_X +PNGAPI +#endif +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if(png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) return; + fprintf(stdout, "w"); +} + + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) +/* Example of using user transform callback (we don't transform anything, + but merely examine the row filters. We set this to 256 rather than + 5 in case illegal filter values are present.) */ +static png_uint_32 filters_used[256]; +void +#ifdef PNG_1_0_X +PNGAPI +#endif +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void +#ifdef PNG_1_0_X +PNGAPI +#endif +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + if(png_ptr != NULL && row_info != NULL) + ++filters_used[*(data-1)]; +} +#endif + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +/* example of using user transform callback (we don't transform anything, + but merely count the zero samples) */ + +static png_uint_32 zero_samples; + +void +#ifdef PNG_1_0_X +PNGAPI +#endif +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void +#ifdef PNG_1_0_X +PNGAPI +#endif +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + png_bytep dp = data; + if(png_ptr == NULL)return; + + /* contents of row_info: + * png_uint_32 width width of row + * png_uint_32 rowbytes number of bytes in row + * png_byte color_type color type of pixels + * png_byte bit_depth bit depth of samples + * png_byte channels number of channels (1-4) + * png_byte pixel_depth bits per pixel (depth*channels) + */ + + + /* counts the number of zero samples (or zero pixels if color_type is 3 */ + + if(row_info->color_type == 0 || row_info->color_type == 3) + { + int pos=0; + png_uint_32 n, nstop; + for (n=0, nstop=row_info->width; nbit_depth == 1) + { + if(((*dp << pos++ ) & 0x80) == 0) zero_samples++; + if(pos == 8) + { + pos = 0; + dp++; + } + } + if(row_info->bit_depth == 2) + { + if(((*dp << (pos+=2)) & 0xc0) == 0) zero_samples++; + if(pos == 8) + { + pos = 0; + dp++; + } + } + if(row_info->bit_depth == 4) + { + if(((*dp << (pos+=4)) & 0xf0) == 0) zero_samples++; + if(pos == 8) + { + pos = 0; + dp++; + } + } + if(row_info->bit_depth == 8) + if(*dp++ == 0) zero_samples++; + if(row_info->bit_depth == 16) + { + if((*dp | *(dp+1)) == 0) zero_samples++; + dp+=2; + } + } + } + else /* other color types */ + { + png_uint_32 n, nstop; + int channel; + int color_channels = row_info->channels; + if(row_info->color_type > 3)color_channels--; + + for (n=0, nstop=row_info->width; nbit_depth == 8) + if(*dp++ == 0) zero_samples++; + if(row_info->bit_depth == 16) + { + if((*dp | *(dp+1)) == 0) zero_samples++; + dp+=2; + } + } + if(row_info->color_type > 3) + { + dp++; + if(row_info->bit_depth == 16)dp++; + } + } + } +} +#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */ + +static int wrote_question = 0; + +#if defined(PNG_NO_STDIO) +/* START of code to validate stdio-free compilation */ +/* These copies of the default read/write functions come from pngrio.c and */ +/* pngwio.c. They allow "don't include stdio" testing of the library. */ +/* This is the function that does the actual reading of data. If you are + not reading from a standard C stream, you should create a replacement + read_data function and use it at run time with png_set_read_fn(), rather + than changing the library. */ + +#ifndef USE_FAR_KEYWORD +static void +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + READFILE((png_FILE_p)png_ptr->io_ptr, data, length, check); + + if (check != length) + { + png_error(png_ptr, "Read Error!"); + } +} +#else +/* this is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + int check; + png_byte *n_data; + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)n_data == data) + { + READFILE(io_ptr, n_data, length, check); + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + do + { + read = MIN(NEAR_BUF_SIZE, remaining); + READFILE(io_ptr, buf, 1, err); + png_memcpy(data, buf, read); /* copy far buffer to near buffer */ + if(err != read) + break; + else + check += err; + data += read; + remaining -= read; + } + while (remaining != 0); + } + if (check != length) + { + png_error(png_ptr, "read Error"); + } +} +#endif /* USE_FAR_KEYWORD */ + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +static void +pngtest_flush(png_structp png_ptr) +{ +#if !defined(_WIN32_WCE) + png_FILE_p io_ptr; + io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); + if (io_ptr != NULL) + fflush(io_ptr); +#endif +} +#endif + +/* This is the function that does the actual writing of data. If you are + not writing to a standard C stream, you should create a replacement + write_data function and use it at run time with png_set_write_fn(), rather + than changing the library. */ +#ifndef USE_FAR_KEYWORD +static void +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + + WRITEFILE((png_FILE_p)png_ptr->io_ptr, data, length, check); + if (check != length) + { + png_error(png_ptr, "Write Error"); + } +} +#else +/* this is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)near_data == data) + { + WRITEFILE(io_ptr, near_data, length, check); + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* copy far buffer to near buffer */ + WRITEFILE(io_ptr, buf, written, err); + if (err != written) + break; + else + check += err; + data += written; + remaining -= written; + } + while (remaining != 0); + } + if (check != length) + { + png_error(png_ptr, "Write Error"); + } +} +#endif /* USE_FAR_KEYWORD */ +#endif /* PNG_NO_STDIO */ +/* END of code to validate stdio-free compilation */ + +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void +pngtest_warning(png_structp png_ptr, png_const_charp message) +{ + PNG_CONST char *name = "UNKNOWN (ERROR!)"; + if (png_ptr != NULL && png_ptr->error_ptr != NULL) + name = png_ptr->error_ptr; + fprintf(STDERR, "%s: libpng warning: %s\n", name, message); +} + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void +pngtest_error(png_structp png_ptr, png_const_charp message) +{ + pngtest_warning(png_ptr, message); + /* We can return because png_error calls the default handler, which is + * actually OK in this case. */ +} + +/* START of code to validate memory allocation and deallocation */ +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + +/* Allocate memory. For reasonable files, size should never exceed + 64K. However, zlib may allocate more then 64K if you don't tell + it not to. See zconf.h and png.h for more information. zlib does + need to allocate exactly 64K, so whatever you call here must + have the ability to do that. + + This piece of code can be compiled to validate max 64K allocations + by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. */ +typedef struct memory_information +{ + png_uint_32 size; + png_voidp pointer; + struct memory_information FAR *next; +} memory_information; +typedef memory_information FAR *memory_infop; + +static memory_infop pinformation = NULL; +static int current_allocation = 0; +static int maximum_allocation = 0; +static int total_allocation = 0; +static int num_allocations = 0; + +png_voidp png_debug_malloc PNGARG((png_structp png_ptr, png_uint_32 size)); +void png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); + +png_voidp +png_debug_malloc(png_structp png_ptr, png_uint_32 size) +{ + + /* png_malloc has already tested for NULL; png_create_struct calls + png_debug_malloc directly, with png_ptr == NULL which is OK */ + + if (size == 0) + return (NULL); + + /* This calls the library allocator twice, once to get the requested + buffer and once to get a new free list entry. */ + { + /* Disable malloc_fn and free_fn */ + memory_infop pinfo; + png_set_mem_fn(png_ptr, NULL, NULL, NULL); + pinfo = (memory_infop)png_malloc(png_ptr, + (png_uint_32)png_sizeof (*pinfo)); + pinfo->size = size; + current_allocation += size; + total_allocation += size; + num_allocations ++; + if (current_allocation > maximum_allocation) + maximum_allocation = current_allocation; + pinfo->pointer = (png_voidp)png_malloc(png_ptr, size); + /* Restore malloc_fn and free_fn */ + png_set_mem_fn(png_ptr, png_voidp_NULL, (png_malloc_ptr)png_debug_malloc, + (png_free_ptr)png_debug_free); + if (size != 0 && pinfo->pointer == NULL) + { + current_allocation -= size; + total_allocation -= size; + png_error(png_ptr, + "out of memory in pngtest->png_debug_malloc."); + } + pinfo->next = pinformation; + pinformation = pinfo; + /* Make sure the caller isn't assuming zeroed memory. */ + png_memset(pinfo->pointer, 0xdd, pinfo->size); + if(verbose) + printf("png_malloc %lu bytes at %x\n",(unsigned long)size, + pinfo->pointer); + return (png_voidp)(pinfo->pointer); + } +} + +/* Free a pointer. It is removed from the list at the same time. */ +void +png_debug_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL) + fprintf(STDERR, "NULL pointer to png_debug_free.\n"); + if (ptr == 0) + { +#if 0 /* This happens all the time. */ + fprintf(STDERR, "WARNING: freeing NULL pointer\n"); +#endif + return; + } + + /* Unlink the element from the list. */ + { + memory_infop FAR *ppinfo = &pinformation; + for (;;) + { + memory_infop pinfo = *ppinfo; + if (pinfo->pointer == ptr) + { + *ppinfo = pinfo->next; + current_allocation -= pinfo->size; + if (current_allocation < 0) + fprintf(STDERR, "Duplicate free of memory\n"); + /* We must free the list element too, but first kill + the memory that is to be freed. */ + png_memset(ptr, 0x55, pinfo->size); + png_free_default(png_ptr, pinfo); + pinfo=NULL; + break; + } + if (pinfo->next == NULL) + { + fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr); + break; + } + ppinfo = &pinfo->next; + } + } + + /* Finally free the data. */ + if(verbose) + printf("Freeing %x\n",ptr); + png_free_default(png_ptr, ptr); + ptr=NULL; +} +#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */ +/* END of code to test memory allocation/deallocation */ + +/* Test one file */ +int +test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) +{ + static png_FILE_p fpin; + static png_FILE_p fpout; /* "static" prevents setjmp corruption */ + png_structp read_ptr; + png_infop read_info_ptr, end_info_ptr; +#ifdef PNG_WRITE_SUPPORTED + png_structp write_ptr; + png_infop write_info_ptr; + png_infop write_end_info_ptr; +#else + png_structp write_ptr = NULL; + png_infop write_info_ptr = NULL; + png_infop write_end_info_ptr = NULL; +#endif + png_bytep row_buf; + png_uint_32 y; + png_uint_32 width, height; + int num_pass, pass; + int bit_depth, color_type; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + +#if defined(_WIN32_WCE) + TCHAR path[MAX_PATH]; +#endif + char inbuf[256], outbuf[256]; + + row_buf = NULL; + +#if defined(_WIN32_WCE) + MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); + if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) +#else + if ((fpin = fopen(inname, "rb")) == NULL) +#endif + { + fprintf(STDERR, "Could not find input file %s\n", inname); + return (1); + } + +#if defined(_WIN32_WCE) + MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); + if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE) +#else + if ((fpout = fopen(outname, "wb")) == NULL) +#endif + { + fprintf(STDERR, "Could not open output file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + png_debug(0, "Allocating read and write structures\n"); +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, + png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, + (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); +#else + read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, + png_error_ptr_NULL, png_error_ptr_NULL); +#endif + png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, + pngtest_warning); +#ifdef PNG_WRITE_SUPPORTED +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, + png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, + (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); +#else + write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, + png_error_ptr_NULL, png_error_ptr_NULL); +#endif + png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, + pngtest_warning); +#endif + png_debug(0, "Allocating read_info, write_info and end_info structures\n"); + read_info_ptr = png_create_info_struct(read_ptr); + end_info_ptr = png_create_info_struct(read_ptr); +#ifdef PNG_WRITE_SUPPORTED + write_info_ptr = png_create_info_struct(write_ptr); + write_end_info_ptr = png_create_info_struct(write_ptr); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_debug(0, "Setting jmpbuf for read struct\n"); +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(read_ptr))) +#endif + { + fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); + if (row_buf) + png_free(read_ptr, row_buf); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(read_ptr),jmpbuf,png_sizeof(jmp_buf)); +#endif + +#ifdef PNG_WRITE_SUPPORTED + png_debug(0, "Setting jmpbuf for write struct\n"); +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(write_ptr))) +#endif + { + fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(write_ptr),jmpbuf,png_sizeof(jmp_buf)); +#endif +#endif +#endif + + png_debug(0, "Initializing input and output streams\n"); +#if !defined(PNG_NO_STDIO) + png_init_io(read_ptr, fpin); +# ifdef PNG_WRITE_SUPPORTED + png_init_io(write_ptr, fpout); +# endif +#else + png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); +# ifdef PNG_WRITE_SUPPORTED + png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, +# if defined(PNG_WRITE_FLUSH_SUPPORTED) + pngtest_flush); +# else + NULL); +# endif +# endif +#endif + if(status_dots_requested == 1) + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, write_row_callback); +#endif + png_set_read_status_fn(read_ptr, read_row_callback); + } + else + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, png_write_status_ptr_NULL); +#endif + png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL); + } + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + { + int i; + for(i=0; i<256; i++) + filters_used[i]=0; + png_set_read_user_transform_fn(read_ptr, count_filters); + } +#endif +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + zero_samples=0; + png_set_write_user_transform_fn(write_ptr, count_zero_samples); +#endif + +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) +# ifndef PNG_HANDLE_CHUNK_ALWAYS +# define PNG_HANDLE_CHUNK_ALWAYS 3 +# endif + png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, + png_bytep_NULL, 0); +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) +# ifndef PNG_HANDLE_CHUNK_IF_SAFE +# define PNG_HANDLE_CHUNK_IF_SAFE 2 +# endif + png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE, + png_bytep_NULL, 0); +#endif + + png_debug(0, "Reading info struct\n"); + png_read_info(read_ptr, read_info_ptr); + + png_debug(0, "Transferring info struct\n"); + { + int interlace_type, compression_type, filter_type; + + if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, + &color_type, &interlace_type, &compression_type, &filter_type)) + { + png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + color_type, interlace_type, compression_type, filter_type); +#else + color_type, PNG_INTERLACE_NONE, compression_type, filter_type); +#endif + } + } +#if defined(PNG_FIXED_POINT_SUPPORTED) +#if defined(PNG_cHRM_SUPPORTED) + { + png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, + &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#if defined(PNG_gAMA_SUPPORTED) + { + png_fixed_point gamma; + + if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma)) + { + png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma); + } + } +#endif +#else /* Use floating point versions */ +#if defined(PNG_FLOATING_POINT_SUPPORTED) +#if defined(PNG_cHRM_SUPPORTED) + { + double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, + &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#if defined(PNG_gAMA_SUPPORTED) + { + double gamma; + + if (png_get_gAMA(read_ptr, read_info_ptr, &gamma)) + { + png_set_gAMA(write_ptr, write_info_ptr, gamma); + } + } +#endif +#endif /* floating point */ +#endif /* fixed point */ +#if defined(PNG_iCCP_SUPPORTED) + { + png_charp name; + png_charp profile; + png_uint_32 proflen; + int compression_type; + + if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, + &profile, &proflen)) + { + png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, + profile, proflen); + } + } +#endif +#if defined(PNG_sRGB_SUPPORTED) + { + int intent; + + if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) + { + png_set_sRGB(write_ptr, write_info_ptr, intent); + } + } +#endif + { + png_colorp palette; + int num_palette; + + if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) + { + png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); + } + } +#if defined(PNG_bKGD_SUPPORTED) + { + png_color_16p background; + + if (png_get_bKGD(read_ptr, read_info_ptr, &background)) + { + png_set_bKGD(write_ptr, write_info_ptr, background); + } + } +#endif +#if defined(PNG_hIST_SUPPORTED) + { + png_uint_16p hist; + + if (png_get_hIST(read_ptr, read_info_ptr, &hist)) + { + png_set_hIST(write_ptr, write_info_ptr, hist); + } + } +#endif +#if defined(PNG_oFFs_SUPPORTED) + { + png_int_32 offset_x, offset_y; + int unit_type; + + if (png_get_oFFs(read_ptr, read_info_ptr,&offset_x,&offset_y,&unit_type)) + { + png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type); + } + } +#endif +#if defined(PNG_pCAL_SUPPORTED) + { + png_charp purpose, units; + png_charpp params; + png_int_32 X0, X1; + int type, nparams; + + if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, + &nparams, &units, ¶ms)) + { + png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, + nparams, units, params); + } + } +#endif +#if defined(PNG_pHYs_SUPPORTED) + { + png_uint_32 res_x, res_y; + int unit_type; + + if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type)) + { + png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); + } + } +#endif +#if defined(PNG_sBIT_SUPPORTED) + { + png_color_8p sig_bit; + + if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) + { + png_set_sBIT(write_ptr, write_info_ptr, sig_bit); + } + } +#endif +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED + { + int unit; + double scal_width, scal_height; + + if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); + } + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + { + int unit; + png_charp scal_width, scal_height; + + if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, scal_height); + } + } +#endif +#endif +#endif +#if defined(PNG_TEXT_SUPPORTED) + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0) + { + png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text); + png_set_text(write_ptr, write_info_ptr, text_ptr, num_text); + } + } +#endif +#if defined(PNG_tIME_SUPPORTED) + { + png_timep mod_time; + + if (png_get_tIME(read_ptr, read_info_ptr, &mod_time)) + { + png_set_tIME(write_ptr, write_info_ptr, mod_time); +#if defined(PNG_TIME_RFC1123_SUPPORTED) + /* we have to use png_strncpy instead of "=" because the string + pointed to by png_convert_to_rfc1123() gets free'ed before + we use it */ + png_strncpy(tIME_string,png_convert_to_rfc1123(read_ptr, + mod_time),30); + tIME_chunk_present++; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } +#endif +#if defined(PNG_tRNS_SUPPORTED) + { + png_bytep trans; + int num_trans; + png_color_16p trans_values; + + if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans, + &trans_values)) + { + png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans, + trans_values); + } + } +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + { + png_unknown_chunkp unknowns; + int num_unknowns = (int)png_get_unknown_chunks(read_ptr, read_info_ptr, + &unknowns); + if (num_unknowns) + { + png_size_t i; + png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns, + num_unknowns); + /* copy the locations from the read_info_ptr. The automatically + generated locations in write_info_ptr are wrong because we + haven't written anything yet */ + for (i = 0; i < (png_size_t)num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, + unknowns[i].location); + } + } +#endif + +#ifdef PNG_WRITE_SUPPORTED + png_debug(0, "\nWriting info struct\n"); + +/* If we wanted, we could write info in two steps: + png_write_info_before_PLTE(write_ptr, write_info_ptr); + */ + png_write_info(write_ptr, write_info_ptr); +#endif + +#ifdef SINGLE_ROWBUF_ALLOC + png_debug(0, "\nAllocating row buffer..."); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + png_debug1(0, "0x%08lx\n\n", (unsigned long)row_buf); +#endif /* SINGLE_ROWBUF_ALLOC */ + png_debug(0, "Writing row data\n"); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) + num_pass = png_set_interlace_handling(read_ptr); +# ifdef PNG_WRITE_SUPPORTED + png_set_interlace_handling(write_ptr); +# endif +#else + num_pass=1; +#endif + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; +#endif + for (pass = 0; pass < num_pass; pass++) + { + png_debug1(0, "Writing row data for pass %d\n",pass); + for (y = 0; y < height; y++) + { +#ifndef SINGLE_ROWBUF_ALLOC + png_debug2(0, "\nAllocating row buffer (pass %d, y = %ld)...", pass,y); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + png_debug2(0, "0x%08lx (%ld bytes)\n", (unsigned long)row_buf, + png_get_rowbytes(read_ptr, read_info_ptr)); +#endif /* !SINGLE_ROWBUF_ALLOC */ + png_read_rows(read_ptr, (png_bytepp)&row_buf, png_bytepp_NULL, 1); + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_decode += (t_stop - t_start); + t_start = t_stop; +#endif + png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_encode += (t_stop - t_start); + t_start = t_stop; +#endif +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef SINGLE_ROWBUF_ALLOC + png_debug2(0, "Freeing row buffer (pass %d, y = %ld)\n\n", pass, y); + png_free(read_ptr, row_buf); +#endif /* !SINGLE_ROWBUF_ALLOC */ + } + } + +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1); +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1); +#endif + + png_debug(0, "Reading and writing end_info data\n"); + + png_read_end(read_ptr, end_info_ptr); +#if defined(PNG_TEXT_SUPPORTED) + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0) + { + png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text); + png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text); + } + } +#endif +#if defined(PNG_tIME_SUPPORTED) + { + png_timep mod_time; + + if (png_get_tIME(read_ptr, end_info_ptr, &mod_time)) + { + png_set_tIME(write_ptr, write_end_info_ptr, mod_time); +#if defined(PNG_TIME_RFC1123_SUPPORTED) + /* we have to use png_strncpy instead of "=" because the string + pointed to by png_convert_to_rfc1123() gets free'ed before + we use it */ + png_strncpy(tIME_string,png_convert_to_rfc1123(read_ptr, + mod_time),30); + tIME_chunk_present++; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + { + png_unknown_chunkp unknowns; + int num_unknowns; + num_unknowns = (int)png_get_unknown_chunks(read_ptr, end_info_ptr, + &unknowns); + if (num_unknowns) + { + png_size_t i; + png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns, + num_unknowns); + /* copy the locations from the read_info_ptr. The automatically + generated locations in write_end_info_ptr are wrong because we + haven't written the end_info yet */ + for (i = 0; i < (png_size_t)num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i, + unknowns[i].location); + } + } +#endif +#ifdef PNG_WRITE_SUPPORTED + png_write_end(write_ptr, write_end_info_ptr); +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED + if(verbose) + { + png_uint_32 iwidth, iheight; + iwidth = png_get_image_width(write_ptr, write_info_ptr); + iheight = png_get_image_height(write_ptr, write_info_ptr); + fprintf(STDERR, "Image width = %lu, height = %lu\n", + (unsigned long)iwidth, (unsigned long)iheight); + } +#endif + + png_debug(0, "Destroying data structs\n"); +#ifdef SINGLE_ROWBUF_ALLOC + png_debug(1, "destroying row_buf for read_ptr\n"); + png_free(read_ptr, row_buf); + row_buf=NULL; +#endif /* SINGLE_ROWBUF_ALLOC */ + png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr\n"); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_debug(1, "destroying write_end_info_ptr\n"); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + png_debug(1, "destroying write_ptr, write_info_ptr\n"); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + png_debug(0, "Destruction complete.\n"); + + FCLOSE(fpin); + FCLOSE(fpout); + + png_debug(0, "Opening files for comparison\n"); +#if defined(_WIN32_WCE) + MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); + if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) +#else + if ((fpin = fopen(inname, "rb")) == NULL) +#endif + { + fprintf(STDERR, "Could not find file %s\n", inname); + return (1); + } + +#if defined(_WIN32_WCE) + MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); + if ((fpout = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) +#else + if ((fpout = fopen(outname, "rb")) == NULL) +#endif + { + fprintf(STDERR, "Could not find file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + for(;;) + { + png_size_t num_in, num_out; + + READFILE(fpin, inbuf, 1, num_in); + READFILE(fpout, outbuf, 1, num_out); + + if (num_in != num_out) + { + fprintf(STDERR, "\nFiles %s and %s are of a different size\n", + inname, outname); + if(wrote_question == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname,PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question=1; + } + FCLOSE(fpin); + FCLOSE(fpout); + return (0); + } + + if (!num_in) + break; + + if (png_memcmp(inbuf, outbuf, num_in)) + { + fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); + if(wrote_question == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname,PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question=1; + } + FCLOSE(fpin); + FCLOSE(fpout); + return (0); + } + } + + FCLOSE(fpin); + FCLOSE(fpout); + + return (0); +} + +/* input and output filenames */ +#ifdef RISCOS +static PNG_CONST char *inname = "pngtest/png"; +static PNG_CONST char *outname = "pngout/png"; +#else +static PNG_CONST char *inname = "pngtest.png"; +static PNG_CONST char *outname = "pngout.png"; +#endif + +int +main(int argc, char *argv[]) +{ + int multiple = 0; + int ierror = 0; + + fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION); + fprintf(STDERR,"%s",png_get_copyright(NULL)); + /* Show the version of libpng used in building the library */ + fprintf(STDERR," library (%lu):%s", + (unsigned long)png_access_version_number(), + png_get_header_version(NULL)); + /* Show the version of libpng used in building the application */ + fprintf(STDERR," pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, + PNG_HEADER_VERSION_STRING); + fprintf(STDERR," png_sizeof(png_struct)=%ld, png_sizeof(png_info)=%ld\n", + (long)png_sizeof(png_struct), (long)png_sizeof(png_info)); + + /* Do some consistency checking on the memory allocation settings, I'm + not sure this matters, but it is nice to know, the first of these + tests should be impossible because of the way the macros are set + in pngconf.h */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n"); +#endif + /* I think the following can happen. */ +#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n"); +#endif + + if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) + { + fprintf(STDERR, + "Warning: versions are different between png.h and png.c\n"); + fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver); + ++ierror; + } + + if (argc > 1) + { + if (strcmp(argv[1], "-m") == 0) + { + multiple = 1; + status_dots_requested = 0; + } + else if (strcmp(argv[1], "-mv") == 0 || + strcmp(argv[1], "-vm") == 0 ) + { + multiple = 1; + verbose = 1; + status_dots_requested = 1; + } + else if (strcmp(argv[1], "-v") == 0) + { + verbose = 1; + status_dots_requested = 1; + inname = argv[2]; + } + else + { + inname = argv[1]; + status_dots_requested = 0; + } + } + + if (!multiple && argc == 3+verbose) + outname = argv[2+verbose]; + + if ((!multiple && argc > 3+verbose) || (multiple && argc < 2)) + { + fprintf(STDERR, + "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", + argv[0], argv[0]); + fprintf(STDERR, + " reads/writes one PNG file (without -m) or multiple files (-m)\n"); + fprintf(STDERR, + " with -m %s is used as a temporary file\n", outname); + exit(1); + } + + if (multiple) + { + int i; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + for (i=2; isize, + (unsigned int) pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + else + { + int i; + for (i=0; i<3; ++i) + { + int kerror; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + if (i == 1) status_dots_requested = 1; + else if(verbose == 0)status_dots_requested = 0; + if (i == 0 || verbose == 1 || ierror != 0) + fprintf(STDERR, "Testing %s:",inname); + kerror = test_one_file(inname, outname); + if(kerror == 0) + { + if(verbose == 1 || i == 2) + { +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + int k; +#endif +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + fprintf(STDERR, "\n PASS (%lu zero samples)\n", + (unsigned long)zero_samples); +#else + fprintf(STDERR, " PASS\n"); +#endif +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + for (k=0; k<256; k++) + if(filters_used[k]) + fprintf(STDERR, " Filter %d was used %lu times\n", + k,(unsigned long)filters_used[k]); +#endif +#if defined(PNG_TIME_RFC1123_SUPPORTED) + if(tIME_chunk_present != 0) + fprintf(STDERR, " tIME = %s\n",tIME_string); +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } + else + { + if(verbose == 0 && i != 2) + fprintf(STDERR, "Testing %s:",inname); + fprintf(STDERR, " FAIL\n"); + ierror += kerror; + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + if (allocation_now != current_allocation) + fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", + current_allocation-allocation_now); + if (current_allocation != 0) + { + memory_infop pinfo = pinformation; + + fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", + current_allocation); + while (pinfo != NULL) + { + fprintf(STDERR," %lu bytes at %x\n", + (unsigned long)pinfo->size, (unsigned int)pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; + fprintf(STDERR," CPU time used = %.3f seconds", + (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); + fprintf(STDERR," (decoding %.3f,\n", + t_decode/(float)CLOCKS_PER_SEC); + fprintf(STDERR," encoding %.3f ,", + t_encode/(float)CLOCKS_PER_SEC); + fprintf(STDERR," other %.3f seconds)\n\n", + t_misc/(float)CLOCKS_PER_SEC); +#endif + + if (ierror == 0) + fprintf(STDERR, "libpng passes test\n"); + else + fprintf(STDERR, "libpng FAILS test\n"); + return (int)(ierror != 0); +} + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef version_1_2_20 your_png_h_is_not_version_1_2_20; diff --git a/kernel/kls_png/ksquirrel-libs-png/pngtrans.c b/kernel/kls_png/ksquirrel-libs-png/pngtrans.c new file mode 100644 index 0000000..1640095 --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngtrans.c @@ -0,0 +1,662 @@ + +/* pngtrans.c - transforms the data in a row (used by both readers and writers) + * + * Last changed in libpng 1.2.17 May 15, 2007 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2007 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* turn on BGR-to-RGB mapping */ +void PNGAPI +png_set_bgr(png_structp png_ptr) +{ + png_debug(1, "in png_set_bgr\n"); + if(png_ptr == NULL) return; + png_ptr->transformations |= PNG_BGR; +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* turn on 16 bit byte swapping */ +void PNGAPI +png_set_swap(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap\n"); + if(png_ptr == NULL) return; + if (png_ptr->bit_depth == 16) + png_ptr->transformations |= PNG_SWAP_BYTES; +} +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* turn on pixel packing */ +void PNGAPI +png_set_packing(png_structp png_ptr) +{ + png_debug(1, "in png_set_packing\n"); + if(png_ptr == NULL) return; + if (png_ptr->bit_depth < 8) + { + png_ptr->transformations |= PNG_PACK; + png_ptr->usr_bit_depth = 8; + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* turn on packed pixel swapping */ +void PNGAPI +png_set_packswap(png_structp png_ptr) +{ + png_debug(1, "in png_set_packswap\n"); + if(png_ptr == NULL) return; + if (png_ptr->bit_depth < 8) + png_ptr->transformations |= PNG_PACKSWAP; +} +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +void PNGAPI +png_set_shift(png_structp png_ptr, png_color_8p true_bits) +{ + png_debug(1, "in png_set_shift\n"); + if(png_ptr == NULL) return; + png_ptr->transformations |= PNG_SHIFT; + png_ptr->shift = *true_bits; +} +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +int PNGAPI +png_set_interlace_handling(png_structp png_ptr) +{ + png_debug(1, "in png_set_interlace handling\n"); + if (png_ptr && png_ptr->interlaced) + { + png_ptr->transformations |= PNG_INTERLACE; + return (7); + } + + return (1); +} +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte on read, or remove a filler or alpha byte on write. + * The filler type has changed in v0.95 to allow future 2-byte fillers + * for 48-bit input data, as well as to avoid problems with some compilers + * that don't like bytes as parameters. + */ +void PNGAPI +png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_filler\n"); + if(png_ptr == NULL) return; + png_ptr->transformations |= PNG_FILLER; + png_ptr->filler = (png_byte)filler; + if (filler_loc == PNG_FILLER_AFTER) + png_ptr->flags |= PNG_FLAG_FILLER_AFTER; + else + png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; + + /* This should probably go in the "do_read_filler" routine. + * I attempted to do that in libpng-1.0.1a but that caused problems + * so I restored it in libpng-1.0.2a + */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_ptr->usr_channels = 4; + } + + /* Also I added this in libpng-1.0.2a (what happens when we expand + * a less-than-8-bit grayscale to GA? */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8) + { + png_ptr->usr_channels = 2; + } +} + +#if !defined(PNG_1_0_X) +/* Added to libpng-1.2.7 */ +void PNGAPI +png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_add_alpha\n"); + if(png_ptr == NULL) return; + png_set_filler(png_ptr, filler, filler_loc); + png_ptr->transformations |= PNG_ADD_ALPHA; +} +#endif + +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +void PNGAPI +png_set_swap_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap_alpha\n"); + if(png_ptr == NULL) return; + png_ptr->transformations |= PNG_SWAP_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +void PNGAPI +png_set_invert_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_alpha\n"); + if(png_ptr == NULL) return; + png_ptr->transformations |= PNG_INVERT_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +void PNGAPI +png_set_invert_mono(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_mono\n"); + if(png_ptr == NULL) return; + png_ptr->transformations |= PNG_INVERT_MONO; +} + +/* invert monochrome grayscale data */ +void /* PRIVATE */ +png_do_invert(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_invert\n"); + /* This test removed from libpng version 1.0.13 and 1.2.0: + * if (row_info->bit_depth == 1 && + */ +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row == NULL || row_info == NULL) + return; +#endif + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(~(*rp)); + rp++; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 8) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i+=2) + { + *rp = (png_byte)(~(*rp)); + rp+=2; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i+=4) + { + *rp = (png_byte)(~(*rp)); + *(rp+1) = (png_byte)(~(*(rp+1))); + rp+=4; + } + } +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* swaps byte order on 16 bit depth images */ +void /* PRIVATE */ +png_do_swap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_swap\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop= row_info->width * row_info->channels; + + for (i = 0; i < istop; i++, rp += 2) + { + png_byte t = *rp; + *rp = *(rp + 1); + *(rp + 1) = t; + } + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +static PNG_CONST png_byte onebppswaptable[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; + +static PNG_CONST png_byte twobppswaptable[256] = { + 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, + 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, + 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, + 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4, + 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8, + 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8, + 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC, + 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC, + 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1, + 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1, + 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5, + 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5, + 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9, + 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9, + 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD, + 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD, + 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2, + 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2, + 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6, + 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6, + 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA, + 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA, + 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE, + 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE, + 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3, + 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3, + 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7, + 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7, + 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB, + 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB, + 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF, + 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF +}; + +static PNG_CONST png_byte fourbppswaptable[256] = { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, + 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, + 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, + 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, + 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, + 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, + 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, + 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, + 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, + 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, + 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, + 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, + 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, + 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, + 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, + 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, + 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, + 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, + 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, + 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, + 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, + 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, + 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, + 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, + 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, + 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, + 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, + 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, + 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, + 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, + 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF +}; + +/* swaps pixel packing order within bytes */ +void /* PRIVATE */ +png_do_packswap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_packswap\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->bit_depth < 8) + { + png_bytep rp, end, table; + + end = row + row_info->rowbytes; + + if (row_info->bit_depth == 1) + table = (png_bytep)onebppswaptable; + else if (row_info->bit_depth == 2) + table = (png_bytep)twobppswaptable; + else if (row_info->bit_depth == 4) + table = (png_bytep)fourbppswaptable; + else + return; + + for (rp = row; rp < end; rp++) + *rp = table[*rp]; + } +} +#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */ + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +/* remove filler or alpha byte(s) */ +void /* PRIVATE */ +png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) +{ + png_debug(1, "in png_do_strip_filler\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + png_bytep sp=row; + png_bytep dp=row; + png_uint_32 row_width=row_info->width; + png_uint_32 i; + + if ((row_info->color_type == PNG_COLOR_TYPE_RGB || + (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + (flags & PNG_FLAG_STRIP_ALPHA))) && + row_info->channels == 4) + { + if (row_info->bit_depth == 8) + { + /* This converts from RGBX or RGBA to RGB */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + dp+=3; sp+=4; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp++; + } + } + /* This converts from XRGB or ARGB to RGB */ + else + { + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + } + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */ + sp += 8; dp += 6; + for (i = 1; i < row_width; i++) + { + /* This could be (although png_memcpy is probably slower): + png_memcpy(dp, sp, 6); + sp += 8; + dp += 6; + */ + + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + else + { + /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */ + for (i = 0; i < row_width; i++) + { + /* This could be (although png_memcpy is probably slower): + png_memcpy(dp, sp, 6); + sp += 8; + dp += 6; + */ + + sp+=2; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 48; + row_info->rowbytes = row_width * 6; + } + row_info->channels = 3; + } + else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY || + (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + (flags & PNG_FLAG_STRIP_ALPHA))) && + row_info->channels == 2) + { + if (row_info->bit_depth == 8) + { + /* This converts from GX or GA to G */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + for (i = 0; i < row_width; i++) + { + *dp++ = *sp++; + sp++; + } + } + /* This converts from XG or AG to G */ + else + { + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This converts from GGXX or GGAA to GG */ + sp += 4; dp += 2; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + else + { + /* This converts from XXGG or AAGG to GG */ + for (i = 0; i < row_width; i++) + { + sp += 2; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + row_info->channels = 1; + } + if (flags & PNG_FLAG_STRIP_ALPHA) + row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; + } +} +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* swaps red and blue bytes within a pixel */ +void /* PRIVATE */ +png_do_bgr(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_bgr\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 3) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 4) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + } + else if (row_info->bit_depth == 16) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 6) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 8) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + } + } +} +#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +void PNGAPI +png_set_user_transform_info(png_structp png_ptr, png_voidp + user_transform_ptr, int user_transform_depth, int user_transform_channels) +{ + png_debug(1, "in png_set_user_transform_info\n"); + if(png_ptr == NULL) return; +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + png_ptr->user_transform_ptr = user_transform_ptr; + png_ptr->user_transform_depth = (png_byte)user_transform_depth; + png_ptr->user_transform_channels = (png_byte)user_transform_channels; +#else + if(user_transform_ptr || user_transform_depth || user_transform_channels) + png_warning(png_ptr, + "This version of libpng does not support user transform info"); +#endif +} +#endif + +/* This function returns a pointer to the user_transform_ptr associated with + * the user transform functions. The application should free any memory + * associated with this pointer before png_write_destroy and png_read_destroy + * are called. + */ +png_voidp PNGAPI +png_get_user_transform_ptr(png_structp png_ptr) +{ +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if (png_ptr == NULL) return (NULL); + return ((png_voidp)png_ptr->user_transform_ptr); +#else + return (NULL); +#endif +} +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pngvcrd.c b/kernel/kls_png/ksquirrel-libs-png/pngvcrd.c new file mode 100644 index 0000000..ce4233e --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngvcrd.c @@ -0,0 +1 @@ +/* pnggvrd.c was removed from libpng-1.2.20. */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pngwio.c b/kernel/kls_png/ksquirrel-libs-png/pngwio.c new file mode 100644 index 0000000..371a4fa --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngwio.c @@ -0,0 +1,234 @@ + +/* pngwio.c - functions for data output + * + * Last changed in libpng 1.2.13 November 13, 2006 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2006 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all output. Users who need + * special handling are expected to write functions that have the same + * arguments as these and perform similar functions, but that possibly + * use different output methods. Note that you shouldn't change these + * functions, but rather write replacement functions and then change + * them at run time with png_set_write_fn(...). + */ + +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Write the data to whatever output you are using. The default routine + writes to a file pointer. Note that this routine sometimes gets called + with very small lengths, so you should implement some kind of simple + buffering if you are using unbuffered writes. This should never be asked + to write more than 64K on a 16 bit machine. */ + +void /* PRIVATE */ +png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + if (png_ptr->write_data_fn != NULL ) + (*(png_ptr->write_data_fn))(png_ptr, data, length); + else + png_error(png_ptr, "Call to NULL write function"); +} + +#if !defined(PNG_NO_STDIO) +/* This is the function that does the actual writing of data. If you are + not writing to a standard C stream, you should create a replacement + write_data function and use it at run time with png_set_write_fn(), rather + than changing the library. */ +#ifndef USE_FAR_KEYWORD +void PNGAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + + if(png_ptr == NULL) return; +#if defined(_WIN32_WCE) + if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) + check = 0; +#else + check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); +#endif + if (check != length) + png_error(png_ptr, "Write Error"); +} +#else +/* this is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +void PNGAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + if(png_ptr == NULL) return; + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)near_data == data) + { +#if defined(_WIN32_WCE) + if ( !WriteFile(io_ptr, near_data, length, &check, NULL) ) + check = 0; +#else + check = fwrite(near_data, 1, length, io_ptr); +#endif + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* copy far buffer to near buffer */ +#if defined(_WIN32_WCE) + if ( !WriteFile(io_ptr, buf, written, &err, NULL) ) + err = 0; +#else + err = fwrite(buf, 1, written, io_ptr); +#endif + if (err != written) + break; + else + check += err; + data += written; + remaining -= written; + } + while (remaining != 0); + } + if (check != length) + png_error(png_ptr, "Write Error"); +} + +#endif +#endif + +/* This function is called to output any data pending writing (normally + to disk). After png_flush is called, there should be no data pending + writing in any buffers. */ +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +void /* PRIVATE */ +png_flush(png_structp png_ptr) +{ + if (png_ptr->output_flush_fn != NULL) + (*(png_ptr->output_flush_fn))(png_ptr); +} + +#if !defined(PNG_NO_STDIO) +void PNGAPI +png_default_flush(png_structp png_ptr) +{ +#if !defined(_WIN32_WCE) + png_FILE_p io_ptr; +#endif + if(png_ptr == NULL) return; +#if !defined(_WIN32_WCE) + io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); + if (io_ptr != NULL) + fflush(io_ptr); +#endif +} +#endif +#endif + +/* This function allows the application to supply new output functions for + libpng if standard C streams aren't being used. + + This function takes as its arguments: + png_ptr - pointer to a png output data structure + io_ptr - pointer to user supplied structure containing info about + the output functions. May be NULL. + write_data_fn - pointer to a new output function that takes as its + arguments a pointer to a png_struct, a pointer to + data to be written, and a 32-bit unsigned int that is + the number of bytes to be written. The new write + function should call png_error(png_ptr, "Error msg") + to exit and output any fatal error messages. + flush_data_fn - pointer to a new flush function that takes as its + arguments a pointer to a png_struct. After a call to + the flush function, there should be no data in any buffers + or pending transmission. If the output method doesn't do + any buffering of ouput, a function prototype must still be + supplied although it doesn't have to do anything. If + PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile + time, output_flush_fn will be ignored, although it must be + supplied for compatibility. */ +void PNGAPI +png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) +{ + if(png_ptr == NULL) return; + png_ptr->io_ptr = io_ptr; + +#if !defined(PNG_NO_STDIO) + if (write_data_fn != NULL) + png_ptr->write_data_fn = write_data_fn; + else + png_ptr->write_data_fn = png_default_write_data; +#else + png_ptr->write_data_fn = write_data_fn; +#endif + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +#if !defined(PNG_NO_STDIO) + if (output_flush_fn != NULL) + png_ptr->output_flush_fn = output_flush_fn; + else + png_ptr->output_flush_fn = png_default_flush; +#else + png_ptr->output_flush_fn = output_flush_fn; +#endif +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + + /* It is an error to read while writing a png file */ + if (png_ptr->read_data_fn != NULL) + { + png_ptr->read_data_fn = NULL; + png_warning(png_ptr, + "Attempted to set both read_data_fn and write_data_fn in"); + png_warning(png_ptr, + "the same structure. Resetting read_data_fn to NULL."); + } +} + +#if defined(USE_FAR_KEYWORD) +#if defined(_MSC_VER) +void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + FP_OFF(near_ptr) = FP_OFF(ptr); + far_ptr = (void FAR *)near_ptr; + if(check != 0) + if(FP_SEG(ptr) != FP_SEG(far_ptr)) + png_error(png_ptr,"segment lost in conversion"); + return(near_ptr); +} +# else +void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + near_ptr = (void FAR *)ptr; + far_ptr = (void FAR *)near_ptr; + if(check != 0) + if(far_ptr != ptr) + png_error(png_ptr,"segment lost in conversion"); + return(near_ptr); +} +# endif +# endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pngwrite.c b/kernel/kls_png/ksquirrel-libs-png/pngwrite.c new file mode 100644 index 0000000..61ecb25 --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngwrite.c @@ -0,0 +1,1549 @@ + +/* pngwrite.c - general routines to write a PNG file + * + * Last changed in libpng 1.2.15 January 5, 2007 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2007 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +/* get internal access to png.h */ +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Writes all the PNG information. This is the suggested way to use the + * library. If you have a new chunk to add, make a function to write it, + * and put it in the correct location here. If you want the chunk written + * after the image data, put it in png_write_end(). I strongly encourage + * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing + * the chunk, as that will keep the code from breaking if you want to just + * write a plain PNG file. If you have long comments, I suggest writing + * them in png_write_end(), and compressing them. + */ +void PNGAPI +png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_info_before_PLTE\n"); + if (png_ptr == NULL || info_ptr == NULL) + return; + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + { + png_write_sig(png_ptr); /* write PNG signature */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) + if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted)) + { + png_warning(png_ptr,"MNG features are not allowed in a PNG datastream"); + png_ptr->mng_features_permitted=0; + } +#endif + /* write IHDR information. */ + png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, + info_ptr->filter_type, +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + info_ptr->interlace_type); +#else + 0); +#endif + /* the rest of these check to see if the valid field has the appropriate + flag set, and if it does, writes the chunk. */ +#if defined(PNG_WRITE_gAMA_SUPPORTED) + if (info_ptr->valid & PNG_INFO_gAMA) + { +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_write_gAMA(png_ptr, info_ptr->gamma); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma); +# endif +#endif + } +#endif +#if defined(PNG_WRITE_sRGB_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sRGB) + png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); +#endif +#if defined(PNG_WRITE_iCCP_SUPPORTED) + if (info_ptr->valid & PNG_INFO_iCCP) + png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, + info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); +#endif +#if defined(PNG_WRITE_sBIT_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sBIT) + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); +#endif +#if defined(PNG_WRITE_cHRM_SUPPORTED) + if (info_ptr->valid & PNG_INFO_cHRM) + { +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_write_cHRM(png_ptr, + info_ptr->x_white, info_ptr->y_white, + info_ptr->x_red, info_ptr->y_red, + info_ptr->x_green, info_ptr->y_green, + info_ptr->x_blue, info_ptr->y_blue); +#else +# ifdef PNG_FIXED_POINT_SUPPORTED + png_write_cHRM_fixed(png_ptr, + info_ptr->int_x_white, info_ptr->int_y_white, + info_ptr->int_x_red, info_ptr->int_y_red, + info_ptr->int_x_green, info_ptr->int_y_green, + info_ptr->int_x_blue, info_ptr->int_y_blue); +# endif +#endif + } +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks\n"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep=png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && !(up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; + } +} + +void PNGAPI +png_write_info(png_structp png_ptr, png_infop info_ptr) +{ +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) + int i; +#endif + + png_debug(1, "in png_write_info\n"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_write_info_before_PLTE(png_ptr, info_ptr); + + if (info_ptr->valid & PNG_INFO_PLTE) + png_write_PLTE(png_ptr, info_ptr->palette, + (png_uint_32)info_ptr->num_palette); + else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Valid palette required for paletted images"); + +#if defined(PNG_WRITE_tRNS_SUPPORTED) + if (info_ptr->valid & PNG_INFO_tRNS) + { +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) + /* invert the alpha channel (in tRNS) */ + if ((png_ptr->transformations & PNG_INVERT_ALPHA) && + info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + int j; + for (j=0; j<(int)info_ptr->num_trans; j++) + info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]); + } +#endif + png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values), + info_ptr->num_trans, info_ptr->color_type); + } +#endif +#if defined(PNG_WRITE_bKGD_SUPPORTED) + if (info_ptr->valid & PNG_INFO_bKGD) + png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); +#endif +#if defined(PNG_WRITE_hIST_SUPPORTED) + if (info_ptr->valid & PNG_INFO_hIST) + png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); +#endif +#if defined(PNG_WRITE_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, + info_ptr->offset_unit_type); +#endif +#if defined(PNG_WRITE_pCAL_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pCAL) + png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, + info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, + info_ptr->pcal_units, info_ptr->pcal_params); +#endif +#if defined(PNG_WRITE_sCAL_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sCAL) +#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) + png_write_sCAL(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_pixel_width, info_ptr->scal_pixel_height); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_s_width, info_ptr->scal_s_height); +#else + png_warning(png_ptr, + "png_write_sCAL not supported; sCAL chunk not written."); +#endif +#endif +#endif +#if defined(PNG_WRITE_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, + info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); +#endif +#if defined(PNG_WRITE_tIME_SUPPORTED) + if (info_ptr->valid & PNG_INFO_tIME) + { + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + png_ptr->mode |= PNG_WROTE_tIME; + } +#endif +#if defined(PNG_WRITE_sPLT_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sPLT) + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); +#endif +#if defined(PNG_WRITE_TEXT_SUPPORTED) + /* Check to see if we need to write text chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing header text chunk %d, type %d\n", i, + info_ptr->text[i].compression); + /* an internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#if defined(PNG_WRITE_iTXt_SUPPORTED) + /* write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + /* If we want a compressed text chunk */ + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) + { +#if defined(PNG_WRITE_zTXt_SUPPORTED) + /* write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#if defined(PNG_WRITE_tEXt_SUPPORTED) + /* write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, + 0); +#else + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + } +#endif +#if defined(PNG_WRITE_APNG_SUPPORTED) + if (info_ptr->valid & PNG_INFO_acTL) + png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays); +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks\n"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep=png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif +} + +/* Writes the end of the PNG file. If you don't want to write comments or + * time information, you can pass NULL for info. If you already wrote these + * in png_write_info(), do not write them again here. If you have long + * comments, I suggest writing them here, and compressing them. + */ +void PNGAPI +png_write_end(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_end\n"); + if (png_ptr == NULL) + return; + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "No IDATs written into file"); +#if defined(PNG_WRITE_APNG_SUPPORTED) + if (png_ptr->num_frames_written != png_ptr->num_frames_to_write) + png_error(png_ptr, "Not enough frames written"); +#endif + + /* see if user wants us to write information chunks */ + if (info_ptr != NULL) + { +#if defined(PNG_WRITE_TEXT_SUPPORTED) + int i; /* local index variable */ +#endif +#if defined(PNG_WRITE_tIME_SUPPORTED) + /* check to see if user has supplied a time chunk */ + if ((info_ptr->valid & PNG_INFO_tIME) && + !(png_ptr->mode & PNG_WROTE_tIME)) + png_write_tIME(png_ptr, &(info_ptr->mod_time)); +#endif +#if defined(PNG_WRITE_TEXT_SUPPORTED) + /* loop through comment chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing trailer text chunk %d, type %d\n", i, + info_ptr->text[i].compression); + /* an internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#if defined(PNG_WRITE_iTXt_SUPPORTED) + /* write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) + { +#if defined(PNG_WRITE_zTXt_SUPPORTED) + /* write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#if defined(PNG_WRITE_tEXt_SUPPORTED) + /* write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0); +#else + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + } +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks\n"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep=png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_AFTER_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + } + + png_ptr->mode |= PNG_AFTER_IDAT; + + /* write end of PNG file */ + png_write_IEND(png_ptr); +} + +#if defined(PNG_WRITE_tIME_SUPPORTED) +#if !defined(_WIN32_WCE) +/* "time.h" functions are not supported on WindowsCE */ +void PNGAPI +png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime) +{ + png_debug(1, "in png_convert_from_struct_tm\n"); + ptime->year = (png_uint_16)(1900 + ttime->tm_year); + ptime->month = (png_byte)(ttime->tm_mon + 1); + ptime->day = (png_byte)ttime->tm_mday; + ptime->hour = (png_byte)ttime->tm_hour; + ptime->minute = (png_byte)ttime->tm_min; + ptime->second = (png_byte)ttime->tm_sec; +} + +void PNGAPI +png_convert_from_time_t(png_timep ptime, time_t ttime) +{ + struct tm *tbuf; + + png_debug(1, "in png_convert_from_time_t\n"); + tbuf = gmtime(&ttime); + png_convert_from_struct_tm(ptime, tbuf); +} +#endif +#endif + +/* Initialize png_ptr structure, and allocate any memory needed */ +png_structp PNGAPI +png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); +} + +/* Alternate initialize png_ptr structure, and allocate any memory needed */ +png_structp PNGAPI +png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + png_structp png_ptr; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + int i; + png_debug(1, "in png_create_write_struct\n"); +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif /* PNG_USER_MEM_SUPPORTED */ + if (png_ptr == NULL) + return (NULL); + + /* added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max=PNG_USER_WIDTH_MAX; + png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; +#endif + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_ptr->jmpbuf)) +#endif + { + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf=NULL; + png_destroy_struct(png_ptr); + return (NULL); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); +#endif +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif /* PNG_USER_MEM_SUPPORTED */ + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + i=0; + do + { + if(user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[80]; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "Incompatible libpng version in application and library"); + } + } + + /* initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + + png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, + png_flush_ptr_NULL); + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, + 1, png_doublep_NULL, png_doublep_NULL); +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then encounter + a png_error() will longjmp here. Since the jmpbuf is then meaningless we + abort instead of returning. */ +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) + PNG_ABORT(); + png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); +#else + if (setjmp(png_ptr->jmpbuf)) + PNG_ABORT(); +#endif +#endif + return (png_ptr); +} + +/* Initialize png_ptr structure, and allocate any memory needed */ +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) + +void PNGAPI +png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size, png_size_t png_info_size) +{ + /* We only come here via pre-1.0.12-compiled applications */ + if(png_ptr == NULL) return; +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + if(png_sizeof(png_struct) > png_struct_size || + png_sizeof(png_info) > png_info_size) + { + char msg[80]; + png_ptr->warning_fn=NULL; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); + } +#endif + if(png_sizeof(png_struct) > png_struct_size) + { + png_ptr->error_fn=NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "The png struct allocated by the application for writing is too small."); + } + if(png_sizeof(png_info) > png_info_size) + { + png_ptr->error_fn=NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "The info struct allocated by the application for writing is too small."); + } + png_write_init_3(&png_ptr, user_png_ver, png_struct_size); +} +#endif /* PNG_1_0_X || PNG_1_2_X */ + + +void PNGAPI +png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size) +{ + png_structp png_ptr=*ptr_ptr; +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* to save current jump buffer */ +#endif + + int i = 0; + + if (png_ptr == NULL) + return; + + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + { +#ifdef PNG_LEGACY_SUPPORTED + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; +#else + png_ptr->warning_fn=NULL; + png_warning(png_ptr, + "Application uses deprecated png_write_init() and should be recompiled."); + break; +#endif + } + } while (png_libpng_ver[i++]); + + png_debug(1, "in png_write_init_3\n"); + +#ifdef PNG_SETJMP_SUPPORTED + /* save jump buffer and error functions */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); +#endif + + if (png_sizeof(png_struct) > png_struct_size) + { + png_destroy_struct(png_ptr); + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); + *ptr_ptr = png_ptr; + } + + /* reset all variables to 0 */ + png_memset(png_ptr, 0, png_sizeof (png_struct)); + + /* added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max=PNG_USER_WIDTH_MAX; + png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* restore jump buffer */ + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); +#endif + + png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, + png_flush_ptr_NULL); + + /* initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, + 1, png_doublep_NULL, png_doublep_NULL); +#endif +} + +/* Write a few rows of image data. If the image is interlaced, + * either you will have to write the 7 sub images, or, if you + * have called png_set_interlace_handling(), you will have to + * "write" the image seven times. + */ +void PNGAPI +png_write_rows(png_structp png_ptr, png_bytepp row, + png_uint_32 num_rows) +{ + png_uint_32 i; /* row counter */ + png_bytepp rp; /* row pointer */ + + png_debug(1, "in png_write_rows\n"); + + if (png_ptr == NULL) + return; + + /* loop through the rows */ + for (i = 0, rp = row; i < num_rows; i++, rp++) + { + png_write_row(png_ptr, *rp); + } +} + +/* Write the image. You only need to call this function once, even + * if you are writing an interlaced image. + */ +void PNGAPI +png_write_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i; /* row index */ + int pass, num_pass; /* pass variables */ + png_bytepp rp; /* points to current row */ + + if (png_ptr == NULL) + return; + + png_debug(1, "in png_write_image\n"); +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* intialize interlace handling. If image is not interlaced, + this will set pass to 1 */ + num_pass = png_set_interlace_handling(png_ptr); +#else + num_pass = 1; +#endif + /* loop through passes */ + for (pass = 0; pass < num_pass; pass++) + { + /* loop through image */ + for (i = 0, rp = image; i < png_ptr->height; i++, rp++) + { + png_write_row(png_ptr, *rp); + } + } +} + +/* called by user to write a row of image data */ +void PNGAPI +png_write_row(png_structp png_ptr, png_bytep row) +{ + if (png_ptr == NULL) + return; + png_debug2(1, "in png_write_row (row %ld, pass %d)\n", + png_ptr->row_number, png_ptr->pass); + + /* initialize transformations and other stuff if first time */ + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* make sure we wrote the header info */ + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + png_error(png_ptr, + "png_write_info was never called before png_write_row."); + + /* check for transforms that have been set but were defined out */ +#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined."); +#endif + + png_write_start_row(png_ptr); + } + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* if interlaced and not interested in row, return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 3: + if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 4: + if ((png_ptr->row_number & 0x03) != 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 6: + if (!(png_ptr->row_number & 0x01)) + { + png_write_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + /* set up row info for transformations */ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->usr_width; + png_ptr->row_info.channels = png_ptr->usr_channels; + png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth; + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_debug1(3, "row_info->color_type = %d\n", png_ptr->row_info.color_type); + png_debug1(3, "row_info->width = %lu\n", png_ptr->row_info.width); + png_debug1(3, "row_info->channels = %d\n", png_ptr->row_info.channels); + png_debug1(3, "row_info->bit_depth = %d\n", png_ptr->row_info.bit_depth); + png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth); + png_debug1(3, "row_info->rowbytes = %lu\n", png_ptr->row_info.rowbytes); + + /* Copy user's row into buffer, leaving room for filter byte. */ + png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row, + png_ptr->row_info.rowbytes); + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* handle interlacing */ + if (png_ptr->interlaced && png_ptr->pass < 6 && + (png_ptr->transformations & PNG_INTERLACE)) + { + png_do_write_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass); + /* this should always get caught above, but still ... */ + if (!(png_ptr->row_info.width)) + { + png_write_finish_row(png_ptr); + return; + } + } +#endif + + /* handle other transformations */ + if (png_ptr->transformations) + png_do_write_transformations(png_ptr); + +#if defined(PNG_MNG_FEATURES_SUPPORTED) + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + /* Find a filter if necessary, filter the row and write it out. */ + png_write_find_filter(png_ptr, &(png_ptr->row_info)); + + if (png_ptr->write_row_fn != NULL) + (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +/* Set the automatic flush interval or 0 to turn flushing off */ +void PNGAPI +png_set_flush(png_structp png_ptr, int nrows) +{ + png_debug(1, "in png_set_flush\n"); + if (png_ptr == NULL) + return; + png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); +} + +/* flush the current output buffers now */ +void PNGAPI +png_write_flush(png_structp png_ptr) +{ + int wrote_IDAT; + + png_debug(1, "in png_write_flush\n"); + if (png_ptr == NULL) + return; + /* We have already written out all of the data */ + if (png_ptr->row_number >= png_ptr->num_rows) + return; + + do + { + int ret; + + /* compress the data */ + ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH); + wrote_IDAT = 0; + + /* check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + + if (!(png_ptr->zstream.avail_out)) + { + /* write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + wrote_IDAT = 1; + } + } while(wrote_IDAT == 1); + + /* If there is any data left to be output, write it into a new IDAT */ + if (png_ptr->zbuf_size != png_ptr->zstream.avail_out) + { + /* write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + png_ptr->flush_rows = 0; + png_flush(png_ptr); +} +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + +/* free all memory used by the write */ +void PNGAPI +png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_write_struct\n"); + if (png_ptr_ptr != NULL) + { + png_ptr = *png_ptr_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + } + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + png_ptr->num_chunk_list=0; + } +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { + png_write_destroy(png_ptr); +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + + +/* Free any memory used in png_ptr struct (old method) */ +void /* PRIVATE */ +png_write_destroy(png_structp png_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* save jump buffer */ +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_write_destroy\n"); + /* free any memory zlib uses */ + deflateEnd(&png_ptr->zstream); + + /* free our memory. png_free checks NULL for us. */ + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->row_buf); + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->sub_row); + png_free(png_ptr, png_ptr->up_row); + png_free(png_ptr, png_ptr->avg_row); + png_free(png_ptr, png_ptr->paeth_row); + +#if defined(PNG_TIME_RFC1123_SUPPORTED) + png_free(png_ptr, png_ptr->time_buffer); +#endif + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_free(png_ptr, png_ptr->prev_filters); + png_free(png_ptr, png_ptr->filter_weights); + png_free(png_ptr, png_ptr->inv_filter_weights); + png_free(png_ptr, png_ptr->filter_costs); + png_free(png_ptr, png_ptr->inv_filter_costs); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* reset structure */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof (png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); +#endif +} + +/* Allow the application to select one or more row filters to use. */ +void PNGAPI +png_set_filter(png_structp png_ptr, int method, int filters) +{ + png_debug(1, "in png_set_filter\n"); + if (png_ptr == NULL) + return; +#if defined(PNG_MNG_FEATURES_SUPPORTED) + if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (method == PNG_INTRAPIXEL_DIFFERENCING)) + method = PNG_FILTER_TYPE_BASE; +#endif + if (method == PNG_FILTER_TYPE_BASE) + { + switch (filters & (PNG_ALL_FILTERS | 0x07)) + { +#ifndef PNG_NO_WRITE_FILTER + case 5: + case 6: + case 7: png_warning(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_NO_WRITE_FILTER */ + case PNG_FILTER_VALUE_NONE: + png_ptr->do_filter=PNG_FILTER_NONE; break; +#ifndef PNG_NO_WRITE_FILTER + case PNG_FILTER_VALUE_SUB: + png_ptr->do_filter=PNG_FILTER_SUB; break; + case PNG_FILTER_VALUE_UP: + png_ptr->do_filter=PNG_FILTER_UP; break; + case PNG_FILTER_VALUE_AVG: + png_ptr->do_filter=PNG_FILTER_AVG; break; + case PNG_FILTER_VALUE_PAETH: + png_ptr->do_filter=PNG_FILTER_PAETH; break; + default: png_ptr->do_filter = (png_byte)filters; break; +#else + default: png_warning(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_NO_WRITE_FILTER */ + } + + /* If we have allocated the row_buf, this means we have already started + * with the image and we should have allocated all of the filter buffers + * that have been selected. If prev_row isn't already allocated, then + * it is too late to start using the filters that need it, since we + * will be missing the data in the previous row. If an application + * wants to start and stop using particular filters during compression, + * it should start out with all of the filters, and then add and + * remove them after the start of compression. + */ + if (png_ptr->row_buf != NULL) + { +#ifndef PNG_NO_WRITE_FILTER + if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Up filter after starting"); + png_ptr->do_filter &= ~PNG_FILTER_UP; + } + else + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Average filter after starting"); + png_ptr->do_filter &= ~PNG_FILTER_AVG; + } + else + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_PAETH) && + png_ptr->paeth_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Paeth filter after starting"); + png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); + } + else + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } + + if (png_ptr->do_filter == PNG_NO_FILTERS) +#endif /* PNG_NO_WRITE_FILTER */ + png_ptr->do_filter = PNG_FILTER_NONE; + } + } + else + png_error(png_ptr, "Unknown custom filter method"); +} + +/* This allows us to influence the way in which libpng chooses the "best" + * filter for the current scanline. While the "minimum-sum-of-absolute- + * differences metric is relatively fast and effective, there is some + * question as to whether it can be improved upon by trying to keep the + * filtered data going to zlib more consistent, hopefully resulting in + * better compression. + */ +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* GRR 970116 */ +void PNGAPI +png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, + int num_weights, png_doublep filter_weights, + png_doublep filter_costs) +{ + int i; + + png_debug(1, "in png_set_filter_heuristics\n"); + if (png_ptr == NULL) + return; + if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST) + { + png_warning(png_ptr, "Unknown filter heuristic method"); + return; + } + + if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT) + { + heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; + } + + if (num_weights < 0 || filter_weights == NULL || + heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) + { + num_weights = 0; + } + + png_ptr->num_prev_filters = (png_byte)num_weights; + png_ptr->heuristic_method = (png_byte)heuristic_method; + + if (num_weights > 0) + { + if (png_ptr->prev_filters == NULL) + { + png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_byte) * num_weights)); + + /* To make sure that the weighting starts out fairly */ + for (i = 0; i < num_weights; i++) + { + png_ptr->prev_filters[i] = 255; + } + } + + if (png_ptr->filter_weights == NULL) + { + png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + + png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + for (i = 0; i < num_weights; i++) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + } + + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] < 0.0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + else + { + png_ptr->inv_filter_weights[i] = + (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5); + png_ptr->filter_weights[i] = + (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5); + } + } + } + + /* If, in the future, there are other filter methods, this would + * need to be based on png_ptr->filter. + */ + if (png_ptr->filter_costs == NULL) + { + png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + + png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + if (filter_costs == NULL || filter_costs[i] < 0.0) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + else if (filter_costs[i] >= 1.0) + { + png_ptr->inv_filter_costs[i] = + (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5); + png_ptr->filter_costs[i] = + (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5); + } + } +} +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +void PNGAPI +png_set_compression_level(png_structp png_ptr, int level) +{ + png_debug(1, "in png_set_compression_level\n"); + if (png_ptr == NULL) + return; + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; + png_ptr->zlib_level = level; +} + +void PNGAPI +png_set_compression_mem_level(png_structp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_compression_mem_level\n"); + if (png_ptr == NULL) + return; + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; + png_ptr->zlib_mem_level = mem_level; +} + +void PNGAPI +png_set_compression_strategy(png_structp png_ptr, int strategy) +{ + png_debug(1, "in png_set_compression_strategy\n"); + if (png_ptr == NULL) + return; + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; + png_ptr->zlib_strategy = strategy; +} + +void PNGAPI +png_set_compression_window_bits(png_structp png_ptr, int window_bits) +{ + if (png_ptr == NULL) + return; + if (window_bits > 15) + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + else if (window_bits < 8) + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); +#ifndef WBITS_8_OK + /* avoid libpng bug with 256-byte windows */ + if (window_bits == 8) + { + png_warning(png_ptr, "Compression window is being reset to 512"); + window_bits=9; + } +#endif + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS; + png_ptr->zlib_window_bits = window_bits; +} + +void PNGAPI +png_set_compression_method(png_structp png_ptr, int method) +{ + png_debug(1, "in png_set_compression_method\n"); + if (png_ptr == NULL) + return; + if (method != 8) + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD; + png_ptr->zlib_method = method; +} + +void PNGAPI +png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) +{ + if (png_ptr == NULL) + return; + png_ptr->write_row_fn = write_row_fn; +} + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +void PNGAPI +png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + write_user_transform_fn) +{ + png_debug(1, "in png_set_write_user_transform_fn\n"); + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->write_user_transform_fn = write_user_transform_fn; +} +#endif + + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +void PNGAPI +png_write_png(png_structp png_ptr, png_infop info_ptr, + int transforms, voidp params) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) + /* invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + + /* Write the file header information. */ + png_write_info(png_ptr, info_ptr); + + /* ------ these transformations don't touch the info structure ------- */ + +#if defined(PNG_WRITE_INVERT_SUPPORTED) + /* invert monochrome pixels */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && (info_ptr->valid & PNG_INFO_sBIT)) + png_set_shift(png_ptr, &info_ptr->sig_bit); +#endif + +#if defined(PNG_WRITE_PACK_SUPPORTED) + /* pack pixels into bytes */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) + /* swap location of alpha bytes from ARGB to RGBA */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) + /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into + * RGB (4 channels -> 3 channels). The second parameter is not used. + */ + if (transforms & PNG_TRANSFORM_STRIP_FILLER) + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); +#endif + +#if defined(PNG_WRITE_BGR_SUPPORTED) + /* flip BGR pixels to RGB */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#if defined(PNG_WRITE_SWAP_SUPPORTED) + /* swap bytes of 16-bit files to most significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) + /* swap bits of 1, 2, 4 bit packed pixel formats */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + + /* ----------------------- end of transformations ------------------- */ + + /* write the bits */ + if (info_ptr->valid & PNG_INFO_IDAT) + png_write_image(png_ptr, info_ptr->row_pointers); + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); + + transforms = transforms; /* quiet compiler warnings */ + params = params; +} +#endif + +#if defined(PNG_WRITE_APNG_SUPPORTED) +void PNGAPI +png_write_frame_head(png_structp png_ptr, png_infop info_ptr, + png_bytepp row_pointers, png_uint_32 width, png_uint_32 height, + png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, + png_byte blend_op) +{ + png_debug(1, "in png_write_frame_head\n"); + + /* there is a chance this has been set after png_write_info was called, + * so it would be set but not written. is there a way to be sure? */ + if (!(info_ptr->valid & PNG_INFO_acTL)) + png_error(png_ptr, "png_write_frame_head(): acTL not set"); + + png_write_reset(png_ptr); + + png_write_reinit(png_ptr, info_ptr, width, height); + + if ( !(png_ptr->num_frames_written == 0 && + (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) ) ) + png_write_fcTL(png_ptr, width, height, x_offset, y_offset, + delay_num, delay_den, dispose_op, blend_op); +} + +void PNGAPI +png_write_frame_tail(png_structp png_ptr, png_infop zpng_info) +{ + png_debug(1, "in png_write_frame_tail\n"); + + png_ptr->num_frames_written++; +} +#endif /* PNG_WRITE_APNG_SUPPORTED */ + +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pngwtran.c b/kernel/kls_png/ksquirrel-libs-png/pngwtran.c new file mode 100644 index 0000000..0372fe6 --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngwtran.c @@ -0,0 +1,572 @@ + +/* pngwtran.c - transforms the data in a row for PNG writers + * + * Last changed in libpng 1.2.9 April 14, 2006 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2006 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Transform the data according to the user's wishes. The order of + * transformations is significant. + */ +void /* PRIVATE */ +png_do_write_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_write_transformations\n"); + + if (png_ptr == NULL) + return; + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + if(png_ptr->write_user_transform_fn != NULL) + (*(png_ptr->write_user_transform_fn)) /* user write transform function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_uint_32 rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#endif +#if defined(PNG_WRITE_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->flags); +#endif +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->bit_depth); +#endif +#if defined(PNG_WRITE_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +} + +#if defined(PNG_WRITE_PACK_SUPPORTED) +/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The + * row_info bit depth should be 8 (one pixel per byte). The channels + * should be 1 (this only happens on grayscale and paletted images). + */ +void /* PRIVATE */ +png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) +{ + png_debug(1, "in png_do_pack\n"); + if (row_info->bit_depth == 8 && +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->channels == 1) + { + switch ((int)bit_depth) + { + case 1: + { + png_bytep sp, dp; + int mask, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + mask = 0x80; + v = 0; + + for (i = 0; i < row_width; i++) + { + if (*sp != 0) + v |= mask; + sp++; + if (mask > 1) + mask >>= 1; + else + { + mask = 0x80; + *dp = (png_byte)v; + dp++; + v = 0; + } + } + if (mask != 0x80) + *dp = (png_byte)v; + break; + } + case 2: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 6; + v = 0; + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x03); + v |= (value << shift); + if (shift == 0) + { + shift = 6; + *dp = (png_byte)v; + dp++; + v = 0; + } + else + shift -= 2; + sp++; + } + if (shift != 6) + *dp = (png_byte)v; + break; + } + case 4: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 4; + v = 0; + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x0f); + v |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp = (png_byte)v; + dp++; + v = 0; + } + else + shift -= 4; + + sp++; + } + if (shift != 4) + *dp = (png_byte)v; + break; + } + } + row_info->bit_depth = (png_byte)bit_depth; + row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Shift pixel values to take advantage of whole range. Pass the + * true number of bits in bit_depth. The row should be packed + * according to row_info->bit_depth. Thus, if you had a row of + * bit depth 4, but the pixels only had values from 0 to 7, you + * would pass 3 as bit_depth, and this routine would translate the + * data to 0 to 15. + */ +void /* PRIVATE */ +png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) +{ + png_debug(1, "in png_do_shift\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && +#else + if ( +#endif + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift_start[4], shift_dec[4]; + int channels = 0; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift_start[channels] = row_info->bit_depth - bit_depth->red; + shift_dec[channels] = bit_depth->red; + channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->green; + shift_dec[channels] = bit_depth->green; + channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->blue; + shift_dec[channels] = bit_depth->blue; + channels++; + } + else + { + shift_start[channels] = row_info->bit_depth - bit_depth->gray; + shift_dec[channels] = bit_depth->gray; + channels++; + } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift_start[channels] = row_info->bit_depth - bit_depth->alpha; + shift_dec[channels] = bit_depth->alpha; + channels++; + } + + /* with low row depths, could only be grayscale, so one channel */ + if (row_info->bit_depth < 8) + { + png_bytep bp = row; + png_uint_32 i; + png_byte mask; + png_uint_32 row_bytes = row_info->rowbytes; + + if (bit_depth->gray == 1 && row_info->bit_depth == 2) + mask = 0x55; + else if (row_info->bit_depth == 4 && bit_depth->gray == 3) + mask = 0x11; + else + mask = 0xff; + + for (i = 0; i < row_bytes; i++, bp++) + { + png_uint_16 v; + int j; + + v = *bp; + *bp = 0; + for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + else + *bp |= (png_byte)((v >> (-j)) & mask); + } + } + } + else if (row_info->bit_depth == 8) + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (i = 0; i < istop; i++, bp++) + { + + png_uint_16 v; + int j; + int c = (int)(i%channels); + + v = *bp; + *bp = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + else + *bp |= (png_byte)((v >> (-j)) & 0xff); + } + } + } + else + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (bp = row, i = 0; i < istop; i++) + { + int c = (int)(i%channels); + png_uint_16 value, v; + int j; + + v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); + value = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); + else + value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); + } + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + } + } +} +#endif + +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_swap_alpha\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from ARGB to RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + /* This converts from AARRGGBB to RRGGBBAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from AG to GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + /* This converts from AAGG to GGAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } + } + } +} +#endif + +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_invert_alpha\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This inverts the alpha channel in RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=3; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=6; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This inverts the alpha channel in GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + /* This inverts the alpha channel in GGAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=2; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + } + } +} +#endif + +#if defined(PNG_MNG_FEATURES_SUPPORTED) +/* undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_write_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_intrapixel\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((*rp - *(rp+1))&0xff); + *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); + png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); + png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); + png_uint_32 red = (png_uint_32)((s0-s1) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2-s1) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp+1) = (png_byte)(red & 0xff); + *(rp+4) = (png_byte)((blue >> 8) & 0xff); + *(rp+5) = (png_byte)(blue & 0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/kernel/kls_png/ksquirrel-libs-png/pngwutil.c b/kernel/kls_png/ksquirrel-libs-png/pngwutil.c new file mode 100644 index 0000000..a526c66 --- /dev/null +++ b/kernel/kls_png/ksquirrel-libs-png/pngwutil.c @@ -0,0 +1,2920 @@ + +/* pngwutil.c - utilities to write a PNG file + * + * Last changed in libpng 1.2.19 August 19, 2007 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2007 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Place a 32-bit number into a buffer in PNG byte order. We work + * with unsigned numbers for convenience, although one supported + * ancillary chunk uses signed (two's complement) numbers. + */ +void PNGAPI +png_save_uint_32(png_bytep buf, png_uint_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} + +/* The png_save_int_32 function assumes integers are stored in two's + * complement format. If this isn't the case, then this routine needs to + * be modified to write data in two's complement format. + */ +void PNGAPI +png_save_int_32(png_bytep buf, png_int_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +void PNGAPI +png_save_uint_16(png_bytep buf, unsigned int i) +{ + buf[0] = (png_byte)((i >> 8) & 0xff); + buf[1] = (png_byte)(i & 0xff); +} + +/* Write a PNG chunk all at once. The type is an array of ASCII characters + * representing the chunk name. The array must be at least 4 bytes in + * length, and does not need to be null terminated. To be safe, pass the + * pre-defined chunk names here, and if you need a new one, define it + * where the others are defined. The length is the length of the data. + * All the data must be present. If that is not possible, use the + * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() + * functions instead. + */ +void PNGAPI +png_write_chunk(png_structp png_ptr, png_bytep chunk_name, + png_bytep data, png_size_t length) +{ + if(png_ptr == NULL) return; + png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); + png_write_chunk_data(png_ptr, data, length); + png_write_chunk_end(png_ptr); +} + +/* Write the start of a PNG chunk. The type is the chunk type. + * The total_length is the sum of the lengths of all the data you will be + * passing in png_write_chunk_data(). + */ +void PNGAPI +png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name, + png_uint_32 length) +{ + png_byte buf[4]; + png_debug2(0, "Writing %s chunk (%lu bytes)\n", chunk_name, length); + if(png_ptr == NULL) return; + + /* write the length */ + png_save_uint_32(buf, length); + png_write_data(png_ptr, buf, (png_size_t)4); + + /* write the chunk name */ + png_write_data(png_ptr, chunk_name, (png_size_t)4); + /* reset the crc and run it over the chunk name */ + png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, chunk_name, (png_size_t)4); +} + +/* Write the data of a PNG chunk started with png_write_chunk_start(). + * Note that multiple calls to this function are allowed, and that the + * sum of the lengths from these calls *must* add up to the total_length + * given to png_write_chunk_start(). + */ +void PNGAPI +png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + /* write the data, and run the CRC over it */ + if(png_ptr == NULL) return; + if (data != NULL && length > 0) + { + png_calculate_crc(png_ptr, data, length); + png_write_data(png_ptr, data, length); + } +} + +/* Finish a chunk started with png_write_chunk_start(). */ +void PNGAPI +png_write_chunk_end(png_structp png_ptr) +{ + png_byte buf[4]; + + if(png_ptr == NULL) return; + + /* write the crc */ + png_save_uint_32(buf, png_ptr->crc); + + png_write_data(png_ptr, buf, (png_size_t)4); +} + +/* Simple function to write the signature. If we have already written + * the magic bytes of the signature, or more likely, the PNG stream is + * being embedded into another stream and doesn't need its own signature, + * we should call png_set_sig_bytes() to tell libpng how many of the + * bytes have already been written. + */ +void /* PRIVATE */ +png_write_sig(png_structp png_ptr) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + /* write the rest of the 8 byte signature */ + png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], + (png_size_t)8 - png_ptr->sig_bytes); + if(png_ptr->sig_bytes < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED) +/* + * This pair of functions encapsulates the operation of (a) compressing a + * text string, and (b) issuing it later as a series of chunk data writes. + * The compression_state structure is shared context for these functions + * set up by the caller in order to make the whole mess thread-safe. + */ + +typedef struct +{ + char *input; /* the uncompressed input data */ + int input_len; /* its length */ + int num_output_ptr; /* number of output pointers used */ + int max_output_ptr; /* size of output_ptr */ + png_charpp output_ptr; /* array of pointers to output */ +} compression_state; + +/* compress given text into storage in the png_ptr structure */ +static int /* PRIVATE */ +png_text_compress(png_structp png_ptr, + png_charp text, png_size_t text_len, int compression, + compression_state *comp) +{ + int ret; + + comp->num_output_ptr = 0; + comp->max_output_ptr = 0; + comp->output_ptr = NULL; + comp->input = NULL; + comp->input_len = 0; + + /* we may just want to pass the text right through */ + if (compression == PNG_TEXT_COMPRESSION_NONE) + { + comp->input = text; + comp->input_len = text_len; + return((int)text_len); + } + + if (compression >= PNG_TEXT_COMPRESSION_LAST) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[50]; + png_snprintf(msg, 50, "Unknown compression type %d", compression); + png_warning(png_ptr, msg); +#else + png_warning(png_ptr, "Unknown compression type"); +#endif + } + + /* We can't write the chunk until we find out how much data we have, + * which means we need to run the compressor first and save the + * output. This shouldn't be a problem, as the vast majority of + * comments should be reasonable, but we will set up an array of + * malloc'd pointers to be sure. + * + * If we knew the application was well behaved, we could simplify this + * greatly by assuming we can always malloc an output buffer large + * enough to hold the compressed text ((1001 * text_len / 1000) + 12) + * and malloc this directly. The only time this would be a bad idea is + * if we can't malloc more than 64K and we have 64K of random input + * data, or if the input string is incredibly large (although this + * wouldn't cause a failure, just a slowdown due to swapping). + */ + + /* set up the compression buffers */ + png_ptr->zstream.avail_in = (uInt)text_len; + png_ptr->zstream.next_in = (Bytef *)text; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf; + + /* this is the same compression loop as in png_write_row() */ + do + { + /* compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + if (ret != Z_OK) + { + /* error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + /* check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* make sure the output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; + + old_ptr = comp->output_ptr; + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof (png_charpp))); + png_memcpy(comp->output_ptr, old_ptr, old_max + * png_sizeof (png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof (png_charp))); + } + + /* save the data */ + comp->output_ptr[comp->num_output_ptr] = (png_charp)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; + + /* and reset the buffer */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + /* continue until we don't have any more to compress */ + } while (png_ptr->zstream.avail_in); + + /* finish the compression */ + do + { + /* tell zlib we are finished */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + + if (ret == Z_OK) + { + /* check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* check to make sure our output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; + + old_ptr = comp->output_ptr; + /* This could be optimized to realloc() */ + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof (png_charpp))); + png_memcpy(comp->output_ptr, old_ptr, + old_max * png_sizeof (png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof (png_charp))); + } + + /* save off the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_charp)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; + + /* and reset the buffer pointers */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + } + else if (ret != Z_STREAM_END) + { + /* we got an error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* text length is number of buffers plus last buffer */ + text_len = png_ptr->zbuf_size * comp->num_output_ptr; + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; + + return((int)text_len); +} + +/* ship the compressed text out via chunk writes */ +static void /* PRIVATE */ +png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) +{ + int i; + + /* handle the no-compression case */ + if (comp->input) + { + png_write_chunk_data(png_ptr, (png_bytep)comp->input, + (png_size_t)comp->input_len); + return; + } + + /* write saved output buffers, if any */ + for (i = 0; i < comp->num_output_ptr; i++) + { + png_write_chunk_data(png_ptr,(png_bytep)comp->output_ptr[i], + png_ptr->zbuf_size); + png_free(png_ptr, comp->output_ptr[i]); + comp->output_ptr[i]=NULL; + } + if (comp->max_output_ptr != 0) + png_free(png_ptr, comp->output_ptr); + comp->output_ptr=NULL; + /* write anything left in zbuf */ + if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) + png_write_chunk_data(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + /* reset zlib for another zTXt/iTXt or image data */ + deflateReset(&png_ptr->zstream); + png_ptr->zstream.data_type = Z_BINARY; +} +#endif + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. Note that the rest of this code depends upon this + * information being correct. + */ +void /* PRIVATE */ +png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, + int bit_depth, int color_type, int compression_type, int filter_type, + int interlace_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IHDR; +#endif + png_byte buf[13]; /* buffer to store the IHDR info */ + + png_debug(1, "in png_write_IHDR\n"); + /* Check that we have valid input data from the application info */ + switch (color_type) + { + case PNG_COLOR_TYPE_GRAY: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: + case 16: png_ptr->channels = 1; break; + default: png_error(png_ptr,"Invalid bit depth for grayscale image"); + } + break; + case PNG_COLOR_TYPE_RGB: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for RGB image"); + png_ptr->channels = 3; + break; + case PNG_COLOR_TYPE_PALETTE: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: png_ptr->channels = 1; break; + default: png_error(png_ptr, "Invalid bit depth for paletted image"); + } + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); + png_ptr->channels = 2; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for RGBA image"); + png_ptr->channels = 4; + break; + default: + png_error(png_ptr, "Invalid image color type specified"); + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Invalid compression type specified"); + compression_type = PNG_COMPRESSION_TYPE_BASE; + } + + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ( +#if defined(PNG_MNG_FEATURES_SUPPORTED) + !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && +#endif + filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Invalid filter type specified"); + filter_type = PNG_FILTER_TYPE_BASE; + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + if (interlace_type != PNG_INTERLACE_NONE && + interlace_type != PNG_INTERLACE_ADAM7) + { + png_warning(png_ptr, "Invalid interlace type specified"); + interlace_type = PNG_INTERLACE_ADAM7; + } +#else + interlace_type=PNG_INTERLACE_NONE; +#endif + + /* save off the relevent information */ + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->color_type = (png_byte)color_type; + png_ptr->interlaced = (png_byte)interlace_type; +#if defined(PNG_MNG_FEATURES_SUPPORTED) + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + png_ptr->width = width; + png_ptr->height = height; + + png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); + /* set the usr info, so any transformations can modify it */ + png_ptr->usr_width = png_ptr->width; + png_ptr->usr_bit_depth = png_ptr->bit_depth; + png_ptr->usr_channels = png_ptr->channels; + + /* pack the header information into the buffer */ + png_save_uint_32(buf, width); + png_save_uint_32(buf + 4, height); + buf[8] = (png_byte)bit_depth; + buf[9] = (png_byte)color_type; + buf[10] = (png_byte)compression_type; + buf[11] = (png_byte)filter_type; + buf[12] = (png_byte)interlace_type; + + /* write the chunk */ + png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13); + +#if defined(PNG_WRITE_APNG_SUPPORTED) + png_ptr->first_frame_width = width; + png_ptr->first_frame_height = height; +#endif + + /* initialize zlib with PNG info */ + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + if (!(png_ptr->do_filter)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || + png_ptr->bit_depth < 8) + png_ptr->do_filter = PNG_FILTER_NONE; + else + png_ptr->do_filter = PNG_ALL_FILTERS; + } + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) + { + if (png_ptr->do_filter != PNG_FILTER_NONE) + png_ptr->zlib_strategy = Z_FILTERED; + else + png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; + } + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) + png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) + png_ptr->zlib_mem_level = 8; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) + png_ptr->zlib_window_bits = 15; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) + png_ptr->zlib_method = 8; + if (deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, + png_ptr->zlib_method, png_ptr->zlib_window_bits, + png_ptr->zlib_mem_level, png_ptr->zlib_strategy) != Z_OK) + png_error(png_ptr, "zlib failed to initialize compressor"); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + /* libpng is not interested in zstream.data_type */ + /* set it to a predefined value, to avoid its evaluation inside zlib */ + png_ptr->zstream.data_type = Z_BINARY; + + png_ptr->mode = PNG_HAVE_IHDR; +} + +/* write the palette. We are careful not to trust png_color to be in the + * correct order for PNG, so people can redefine it to any convenient + * structure. + */ +void /* PRIVATE */ +png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_PLTE; +#endif + png_uint_32 i; + png_colorp pal_ptr; + png_byte buf[3]; + + png_debug(1, "in png_write_PLTE\n"); + if (( +#if defined(PNG_MNG_FEATURES_SUPPORTED) + !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && +#endif + num_pal == 0) || num_pal > 256) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_error(png_ptr, "Invalid number of colors in palette"); + } + else + { + png_warning(png_ptr, "Invalid number of colors in palette"); + return; + } + } + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring request to write a PLTE chunk in grayscale PNG"); + return; + } + + png_ptr->num_palette = (png_uint_16)num_pal; + png_debug1(3, "num_palette = %d\n", png_ptr->num_palette); + + png_write_chunk_start(png_ptr, png_PLTE, num_pal * 3); +#ifndef PNG_NO_POINTER_INDEXING + for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) + { + buf[0] = pal_ptr->red; + buf[1] = pal_ptr->green; + buf[2] = pal_ptr->blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } +#else + /* This is a little slower but some buggy compilers need to do this instead */ + pal_ptr=palette; + for (i = 0; i < num_pal; i++) + { + buf[0] = pal_ptr[i].red; + buf[1] = pal_ptr[i].green; + buf[2] = pal_ptr[i].blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } +#endif + png_write_chunk_end(png_ptr); + png_ptr->mode |= PNG_HAVE_PLTE; +} + +/* write an IDAT chunk */ +void /* PRIVATE */ +png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IDAT; +#if defined(PNG_WRITE_APNG_SUPPORTED) + PNG_fdAT; +#endif +#endif + png_debug(1, "in png_write_IDAT\n"); + + /* Optimize the CMF field in the zlib stream. */ + /* This hack of the zlib stream is compliant to the stream specification. */ + if (!(png_ptr->mode & PNG_HAVE_IDAT) && + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) + { + unsigned int z_cmf = data[0]; /* zlib compression method and flags */ + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) + { + /* Avoid memory underflows and multiplication overflows. */ + /* The conditions below are practically always satisfied; + however, they still must be checked. */ + if (length >= 2 && + png_ptr->height < 16384 && png_ptr->width < 16384) + { + png_uint_32 uncompressed_idat_size = png_ptr->height * + ((png_ptr->width * + png_ptr->channels * png_ptr->bit_depth + 15) >> 3); + unsigned int z_cinfo = z_cmf >> 4; + unsigned int half_z_window_size = 1 << (z_cinfo + 7); + while (uncompressed_idat_size <= half_z_window_size && + half_z_window_size >= 256) + { + z_cinfo--; + half_z_window_size >>= 1; + } + z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); + if (data[0] != (png_byte)z_cmf) + { + data[0] = (png_byte)z_cmf; + data[1] &= 0xe0; + data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f); + } + } + } + else + png_error(png_ptr, + "Invalid zlib compression method or flags in IDAT"); + } + +#if defined(PNG_WRITE_APNG_SUPPORTED) + if(png_ptr->num_frames_written == 0) +#endif + png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length); +#if defined(PNG_WRITE_APNG_SUPPORTED) + else + { + png_byte buf[4]; + + png_write_chunk_start(png_ptr, (png_bytep)png_fdAT, 4 + length); + + png_save_uint_32(buf, png_ptr->next_seq_num); + png_write_chunk_data(png_ptr, buf, 4); + + png_write_chunk_data(png_ptr, data, length); + + png_write_chunk_end(png_ptr); + + png_ptr->next_seq_num++; + } +#endif + + png_ptr->mode |= PNG_HAVE_IDAT; +} + +/* write an IEND chunk */ +void /* PRIVATE */ +png_write_IEND(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IEND; +#endif + png_debug(1, "in png_write_IEND\n"); + png_write_chunk(png_ptr, (png_bytep)png_IEND, png_bytep_NULL, + (png_size_t)0); + png_ptr->mode |= PNG_HAVE_IEND; +} + +#if defined(PNG_WRITE_gAMA_SUPPORTED) +/* write a gAMA chunk */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void /* PRIVATE */ +png_write_gAMA(png_structp png_ptr, double file_gamma) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_gAMA; +#endif + png_uint_32 igamma; + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA\n"); + /* file_gamma is saved in 1/100,000ths */ + igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5); + png_save_uint_32(buf, igamma); + png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_gAMA; +#endif + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA\n"); + /* file_gamma is saved in 1/100,000ths */ + png_save_uint_32(buf, (png_uint_32)file_gamma); + png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); +} +#endif +#endif + +#if defined(PNG_WRITE_sRGB_SUPPORTED) +/* write a sRGB chunk */ +void /* PRIVATE */ +png_write_sRGB(png_structp png_ptr, int srgb_intent) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sRGB; +#endif + png_byte buf[1]; + + png_debug(1, "in png_write_sRGB\n"); + if(srgb_intent >= PNG_sRGB_INTENT_LAST) + png_warning(png_ptr, + "Invalid sRGB rendering intent specified"); + buf[0]=(png_byte)srgb_intent; + png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1); +} +#endif + +#if defined(PNG_WRITE_iCCP_SUPPORTED) +/* write an iCCP chunk */ +void /* PRIVATE */ +png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, + png_charp profile, int profile_len) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_iCCP; +#endif + png_size_t name_len; + png_charp new_name; + compression_state comp; + int embedded_profile_len = 0; + + png_debug(1, "in png_write_iCCP\n"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + comp.input_len = 0; + + if (name == NULL || (name_len = png_check_keyword(png_ptr, name, + &new_name)) == 0) + { + png_warning(png_ptr, "Empty keyword in iCCP chunk"); + return; + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + png_warning(png_ptr, "Unknown compression type in iCCP chunk"); + + if (profile == NULL) + profile_len = 0; + + if (profile_len > 3) + embedded_profile_len = + ((*( (png_bytep)profile ))<<24) | + ((*( (png_bytep)profile+1))<<16) | + ((*( (png_bytep)profile+2))<< 8) | + ((*( (png_bytep)profile+3)) ); + + if (profile_len < embedded_profile_len) + { + png_warning(png_ptr, + "Embedded profile length too large in iCCP chunk"); + return; + } + + if (profile_len > embedded_profile_len) + { + png_warning(png_ptr, + "Truncating profile to actual length in iCCP chunk"); + profile_len = embedded_profile_len; + } + + if (profile_len) + profile_len = png_text_compress(png_ptr, profile, (png_size_t)profile_len, + PNG_COMPRESSION_TYPE_BASE, &comp); + + /* make sure we include the NULL after the name and the compression type */ + png_write_chunk_start(png_ptr, png_iCCP, + (png_uint_32)name_len+profile_len+2); + new_name[name_len+1]=0x00; + png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 2); + + if (profile_len) + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#if defined(PNG_WRITE_sPLT_SUPPORTED) +/* write a sPLT chunk */ +void /* PRIVATE */ +png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sPLT; +#endif + png_size_t name_len; + png_charp new_name; + png_byte entrybuf[10]; + int entry_size = (spalette->depth == 8 ? 6 : 10); + int palette_size = entry_size * spalette->nentries; + png_sPLT_entryp ep; +#ifdef PNG_NO_POINTER_INDEXING + int i; +#endif + + png_debug(1, "in png_write_sPLT\n"); + if (spalette->name == NULL || (name_len = png_check_keyword(png_ptr, + spalette->name, &new_name))==0) + { + png_warning(png_ptr, "Empty keyword in sPLT chunk"); + return; + } + + /* make sure we include the NULL after the name */ + png_write_chunk_start(png_ptr, png_sPLT, + (png_uint_32)(name_len + 2 + palette_size)); + png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 1); + png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, 1); + + /* loop through each palette entry, writing appropriately */ +#ifndef PNG_NO_POINTER_INDEXING + for (ep = spalette->entries; epentries+spalette->nentries; ep++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep->red; + entrybuf[1] = (png_byte)ep->green; + entrybuf[2] = (png_byte)ep->blue; + entrybuf[3] = (png_byte)ep->alpha; + png_save_uint_16(entrybuf + 4, ep->frequency); + } + else + { + png_save_uint_16(entrybuf + 0, ep->red); + png_save_uint_16(entrybuf + 2, ep->green); + png_save_uint_16(entrybuf + 4, ep->blue); + png_save_uint_16(entrybuf + 6, ep->alpha); + png_save_uint_16(entrybuf + 8, ep->frequency); + } + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); + } +#else + ep=spalette->entries; + for (i=0; i>spalette->nentries; i++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep[i].red; + entrybuf[1] = (png_byte)ep[i].green; + entrybuf[2] = (png_byte)ep[i].blue; + entrybuf[3] = (png_byte)ep[i].alpha; + png_save_uint_16(entrybuf + 4, ep[i].frequency); + } + else + { + png_save_uint_16(entrybuf + 0, ep[i].red); + png_save_uint_16(entrybuf + 2, ep[i].green); + png_save_uint_16(entrybuf + 4, ep[i].blue); + png_save_uint_16(entrybuf + 6, ep[i].alpha); + png_save_uint_16(entrybuf + 8, ep[i].frequency); + } + png_write_chunk_data(png_ptr, entrybuf, entry_size); + } +#endif + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#if defined(PNG_WRITE_sBIT_SUPPORTED) +/* write the sBIT chunk */ +void /* PRIVATE */ +png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sBIT; +#endif + png_byte buf[4]; + png_size_t size; + + png_debug(1, "in png_write_sBIT\n"); + /* make sure we don't depend upon the order of PNG_COLOR_8 */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + png_byte maxbits; + + maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : + png_ptr->usr_bit_depth); + if (sbit->red == 0 || sbit->red > maxbits || + sbit->green == 0 || sbit->green > maxbits || + sbit->blue == 0 || sbit->blue > maxbits) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[0] = sbit->red; + buf[1] = sbit->green; + buf[2] = sbit->blue; + size = 3; + } + else + { + if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[0] = sbit->gray; + size = 1; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[size++] = sbit->alpha; + } + + png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size); +} +#endif + +#if defined(PNG_WRITE_cHRM_SUPPORTED) +/* write the cHRM chunk */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void /* PRIVATE */ +png_write_cHRM(png_structp png_ptr, double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_cHRM; +#endif + png_byte buf[32]; + png_uint_32 itemp; + + png_debug(1, "in png_write_cHRM\n"); + /* each value is saved in 1/100,000ths */ + if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 || + white_x + white_y > 1.0) + { + png_warning(png_ptr, "Invalid cHRM white point specified"); +#if !defined(PNG_NO_CONSOLE_IO) + fprintf(stderr,"white_x=%f, white_y=%f\n",white_x, white_y); +#endif + return; + } + itemp = (png_uint_32)(white_x * 100000.0 + 0.5); + png_save_uint_32(buf, itemp); + itemp = (png_uint_32)(white_y * 100000.0 + 0.5); + png_save_uint_32(buf + 4, itemp); + + if (red_x < 0 || red_y < 0 || red_x + red_y > 1.0) + { + png_warning(png_ptr, "Invalid cHRM red point specified"); + return; + } + itemp = (png_uint_32)(red_x * 100000.0 + 0.5); + png_save_uint_32(buf + 8, itemp); + itemp = (png_uint_32)(red_y * 100000.0 + 0.5); + png_save_uint_32(buf + 12, itemp); + + if (green_x < 0 || green_y < 0 || green_x + green_y > 1.0) + { + png_warning(png_ptr, "Invalid cHRM green point specified"); + return; + } + itemp = (png_uint_32)(green_x * 100000.0 + 0.5); + png_save_uint_32(buf + 16, itemp); + itemp = (png_uint_32)(green_y * 100000.0 + 0.5); + png_save_uint_32(buf + 20, itemp); + + if (blue_x < 0 || blue_y < 0 || blue_x + blue_y > 1.0) + { + png_warning(png_ptr, "Invalid cHRM blue point specified"); + return; + } + itemp = (png_uint_32)(blue_x * 100000.0 + 0.5); + png_save_uint_32(buf + 24, itemp); + itemp = (png_uint_32)(blue_y * 100000.0 + 0.5); + png_save_uint_32(buf + 28, itemp); + + png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, + png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, + png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, + png_fixed_point blue_y) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_cHRM; +#endif + png_byte buf[32]; + + png_debug(1, "in png_write_cHRM\n"); + /* each value is saved in 1/100,000ths */ + if (white_x > 80000L || white_y > 80000L || white_x + white_y > 100000L) + { + png_warning(png_ptr, "Invalid fixed cHRM white point specified"); +#if !defined(PNG_NO_CONSOLE_IO) + fprintf(stderr,"white_x=%ld, white_y=%ld\n",white_x, white_y); +#endif + return; + } + png_save_uint_32(buf, (png_uint_32)white_x); + png_save_uint_32(buf + 4, (png_uint_32)white_y); + + if (red_x + red_y > 100000L) + { + png_warning(png_ptr, "Invalid cHRM fixed red point specified"); + return; + } + png_save_uint_32(buf + 8, (png_uint_32)red_x); + png_save_uint_32(buf + 12, (png_uint_32)red_y); + + if (green_x + green_y > 100000L) + { + png_warning(png_ptr, "Invalid fixed cHRM green point specified"); + return; + } + png_save_uint_32(buf + 16, (png_uint_32)green_x); + png_save_uint_32(buf + 20, (png_uint_32)green_y); + + if (blue_x + blue_y > 100000L) + { + png_warning(png_ptr, "Invalid fixed cHRM blue point specified"); + return; + } + png_save_uint_32(buf + 24, (png_uint_32)blue_x); + png_save_uint_32(buf + 28, (png_uint_32)blue_y); + + png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); +} +#endif +#endif + +#if defined(PNG_WRITE_tRNS_SUPPORTED) +/* write the tRNS chunk */ +void /* PRIVATE */ +png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran, + int num_trans, int color_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_tRNS; +#endif + png_byte buf[6]; + + png_debug(1, "in png_write_tRNS\n"); + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) + { + png_warning(png_ptr,"Invalid number of transparent colors specified"); + return; + } + /* write the chunk out as it is */ + png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans, (png_size_t)num_trans); + } + else if (color_type == PNG_COLOR_TYPE_GRAY) + { + /* one 16 bit value */ + if(tran->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); + return; + } + png_save_uint_16(buf, tran->gray); + png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2); + } + else if (color_type == PNG_COLOR_TYPE_RGB) + { + /* three 16 bit values */ + png_save_uint_16(buf, tran->red); + png_save_uint_16(buf + 2, tran->green); + png_save_uint_16(buf + 4, tran->blue); + if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); + return; + } + png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6); + } + else + { + png_warning(png_ptr, "Can't write tRNS with an alpha channel"); + } +} +#endif + +#if defined(PNG_WRITE_bKGD_SUPPORTED) +/* write the background chunk */ +void /* PRIVATE */ +png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_bKGD; +#endif + png_byte buf[6]; + + png_debug(1, "in png_write_bKGD\n"); + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if ( +#if defined(PNG_MNG_FEATURES_SUPPORTED) + (png_ptr->num_palette || + (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && +#endif + back->index > png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid background palette index"); + return; + } + buf[0] = back->index; + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1); + } + else if (color_type & PNG_COLOR_MASK_COLOR) + { + png_save_uint_16(buf, back->red); + png_save_uint_16(buf + 2, back->green); + png_save_uint_16(buf + 4, back->blue); + if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); + return; + } + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6); + } + else + { + if(back->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); + return; + } + png_save_uint_16(buf, back->gray); + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2); + } +} +#endif + +#if defined(PNG_WRITE_hIST_SUPPORTED) +/* write the histogram */ +void /* PRIVATE */ +png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_hIST; +#endif + int i; + png_byte buf[3]; + + png_debug(1, "in png_write_hIST\n"); + if (num_hist > (int)png_ptr->num_palette) + { + png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist, + png_ptr->num_palette); + png_warning(png_ptr, "Invalid number of histogram entries specified"); + return; + } + + png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); + for (i = 0; i < num_hist; i++) + { + png_save_uint_16(buf, hist[i]); + png_write_chunk_data(png_ptr, buf, (png_size_t)2); + } + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, + * and if invalid, correct the keyword rather than discarding the entire + * chunk. The PNG 1.0 specification requires keywords 1-79 characters in + * length, forbids leading or trailing whitespace, multiple internal spaces, + * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. + * + * The new_key is allocated to hold the corrected keyword and must be freed + * by the calling routine. This avoids problems with trying to write to + * static keywords without having to have duplicate copies of the strings. + */ +png_size_t /* PRIVATE */ +png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) +{ + png_size_t key_len; + png_charp kp, dp; + int kflag; + int kwarn=0; + + png_debug(1, "in png_check_keyword\n"); + *new_key = NULL; + + if (key == NULL || (key_len = png_strlen(key)) == 0) + { + png_warning(png_ptr, "zero length keyword"); + return ((png_size_t)0); + } + + png_debug1(2, "Keyword to be checked is '%s'\n", key); + + *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); + if (*new_key == NULL) + { + png_warning(png_ptr, "Out of memory while procesing keyword"); + return ((png_size_t)0); + } + + /* Replace non-printing characters with a blank and print a warning */ + for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++) + { + if ((png_byte)*kp < 0x20 || + ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1)) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[40]; + + png_snprintf(msg, 40, + "invalid keyword character 0x%02X", (png_byte)*kp); + png_warning(png_ptr, msg); +#else + png_warning(png_ptr, "invalid character in keyword"); +#endif + *dp = ' '; + } + else + { + *dp = *kp; + } + } + *dp = '\0'; + + /* Remove any trailing white space. */ + kp = *new_key + key_len - 1; + if (*kp == ' ') + { + png_warning(png_ptr, "trailing spaces removed from keyword"); + + while (*kp == ' ') + { + *(kp--) = '\0'; + key_len--; + } + } + + /* Remove any leading white space. */ + kp = *new_key; + if (*kp == ' ') + { + png_warning(png_ptr, "leading spaces removed from keyword"); + + while (*kp == ' ') + { + kp++; + key_len--; + } + } + + png_debug1(2, "Checking for multiple internal spaces in '%s'\n", kp); + + /* Remove multiple internal spaces. */ + for (kflag = 0, dp = *new_key; *kp != '\0'; kp++) + { + if (*kp == ' ' && kflag == 0) + { + *(dp++) = *kp; + kflag = 1; + } + else if (*kp == ' ') + { + key_len--; + kwarn=1; + } + else + { + *(dp++) = *kp; + kflag = 0; + } + } + *dp = '\0'; + if(kwarn) + png_warning(png_ptr, "extra interior spaces removed from keyword"); + + if (key_len == 0) + { + png_free(png_ptr, *new_key); + *new_key=NULL; + png_warning(png_ptr, "Zero length keyword"); + } + + if (key_len > 79) + { + png_warning(png_ptr, "keyword length must be 1 - 79 characters"); + new_key[79] = '\0'; + key_len = 79; + } + + return (key_len); +} +#endif + +#if defined(PNG_WRITE_tEXt_SUPPORTED) +/* write a tEXt chunk */ +void /* PRIVATE */ +png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, + png_size_t text_len) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_tEXt; +#endif + png_size_t key_len; + png_charp new_key; + + png_debug(1, "in png_write_tEXt\n"); + if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) + { + png_warning(png_ptr, "Empty keyword in tEXt chunk"); + return; + } + + if (text == NULL || *text == '\0') + text_len = 0; + else + text_len = png_strlen(text); + + /* make sure we include the 0 after the key */ + png_write_chunk_start(png_ptr, (png_bytep)png_tEXt, (png_uint_32)key_len+text_len+1); + /* + * We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); + if (text_len) + png_write_chunk_data(png_ptr, (png_bytep)text, text_len); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); +} +#endif + +#if defined(PNG_WRITE_zTXt_SUPPORTED) +/* write a compressed text chunk */ +void /* PRIVATE */ +png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, + png_size_t text_len, int compression) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_zTXt; +#endif + png_size_t key_len; + char buf[1]; + png_charp new_key; + compression_state comp; + + png_debug(1, "in png_write_zTXt\n"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + comp.input_len = 0; + + if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) + { + png_warning(png_ptr, "Empty keyword in zTXt chunk"); + return; + } + + if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) + { + png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); + png_free(png_ptr, new_key); + return; + } + + text_len = png_strlen(text); + + /* compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression, + &comp); + + /* write start of chunk */ + png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, (png_uint_32) + (key_len+text_len+2)); + /* write key */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); + png_free(png_ptr, new_key); + + buf[0] = (png_byte)compression; + /* write compression */ + png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1); + /* write the compressed data */ + png_write_compressed_data_out(png_ptr, &comp); + + /* close the chunk */ + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_iTXt_SUPPORTED) +/* write an iTXt chunk */ +void /* PRIVATE */ +png_write_iTXt(png_structp png_ptr, int compression, png_charp key, + png_charp lang, png_charp lang_key, png_charp text) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_iTXt; +#endif + png_size_t lang_len, key_len, lang_key_len, text_len; + png_charp new_lang, new_key; + png_byte cbuf[2]; + compression_state comp; + + png_debug(1, "in png_write_iTXt\n"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + + if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) + { + png_warning(png_ptr, "Empty keyword in iTXt chunk"); + return; + } + if (lang == NULL || (lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0) + { + png_warning(png_ptr, "Empty language field in iTXt chunk"); + new_lang = NULL; + lang_len = 0; + } + + if (lang_key == NULL) + lang_key_len = 0; + else + lang_key_len = png_strlen(lang_key); + + if (text == NULL) + text_len = 0; + else + text_len = png_strlen(text); + + /* compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression-2, + &comp); + + + /* make sure we include the compression flag, the compression byte, + * and the NULs after the key, lang, and lang_key parts */ + + png_write_chunk_start(png_ptr, (png_bytep)png_iTXt, + (png_uint_32)( + 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ + + key_len + + lang_len + + lang_key_len + + text_len)); + + /* + * We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); + + /* set the compression flag */ + if (compression == PNG_ITXT_COMPRESSION_NONE || \ + compression == PNG_TEXT_COMPRESSION_NONE) + cbuf[0] = 0; + else /* compression == PNG_ITXT_COMPRESSION_zTXt */ + cbuf[0] = 1; + /* set the compression method */ + cbuf[1] = 0; + png_write_chunk_data(png_ptr, cbuf, 2); + + cbuf[0] = 0; + png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf), lang_len + 1); + png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf), lang_key_len + 1); + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); + if (new_lang) + png_free(png_ptr, new_lang); +} +#endif + +#if defined(PNG_WRITE_oFFs_SUPPORTED) +/* write the oFFs chunk */ +void /* PRIVATE */ +png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, + int unit_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_oFFs; +#endif + png_byte buf[9]; + + png_debug(1, "in png_write_oFFs\n"); + if (unit_type >= PNG_OFFSET_LAST) + png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); + + png_save_int_32(buf, x_offset); + png_save_int_32(buf + 4, y_offset); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); +} +#endif +#if defined(PNG_WRITE_pCAL_SUPPORTED) +/* write the pCAL chunk (described in the PNG extensions document) */ +void /* PRIVATE */ +png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, + png_int_32 X1, int type, int nparams, png_charp units, png_charpp params) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_pCAL; +#endif + png_size_t purpose_len, units_len, total_len; + png_uint_32p params_len; + png_byte buf[10]; + png_charp new_purpose; + int i; + + png_debug1(1, "in png_write_pCAL (%d parameters)\n", nparams); + if (type >= PNG_EQUATION_LAST) + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + + purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; + png_debug1(3, "pCAL purpose length = %d\n", (int)purpose_len); + units_len = png_strlen(units) + (nparams == 0 ? 0 : 1); + png_debug1(3, "pCAL units length = %d\n", (int)units_len); + total_len = purpose_len + units_len + 10; + + params_len = (png_uint_32p)png_malloc(png_ptr, (png_uint_32)(nparams + *png_sizeof(png_uint_32))); + + /* Find the length of each parameter, making sure we don't count the + null terminator for the last parameter. */ + for (i = 0; i < nparams; i++) + { + params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); + png_debug2(3, "pCAL parameter %d length = %lu\n", i, params_len[i]); + total_len += (png_size_t)params_len[i]; + } + + png_debug1(3, "pCAL total length = %d\n", (int)total_len); + png_write_chunk_start(png_ptr, png_pCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_bytep)new_purpose, purpose_len); + png_save_int_32(buf, X0); + png_save_int_32(buf + 4, X1); + buf[8] = (png_byte)type; + buf[9] = (png_byte)nparams; + png_write_chunk_data(png_ptr, buf, (png_size_t)10); + png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len); + + png_free(png_ptr, new_purpose); + + for (i = 0; i < nparams; i++) + { + png_write_chunk_data(png_ptr, (png_bytep)params[i], + (png_size_t)params_len[i]); + } + + png_free(png_ptr, params_len); + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_sCAL_SUPPORTED) +/* write the sCAL chunk */ +#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) +void /* PRIVATE */ +png_write_sCAL(png_structp png_ptr, int unit, double width, double height) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sCAL; +#endif + char buf[64]; + png_size_t total_len; + + png_debug(1, "in png_write_sCAL\n"); + + buf[0] = (char)unit; +#if defined(_WIN32_WCE) +/* sprintf() function is not supported on WindowsCE */ + { + wchar_t wc_buf[32]; + size_t wc_len; + swprintf(wc_buf, TEXT("%12.12e"), width); + wc_len = wcslen(wc_buf); + WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL, NULL); + total_len = wc_len + 2; + swprintf(wc_buf, TEXT("%12.12e"), height); + wc_len = wcslen(wc_buf); + WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + total_len, wc_len, + NULL, NULL); + total_len += wc_len; + } +#else + png_snprintf(buf + 1, 63, "%12.12e", width); + total_len = 1 + png_strlen(buf + 1) + 1; + png_snprintf(buf + total_len, 64-total_len, "%12.12e", height); + total_len += png_strlen(buf + total_len); +#endif + + png_debug1(3, "sCAL total length = %u\n", (unsigned int)total_len); + png_write_chunk(png_ptr, png_sCAL, (png_bytep)buf, total_len); +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width, + png_charp height) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sCAL; +#endif + png_byte buf[64]; + png_size_t wlen, hlen, total_len; + + png_debug(1, "in png_write_sCAL_s\n"); + + wlen = png_strlen(width); + hlen = png_strlen(height); + total_len = wlen + hlen + 2; + if (total_len > 64) + { + png_warning(png_ptr, "Can't write sCAL (buffer too small)"); + return; + } + + buf[0] = (png_byte)unit; + png_memcpy(buf + 1, width, wlen + 1); /* append the '\0' here */ + png_memcpy(buf + wlen + 2, height, hlen); /* do NOT append the '\0' here */ + + png_debug1(3, "sCAL total length = %u\n", (unsigned int)total_len); + png_write_chunk(png_ptr, png_sCAL, buf, total_len); +} +#endif +#endif +#endif + +#if defined(PNG_WRITE_pHYs_SUPPORTED) +/* write the pHYs chunk */ +void /* PRIVATE */ +png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, + png_uint_32 y_pixels_per_unit, + int unit_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_pHYs; +#endif + png_byte buf[9]; + + png_debug(1, "in png_write_pHYs\n"); + if (unit_type >= PNG_RESOLUTION_LAST) + png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); + + png_save_uint_32(buf, x_pixels_per_unit); + png_save_uint_32(buf + 4, y_pixels_per_unit); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); +} +#endif + +#if defined(PNG_WRITE_tIME_SUPPORTED) +/* Write the tIME chunk. Use either png_convert_from_struct_tm() + * or png_convert_from_time_t(), or fill in the structure yourself. + */ +void /* PRIVATE */ +png_write_tIME(png_structp png_ptr, png_timep mod_time) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_tIME; +#endif + png_byte buf[7]; + + png_debug(1, "in png_write_tIME\n"); + if (mod_time->month > 12 || mod_time->month < 1 || + mod_time->day > 31 || mod_time->day < 1 || + mod_time->hour > 23 || mod_time->second > 60) + { + png_warning(png_ptr, "Invalid time specified for tIME chunk"); + return; + } + + png_save_uint_16(buf, mod_time->year); + buf[2] = mod_time->month; + buf[3] = mod_time->day; + buf[4] = mod_time->hour; + buf[5] = mod_time->minute; + buf[6] = mod_time->second; + + png_write_chunk(png_ptr, png_tIME, buf, (png_size_t)7); +} +#endif + +#if defined(PNG_WRITE_APNG_SUPPORTED) +void /* PRIVATE */ +png_write_acTL(png_structp png_ptr, + png_uint_32 num_frames, png_uint_32 num_plays) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_acTL; +#endif + png_byte data[16]; + + png_debug(1, "in png_write_acTL\n"); + + png_ptr->num_frames_to_write = num_frames; + + if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) + num_frames--; + + png_save_uint_32(data, num_frames); + png_save_uint_32(data + 4, num_plays); + + png_write_chunk(png_ptr, (png_bytep)png_acTL, data, (png_size_t)8); +} + +void /* PRIVATE */ +png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height, + png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, + png_byte blend_op) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_fcTL; +#endif + png_byte data[26]; + + png_debug(1, "in png_write_fcTL\n"); + + if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0)) + png_error(png_ptr, "x and/or y offset for the first frame aren't 0\n"); + if (png_ptr->num_frames_written == 0 && + (width != png_ptr->first_frame_width || + height != png_ptr->first_frame_height)) + png_error(png_ptr, "width and/or height in the first frame's fcTL " + "don't match the ones in IHDR\n"); + + /* more error checking */ + png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, + delay_num, delay_den, dispose_op, blend_op); + + png_save_uint_32(data, png_ptr->next_seq_num); + png_save_uint_32(data + 4, width); + png_save_uint_32(data + 8, height); + png_save_uint_32(data + 12, x_offset); + png_save_uint_32(data + 16, y_offset); + png_save_uint_16(data + 20, delay_num); + png_save_uint_16(data + 22, delay_den); + data[24] = dispose_op; + data[25] = blend_op; + + png_write_chunk(png_ptr, (png_bytep)png_fcTL, data, (png_size_t)26); + + png_ptr->next_seq_num++; +} +#endif /* PNG_WRITE_APNG_SUPPORTED */ + +/* initializes the row writing capability of libpng */ +void /* PRIVATE */ +png_write_start_row(png_structp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif +#endif + + png_size_t buf_size; + + png_debug(1, "in png_write_start_row\n"); + buf_size = (png_size_t)(PNG_ROWBYTES( + png_ptr->usr_channels*png_ptr->usr_bit_depth,png_ptr->width)+1); + + /* set up row buffer */ + png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size); + png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; + +#ifndef PNG_NO_WRITE_FILTERING + /* set up filtering buffer, if using this filter */ + if (png_ptr->do_filter & PNG_FILTER_SUB) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + /* We only need to keep the previous row if we are using one of these. */ + if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) + { + /* set up previous row buffer */ + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size); + png_memset(png_ptr->prev_row, 0, buf_size); + + if (png_ptr->do_filter & PNG_FILTER_UP) + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + + if (png_ptr->do_filter & PNG_FILTER_AVG) + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + + if (png_ptr->do_filter & PNG_FILTER_PAETH) + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } +#endif /* PNG_NO_WRITE_FILTERING */ + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* if interlaced, we need to set up width and height of pass */ + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - + png_pass_start[0]) / png_pass_inc[0]; + } + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + } + else +#endif + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; +} + +/* Internal use only. Called when finished processing a row of data. */ +void /* PRIVATE */ +png_write_finish_row(png_structp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif +#endif + + int ret; + + png_debug(1, "in png_write_finish_row\n"); + /* next row */ + png_ptr->row_number++; + + /* see if we are done */ + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* if interlaced, go to next pass */ + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + if (png_ptr->transformations & PNG_INTERLACE) + { + png_ptr->pass++; + } + else + { + /* loop until we find a non-zero width or height pass */ + do + { + png_ptr->pass++; + if (png_ptr->pass >= 7) + break; + png_ptr->usr_width = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + if (png_ptr->transformations & PNG_INTERLACE) + break; + } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); + + } + + /* reset the row above the image for the next pass */ + if (png_ptr->pass < 7) + { + if (png_ptr->prev_row != NULL) + png_memset(png_ptr->prev_row, 0, + (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* + png_ptr->usr_bit_depth,png_ptr->width))+1); + return; + } + } +#endif + + /* if we get here, we've just written the last row, so we need + to flush the compressor */ + do + { + /* tell the compressor we are done */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + /* check for an error */ + if (ret == Z_OK) + { + /* check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else if (ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* write any extra space */ + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - + png_ptr->zstream.avail_out); + } + + deflateReset(&png_ptr->zstream); + png_ptr->zstream.data_type = Z_BINARY; +} + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Pick out the correct pixels for the interlace pass. + * The basic idea here is to go through the row with a source + * pointer and a destination pointer (sp and dp), and copy the + * correct pixels for the pass. As the row gets compacted, + * sp will always be >= dp, so we should never overwrite anything. + * See the default: case for the easiest code to understand. + */ +void /* PRIVATE */ +png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +#endif + + png_debug(1, "in png_do_write_interlace\n"); + /* we don't have to do anything on the last pass (6) */ +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && pass < 6) +#else + if (pass < 6) +#endif + { + /* each pixel depth is handled separately */ + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + d = 0; + shift = 7; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 3); + value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; + d |= (value << shift); + + if (shift == 0) + { + shift = 7; + *dp++ = (png_byte)d; + d = 0; + } + else + shift--; + + } + if (shift != 7) + *dp = (png_byte)d; + break; + } + case 2: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 6; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 2); + value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; + d |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp++ = (png_byte)d; + d = 0; + } + else + shift -= 2; + } + if (shift != 6) + *dp = (png_byte)d; + break; + } + case 4: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 4; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 1); + value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; + d |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp++ = (png_byte)d; + d = 0; + } + else + shift -= 4; + } + if (shift != 4) + *dp = (png_byte)d; + break; + } + default: + { + png_bytep sp; + png_bytep dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + png_size_t pixel_bytes; + + /* start at the beginning */ + dp = row; + /* find out how many bytes each pixel takes up */ + pixel_bytes = (row_info->pixel_depth >> 3); + /* loop through the row, only looking at the pixels that + matter */ + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + /* find out where the original pixel is */ + sp = row + (png_size_t)i * pixel_bytes; + /* move the pixel */ + if (dp != sp) + png_memcpy(dp, sp, pixel_bytes); + /* next pixel */ + dp += pixel_bytes; + } + break; + } + } + /* set new row width */ + row_info->width = (row_info->width + + png_pass_inc[pass] - 1 - + png_pass_start[pass]) / + png_pass_inc[pass]; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +/* This filters the row, chooses which filter to use, if it has not already + * been specified by the application, and then writes the row out with the + * chosen filter. + */ +#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) +#define PNG_HISHIFT 10 +#define PNG_LOMASK ((png_uint_32)0xffffL) +#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) +void /* PRIVATE */ +png_write_find_filter(png_structp png_ptr, png_row_infop row_info) +{ + png_bytep best_row; +#ifndef PNG_NO_WRITE_FILTER + png_bytep prev_row, row_buf; + png_uint_32 mins, bpp; + png_byte filter_to_do = png_ptr->do_filter; + png_uint_32 row_bytes = row_info->rowbytes; +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + int num_p_filters = (int)png_ptr->num_prev_filters; +#endif + + png_debug(1, "in png_write_find_filter\n"); + /* find out how many bytes offset each pixel is */ + bpp = (row_info->pixel_depth + 7) >> 3; + + prev_row = png_ptr->prev_row; +#endif + best_row = png_ptr->row_buf; +#ifndef PNG_NO_WRITE_FILTER + row_buf = best_row; + mins = PNG_MAXSUM; + + /* The prediction method we use is to find which method provides the + * smallest value when summing the absolute values of the distances + * from zero, using anything >= 128 as negative numbers. This is known + * as the "minimum sum of absolute differences" heuristic. Other + * heuristics are the "weighted minimum sum of absolute differences" + * (experimental and can in theory improve compression), and the "zlib + * predictive" method (not implemented yet), which does test compressions + * of lines using different filter methods, and then chooses the + * (series of) filter(s) that give minimum compressed data size (VERY + * computationally expensive). + * + * GRR 980525: consider also + * (1) minimum sum of absolute differences from running average (i.e., + * keep running sum of non-absolute differences & count of bytes) + * [track dispersion, too? restart average if dispersion too large?] + * (1b) minimum sum of absolute differences from sliding average, probably + * with window size <= deflate window (usually 32K) + * (2) minimum sum of squared differences from zero or running average + * (i.e., ~ root-mean-square approach) + */ + + + /* We don't need to test the 'no filter' case if this is the only filter + * that has been chosen, as it doesn't actually do anything to the data. + */ + if ((filter_to_do & PNG_FILTER_NONE) && + filter_to_do != PNG_FILTER_NONE) + { + png_bytep rp; + png_uint_32 sum = 0; + png_uint_32 i; + int v; + + for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) + { + v = *rp; + sum += (v < 128) ? v : 256 - v; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + png_uint_32 sumhi, sumlo; + int j; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ + + /* Reduce the sum if we match any of the previous rows */ + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + /* Factor in the cost of this filter (this is here for completeness, + * but it makes no sense to have a "cost" for the NONE filter, as + * it has the minimum possible computational cost - none). + */ + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + mins = sum; + } + + /* sub filter */ + if (filter_to_do == PNG_FILTER_SUB) + /* it's the only filter so no testing is needed */ + { + png_bytep rp, lp, dp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + *dp = *rp; + } + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + } + best_row = png_ptr->sub_row; + } + + else if (filter_to_do & PNG_FILTER_SUB) + { + png_bytep rp, dp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + /* We temporarily increase the "minimum sum" by the factor we + * would reduce the sum of this filter, so that we can do the + * early exit comparison without scaling the sum each time. + */ + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + v = *dp = *rp; + + sum += (v < 128) ? v : 256 - v; + } + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->sub_row; + } + } + + /* up filter */ + if (filter_to_do == PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; + i++, rp++, pp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); + } + best_row = png_ptr->up_row; + } + + else if (filter_to_do & PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->up_row; + } + } + + /* avg filter */ + if (filter_to_do == PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + } + for (lp = row_buf + 1; i < row_bytes; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) + & 0xff); + } + best_row = png_ptr->avg_row; + } + + else if (filter_to_do & PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + for (lp = row_buf + 1; i < row_bytes; i++) + { + v = *dp++ = + (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->avg_row; + } + } + + /* Paeth filter */ + if (filter_to_do == PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + } + best_row = png_ptr->paeth_row; + } + + else if (filter_to_do & PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + +#ifndef PNG_SLOW_PAETH + p = b - c; + pc = a - c; +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; +#else /* PNG_SLOW_PAETH */ + p = a + b - c; + pa = abs(p - a); + pb = abs(p - b); + pc = abs(p - c); + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; +#endif /* PNG_SLOW_PAETH */ + + v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + best_row = png_ptr->paeth_row; + } + } +#endif /* PNG_NO_WRITE_FILTER */ + /* Do the actual writing of the filtered row data from the chosen filter. */ + + png_write_filtered_row(png_ptr, best_row); + +#ifndef PNG_NO_WRITE_FILTER +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + /* Save the type of filter we picked this time for future calculations */ + if (png_ptr->num_prev_filters > 0) + { + int j; + for (j = 1; j < num_p_filters; j++) + { + png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; + } + png_ptr->prev_filters[j] = best_row[0]; + } +#endif +#endif /* PNG_NO_WRITE_FILTER */ +} + + +/* Do the actual writing of a previously filtered row. */ +void /* PRIVATE */ +png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) +{ + png_debug(1, "in png_write_filtered_row\n"); + png_debug1(2, "filter = %d\n", filtered_row[0]); + /* set up the zlib input buffer */ + + png_ptr->zstream.next_in = filtered_row; + png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1; + /* repeat until we have compressed all the data */ + do + { + int ret; /* return of zlib */ + + /* compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + /* check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + + /* see if it is time to write another IDAT */ + if (!(png_ptr->zstream.avail_out)) + { + /* write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + /* repeat until all data has been compressed */ + } while (png_ptr->zstream.avail_in); + + /* swap the current and previous rows */ + if (png_ptr->prev_row != NULL) + { + png_bytep tptr; + + tptr = png_ptr->prev_row; + png_ptr->prev_row = png_ptr->row_buf; + png_ptr->row_buf = tptr; + } + + /* finish row - updates counters and flushes zlib if last row */ + png_write_finish_row(png_ptr); + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) + png_ptr->flush_rows++; + + if (png_ptr->flush_dist > 0 && + png_ptr->flush_rows >= png_ptr->flush_dist) + { + png_write_flush(png_ptr); + } +#endif +} + +#if defined(PNG_WRITE_APNG_SUPPORTED) +void /* PRIVATE */ +png_write_reset(png_structp png_ptr) +{ + png_ptr->row_number = 0; + png_ptr->pass = 0; + png_ptr->mode &= ~PNG_HAVE_IDAT; +} + +void /* PRIVATE */ +png_write_reinit(png_structp png_ptr, png_infop info_ptr, + png_uint_32 width, png_uint_32 height) +{ + if (png_ptr->num_frames_written == 0 && + (width != png_ptr->first_frame_width || + height != png_ptr->first_frame_height)) + png_error(png_ptr, "width and/or height in the first frame's fcTL " + "don't match the ones in IHDR\n"); + if (width > png_ptr->first_frame_width || + height > png_ptr->first_frame_height) + png_error(png_ptr, "width and/or height for a frame greater than" + "the ones in IHDR"); + + png_set_IHDR(png_ptr, info_ptr, width, height, + info_ptr->bit_depth, info_ptr->color_type, + info_ptr->interlace_type, info_ptr->compression_type, + info_ptr->filter_type); + + png_ptr->width = width; + png_ptr->height = height; + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); + png_ptr->usr_width = png_ptr->width; +} +#endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/kernel/kls_pnm/Makefile.am b/kernel/kls_pnm/Makefile.am new file mode 100644 index 0000000..ddc0486 --- /dev/null +++ b/kernel/kls_pnm/Makefile.am @@ -0,0 +1,11 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_pnm.la + +libkls_pnm_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_pnm_la_LDFLAGS = ${SQ_RELEASE} + +libkls_pnm_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DCODEC_PNM \ No newline at end of file diff --git a/kernel/kls_pnm/fmt_codec_pnm.cpp b/kernel/kls_pnm/fmt_codec_pnm.cpp new file mode 100644 index 0000000..00edbfb --- /dev/null +++ b/kernel/kls_pnm/fmt_codec_pnm.cpp @@ -0,0 +1,1469 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_pnm/fmt_codec_pnm_defs.h b/kernel/kls_pnm/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_pnm/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_psd/Makefile.am b/kernel/kls_psd/Makefile.am new file mode 100644 index 0000000..82132ab --- /dev/null +++ b/kernel/kls_psd/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_psd.la + +libkls_psd_la_SOURCES = fmt_codec_psd.cpp fmt_codec_psd_defs.h + +libkls_psd_la_LDFLAGS = ${SQ_RELEASE} + +libkls_psd_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_psd/fmt_codec_psd.cpp b/kernel/kls_psd/fmt_codec_psd.cpp new file mode 100644 index 0000000..dad3863 --- /dev/null +++ b/kernel/kls_psd/fmt_codec_psd.cpp @@ -0,0 +1,394 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_psd_defs.h" +#include "fmt_codec_psd.h" + +#include "../xpm/codec_psd.xpm" + +/* + * + * Adobe's Photoshop is probably the fullest featured and most highly + * respected commercial image-processing bitmap manipulation program in + * the PC and Macintosh worlds. Its wide distribution + * has meant that image data is often left in PSD + * format files and may persist in this form after the original image + * data is long gone. + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.8.1"; + o->name = "Adobe Photoshop PSD"; + o->filter = "*.psd "; + o->config = ""; + o->mime = "\x0038\x0042\x0050\x0053\x0001"; + o->mimetype = "image/psd;image/x-vnd.adobe.photoshop"; + o->pixmap = codec_psd; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + layer = -1; + + u32 ident; + u16 ver; + + if(!frs.be_getlong(&ident)) + return SQE_R_BADFILE; + + if(ident != 0x38425053) + return SQE_R_NOTSUPPORTED; + + if(!frs.be_getshort(&ver)) + return SQE_R_BADFILE; + + if(ver != 1) + return SQE_R_BADFILE; + + last = 0; + L = 0; + + s8 dummy[6]; + if(!frs.readK(dummy, 6)) return SQE_R_BADFILE; + + if(!frs.be_getshort(&channels)) + return SQE_R_BADFILE; + + if(!frs.be_getlong(&height)) + return SQE_R_BADFILE; + + if(!frs.be_getlong(&width)) + return SQE_R_BADFILE; + + if(!frs.be_getshort(&depth)) + return SQE_R_BADFILE; + + if(!frs.be_getshort(&mode)) + return SQE_R_BADFILE; + + if(depth != 8) + return SQE_R_NOTSUPPORTED; + + if(mode != PSD_RGB && mode != PSD_CMYK && mode != PSD_INDEXED && mode != PSD_GRAYSCALE) + return SQE_R_NOTSUPPORTED; + + if(mode == PSD_RGB && channels != 3 && channels != 4) + return SQE_R_NOTSUPPORTED; + + if(mode == PSD_CMYK && channels != 4 && channels != 5) + return SQE_R_NOTSUPPORTED; + + if(mode == PSD_INDEXED && channels != 1) + return SQE_R_NOTSUPPORTED; + + u32 data_count; + + if(!frs.be_getlong(&data_count)) + return SQE_R_BADFILE; + + if(data_count) + { + if(!frs.readK(pal, 256 * sizeof(RGB))) return SQE_R_BADFILE; + } + + if(!frs.be_getlong(&data_count)) + return SQE_R_BADFILE; + + if(data_count) + frs.seekg(data_count, ios::cur); + + if(!frs.be_getlong(&data_count)) + return SQE_R_BADFILE; + + if(data_count) + frs.seekg(data_count, ios::cur); + + // find out if the data is compressed + // 0: no compressiod + // 1: RLE compressed + + if(!frs.be_getshort(&compression)) + return SQE_R_BADFILE; + + if(compression != 1 && compression != 0) + return SQE_R_NOTSUPPORTED; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + image.hasalpha = (mode == PSD_RGB) ? true : ((channels == 5) ? true : false); + image.passes = (channels == 5) ? 4 : channels; + image.h = height; + image.w = width; + + if(compression) + { + u16 b[height * channels]; + + if(!frs.readK(b, 2 * height * channels)) return SQE_R_BADFILE; + } + + std::string type; + + switch(mode) + { + case PSD_RGB: + type = "RGB"; + image.bpp = 24; + break; + + case PSD_CMYK: + type = "CMYK"; + image.bpp = (channels == 5) ? 32 : 24; + break; + + case PSD_INDEXED: + type = "Color indexed"; + image.bpp = 8; + break; + + case PSD_GRAYSCALE: + type = "Grayscale"; + image.bpp = 8; + break; + } + + last = (RGBA **)calloc(height, sizeof(RGBA*)); + + if(!last) + return SQE_R_NOMEMORY; + + const s32 S = width * sizeof(RGBA); + + for(u32 i = 0;i < height;i++) + { + last[i] = (RGBA*)0; + } + + for(u32 i = 0;i < height;i++) + { + last[i] = (RGBA*)malloc(S); + + if(!last[i]) + return SQE_R_NOMEMORY; + + memset(last[i], 255, S); + } + + line = -1; + + L = (u8*)calloc(width, 1); + + if(!L) + return SQE_R_NOMEMORY; + + image.compression = ((compression) ? "RLE" : "-"); + image.colorspace = type; + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + layer++; + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + u8 c, value, *p; + s32 count = 0; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + line++; + + memcpy(scan, last[line], im->w * sizeof(RGBA)); + + if(compression) + { + while(count < im->w) + { + if(!frs.readK(&c, 1)) return SQE_R_BADFILE; + + if(c == 128) + {} // do nothing + else if(c > 128) + { + c ^= 0xff; + c += 2; + + if(!frs.readK(&value, 1)) return SQE_R_BADFILE; + + for(s32 i = count; i < count+c;i++) + { + p = (u8*)(scan+i); + *(p+layer) = value; + } + + count += c; + } + else if(c < 128) + { + c++; + + for(s32 i = count; i < count+c;i++) + { + if(!frs.readK(&value, 1)) return SQE_R_BADFILE; + + p = (u8*)(scan+i); + *(p+layer) = value; + } + + count += c; + } + } + } + else + { + if(!frs.readK(L, width)) return SQE_R_BADFILE; + + for(u32 i = 0;i < width;i++) + { + p = (u8*)(scan+i); + *(p+layer) = L[i]; + } + } + + memcpy(last[line], scan, im->w * sizeof(RGBA)); + + if(layer == im->passes-1) + { + if(mode == PSD_CMYK) + { + for(s32 i = 0;i < im->w;i++) + { + scan[i].r = (scan[i].r * scan[i].a) >> 8; + scan[i].g = (scan[i].g * scan[i].a) >> 8; + scan[i].b = (scan[i].b * scan[i].a) >> 8; + + if(channels == 4) + scan[i].a = 255; + } + } + else if(mode == PSD_INDEXED) + { + u8 r; + const s32 z1 = 768/3; + const s32 z2 = z1 << 1; + + for(s32 i = 0;i < im->w;i++) + { + u8 *p = (u8*)pal; + r = scan[i].r; + + (scan+i)->r = *(p+r); + (scan+i)->g = *(p+r+z1); + (scan+i)->b = *(p+r+z2); + scan[i].a = 255; + } + } + else if(mode == PSD_GRAYSCALE) + { + u8 v; + + for(s32 i = 0;i < im->w;i++) + { + v = scan[i].r; + + (scan+i)->r = v; + (scan+i)->g = v; + (scan+i)->b = v; + scan[i].a = 255; + } + } + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + if(last) + { + for(u32 i = 0;i < height;i++) + { + if(last[i]) + free(last[i]); + } + + free(last); + } + + finfo.meta.clear(); + finfo.image.clear(); + + if(L) + free(L); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_psd/fmt_codec_psd_defs.h b/kernel/kls_psd/fmt_codec_psd_defs.h new file mode 100644 index 0000000..aa6f3dd --- /dev/null +++ b/kernel/kls_psd/fmt_codec_psd_defs.h @@ -0,0 +1,43 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_psd +#define KSQUIRREL_READ_IMAGE_psd + +// 0: Bitmap +// 1: Grayscale +// 2: Indexed color +// 3: RGB color +// 4: CMYK color +// 7: Multichannel +// 8: Duotone +// 9: Lab color + +#define PSD_BITMAP 0 +#define PSD_GRAYSCALE 1 +#define PSD_INDEXED 2 +#define PSD_RGB 3 +#define PSD_CMYK 4 +#define PSD_MULTICHANNEL 7 +#define PSD_DUOTONE 8 +#define PSD_LAB 9 + +#endif diff --git a/kernel/kls_psp/Makefile.am b/kernel/kls_psp/Makefile.am new file mode 100644 index 0000000..d9ae202 --- /dev/null +++ b/kernel/kls_psp/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_psp.la + +libkls_psp_la_SOURCES = fmt_codec_psp.cpp fmt_codec_psp_defs.h + +libkls_psp_la_LDFLAGS = ${SQ_RELEASE} + +libkls_psp_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_psp/fmt_codec_psp.cpp b/kernel/kls_psp/fmt_codec_psp.cpp new file mode 100644 index 0000000..e77caa4 --- /dev/null +++ b/kernel/kls_psp/fmt_codec_psp.cpp @@ -0,0 +1,635 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_psp_defs.h" +#include "fmt_codec_psp.h" + +#include "ksquirrel-libs/error.h" + +#include "../xpm/codec_psp.xpm" + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.1.0"; + o->name = "PaintShop Pro"; + o->filter = "*.psp "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-psp"; + o->pixmap = codec_psp; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +/************** Utility functions from DevIL *********************/ + +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2002 by Denton Woods +// Last modified: 05/04/2002 <--Y2K Compliant! =] +// +// Filename: src-IL/src/il_psp.c +// +// Description: Reads a Paint Shop Pro file. +// +//----------------------------------------------------------------------------- + + +bool fmt_codec::iGetPspHead() +{ + if(!frs.readK(Header.FileSig, 32)) + return false; + + if(!frs.readK(&Header.MajorVersion, sizeof(Header.MajorVersion))) + return false; + + if(!frs.readK(&Header.MinorVersion, sizeof(Header.MinorVersion))) + return false; + + return true; +} + +bool fmt_codec::iCheckPsp() +{ + if (strcmp(Header.FileSig, "Paint Shop Pro Image File\n\x1a")) // "i" + return false; + if (Header.MajorVersion < 3 || Header.MajorVersion > 5) + return false; + if (Header.MinorVersion != 0) + return false; + + return true; +} + +bool fmt_codec::ReadGenAttributes() +{ + BLOCKHEAD AttHead; + ILint Padding; + ILuint ChunkLen; + + if(!frs.readK(&AttHead, sizeof(AttHead))) + return false; + + if (AttHead.HeadID[0] != 0x7E || AttHead.HeadID[1] != 0x42 || AttHead.HeadID[2] != 0x4B || AttHead.HeadID[3] != 0x00) + return false; + + if (AttHead.BlockID != PSP_IMAGE_BLOCK) + return false; + + if(!frs.readK(&ChunkLen, sizeof(ChunkLen))) + return false; + + if (Header.MajorVersion != 3) + ChunkLen -= 4; + + if (!frs.readK(&AttChunk, std::min(sizeof(AttChunk), size_t(ChunkLen)))) + return false; + + // Can have new entries in newer versions of the spec (4.0). + Padding = (ChunkLen) - sizeof(AttChunk); + + if (Padding > 0) + frs.seekg(Padding, ios::cur); + + // @TODO: Anything but 24 not supported yet... + if (AttChunk.BitDepth != 24 && AttChunk.BitDepth != 8) + return false; + + // @TODO; Add support for compression... + if (AttChunk.Compression != PSP_COMP_NONE && AttChunk.Compression != PSP_COMP_RLE) + return false; + + // @TODO: Check more things in the general attributes chunk here. + return true; +} + +bool fmt_codec::ParseChunks() +{ + BLOCKHEAD Block; + size_t Pos; + + do { + if (!frs.readK(&Block, sizeof(Block))) + return true; + + if (Header.MajorVersion == 3) + frs.readK(&Block.BlockLen, sizeof(Block.BlockLen)); + + if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) + return true; + + Pos = frs.tellg(); + + switch (Block.BlockID) + { + case PSP_LAYER_START_BLOCK: + if (!ReadLayerBlock()) + return false; + break; + + case PSP_ALPHA_BANK_BLOCK: + if (!ReadAlphaBlock()) + return false; + break; + + case PSP_COLOR_BLOCK: + if (!ReadPalette()) + return false; + break; + } + + // Skip to next block just in case we didn't read the entire block. + frs.seekg(Pos + Block.BlockLen, ios::beg); + + } + while (1); + + return true; +} + +bool fmt_codec::ReadLayerBlock() +{ + BLOCKHEAD Block; + LAYERINFO_CHUNK LayerInfo; + LAYERBITMAP_CHUNK Bitmap; + ILuint ChunkSize, Padding, i; + ILushort NumChars; + + // Layer sub-block header + if (!frs.readK(&Block, sizeof(Block))) + return false; + + if(Header.MajorVersion == 3) + frs.readK(&Block.BlockLen, sizeof(Block.BlockLen)); + + if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) + return false; + + if (Block.BlockID != PSP_LAYER_BLOCK) + return false; + + if (Header.MajorVersion == 3) + { + frs.seekg(256, ios::cur); // We don't care about the name of the layer. + frs.readK(&LayerInfo, sizeof(LayerInfo)); + + if(!frs.readK(&Bitmap, sizeof(Bitmap))) + return false; + } + else + { // Header.MajorVersion >= 4 + frs.readK(&ChunkSize, sizeof(ChunkSize)); + frs.readK(&NumChars, sizeof(NumChars)); + frs.seekg(NumChars, ios::cur); // We don't care about the layer's name. + + ChunkSize -= (2 + 4 + NumChars); + + if (!frs.readK(&LayerInfo, std::min(sizeof(LayerInfo), size_t(ChunkSize)))) + return false; + + // Can have new entries in newer versions of the spec (5.0). + Padding = (ChunkSize) - sizeof(LayerInfo); + + if (Padding > 0) + frs.seekg(Padding, ios::cur); + + frs.readK(&ChunkSize, sizeof(ChunkSize)); + + if (!frs.readK(&Bitmap, sizeof(Bitmap))) + return false; + + Padding = (ChunkSize - 4) - sizeof(Bitmap); + + if (Padding > 0) + frs.seekg(Padding, ios::cur); + } + + Channels = new ILubyte* [Bitmap.NumChannels]; + + if (!Channels) + return false; + + NumChannels = Bitmap.NumChannels; + + for (i = 0; i < NumChannels; i++) + Channels[i] = 0; + + for (i = 0; i < NumChannels; i++) + { + Channels[i] = GetChannel(); + + if(!Channels[i]) + return false; + } + + return true; +} + +bool fmt_codec::ReadAlphaBlock() +{ + BLOCKHEAD Block; + ALPHAINFO_CHUNK AlphaInfo; + ALPHA_CHUNK AlphaChunk; + ILushort NumAlpha, StringSize; + ILuint ChunkSize, Padding; + + if (Header.MajorVersion == 3) { + frs.readK(&NumAlpha, sizeof(NumAlpha)); + } + else { + frs.readK(&ChunkSize, sizeof(ChunkSize)); + frs.readK(&NumAlpha, sizeof(NumAlpha)); + + Padding = (ChunkSize - 4 - 2); + + if (Padding > 0) + frs.seekg(Padding, ios::cur); + } + + // Alpha channel header + if (!frs.readK(&Block, sizeof(Block))) + return false; + + if (Header.MajorVersion == 3) + frs.readK(&Block.BlockLen, sizeof(Block.BlockLen)); + + if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || + Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { + return false; + } + if (Block.BlockID != PSP_ALPHA_CHANNEL_BLOCK) + return false; + + if (Header.MajorVersion >= 4) + { + frs.readK(&ChunkSize, sizeof(ChunkSize)); + frs.readK(&StringSize, sizeof(StringSize)); + + frs.seekg(StringSize, ios::cur); + + if (!frs.readK(&AlphaInfo, sizeof(AlphaInfo))) + return false; + + Padding = (ChunkSize - 4 - 2 - StringSize - sizeof(AlphaInfo)); + + if (Padding > 0) + frs.seekg(Padding, ios::cur); + + frs.readK(&ChunkSize, sizeof(ChunkSize)); + + if (!frs.readK(&AlphaChunk, sizeof(AlphaChunk))) + return false; + + Padding = (ChunkSize - 4 - sizeof(AlphaChunk)); + + if (Padding > 0) + frs.seekg(Padding, ios::cur); + } + else { + frs.seekg(256, ios::cur); + frs.readK(&AlphaInfo, sizeof(AlphaInfo)); + + if(!frs.readK(&AlphaChunk, sizeof(AlphaChunk))) + return false; + } + + Alpha = GetChannel(); + + if (!Alpha) + return false; + + return true; +} + +ILubyte *fmt_codec::GetChannel() +{ + BLOCKHEAD Block; + CHANNEL_CHUNK Channel; + ILubyte *CompData = 0, *Data = 0; + ILuint ChunkSize, Padding; + + if (!frs.readK(&Block, sizeof(Block))) + return 0; + + if (Header.MajorVersion == 3) + frs.readK(&Block.BlockLen, sizeof(Block.BlockLen)); + + if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) + return 0; + + if (Block.BlockID != PSP_CHANNEL_BLOCK) + return 0; + + if (Header.MajorVersion >= 4) + { + frs.readK(&ChunkSize, sizeof(ChunkSize)); + + if (!frs.readK(&Channel, sizeof(Channel))) + return 0; + + Padding = (ChunkSize - 4) - sizeof(Channel); + + if (Padding > 0) + frs.seekg(Padding, ios::cur); + } + else + { + if (!frs.readK(&Channel, sizeof(Channel))) + return 0; + } + + CompData = new ILubyte [Channel.CompLen]; + + if (!CompData) + return 0; + + if (!frs.readK(CompData, Channel.CompLen)) + { + delete CompData; + return 0; + } + + if(AttChunk.Compression != PSP_COMP_NONE) + { + Data = new ILubyte [AttChunk.Width * AttChunk.Height]; + + if (!Data) + { + delete CompData; + return 0; + } + } + + switch (AttChunk.Compression) + { + case PSP_COMP_NONE: + return CompData; + + case PSP_COMP_RLE: + if (!UncompRLE(CompData, Data, Channel.CompLen)) + { + delete Data; + delete CompData; + return 0; + } + break; + + default: + delete Data; + delete CompData; + return 0; + } + + delete CompData; + + return Data; +} + +bool fmt_codec::UncompRLE(ILubyte *CompData, ILubyte *Data, ILuint CompLen) +{ + ILubyte Run, Colour; + ILint i, Count; + + for (i = 0, Count = 0; i < (ILint)CompLen; ) { + Run = *CompData++; + i++; + if (Run > 128) { + Run -= 128; + Colour = *CompData++; + i++; + memset(Data, Colour, Run); + } + else { + memcpy(Data, CompData, Run); + CompData += Run; + i += Run; + } + Data += Run; + Count += Run; + } + + return true; +} + +bool fmt_codec::ReadPalette() +{ + ILuint ChunkSize, PalCount, Padding; + RGBA rgba; + + if (Header.MajorVersion >= 4) + { + frs.readK(&ChunkSize, sizeof(ChunkSize)); + frs.readK(&PalCount, sizeof(PalCount)); + + Padding = (ChunkSize - 4 - 4); + + if (Padding > 0) + frs.seekg(Padding, ios::cur); + } + else + frs.readK(&PalCount, sizeof(PalCount)); + + pal = new RGBA [PalCount]; + + if(!pal) + return false; + + RGBA *ppal = pal; + + for(u32 i = 0;i < PalCount;i++) + { + if(!frs.readK(&rgba, sizeof(RGBA))) + return false; + + ppal->r = rgba.b; + ppal->g = rgba.g; + ppal->b = rgba.r; + ppal->a = rgba.a; + + ppal++; + } + + return true; +} + +/******************** ksquirrel-libs stuff ****************************/ + +s32 fmt_codec::read_init(const std::string &file) +{ + Channels = 0; + Alpha = 0; + pal = 0; + + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + read_error = false; + finfo.animated = false; + + if(!iGetPspHead()) + return SQE_R_BADFILE; + + if(!iCheckPsp()) + return SQE_R_BADFILE; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + if(!ReadGenAttributes()) + return SQE_R_BADFILE; + + if(!ParseChunks()) + return SQE_R_BADFILE; + +// if(!AssembleImage()) +// return SQE_R_BADFILE; + + fmt_image image; + + image.w = AttChunk.Width; + image.h = AttChunk.Height; + image.compression = (AttChunk.Compression == PSP_COMP_RLE ? "RLE" : "-"); + image.bpp = (NumChannels == 1 ? 8 : ((Alpha || NumChannels == 4) ? 32 : 24)); + image.colorspace = fmt_utils::colorSpaceByBpp(image.bpp); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + line++; + + fmt_image *im = image(currentImage); + + u32 i, j; + u32 ifrom = line * im->w; + u32 ito = ifrom + im->w; + + if (NumChannels == 1) + { + memset(scan, 0, im->w * sizeof(RGBA)); + + for (i = ifrom, j = 0; i < ito; i++, j++) + { + scan[j] = pal[Channels[0][i]]; + scan[j].a = 255; + } + } + else + { + if (Alpha) + { + memset(scan, 0, im->w * sizeof(RGBA)); + u8 *data = (u8 *)scan; + + for (i = ifrom, j = 0; i < ito; i++, j += 4) + { + data[j ] = Channels[0][i]; + data[j+1] = Channels[1][i]; + data[j+2] = Channels[2][i]; + data[j+3] = Alpha[i]; + } + } + // 3 channels, or 4 without alpha + else if (NumChannels == 3 || NumChannels == 4) + { + memset(scan, 0, im->w * sizeof(RGBA)); + u8 *data = (u8 *)scan; + + for (i = ifrom, j = 0; i < ito; i++, j += 4) + { + data[j ] = Channels[0][i]; + data[j+1] = Channels[1][i]; + data[j+2] = Channels[2][i]; + data[j+3] = 255; + } + } + else + return SQE_R_BADFILE; + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + if(Channels) + { + for (u32 i = 0; i < NumChannels; i++) + delete Channels[i]; + + delete Channels; + } + + delete Alpha; + delete pal; + + Channels = 0; + Alpha = 0; + pal = 0; + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_psp/fmt_codec_psp_defs.h b/kernel/kls_psp/fmt_codec_psp_defs.h new file mode 100644 index 0000000..a03410e --- /dev/null +++ b/kernel/kls_psp/fmt_codec_psp_defs.h @@ -0,0 +1,249 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_psp +#define KSQUIRREL_CODEC_DEFS_psp + +static const u8 PSPSignature[32] = +{ + 0x50, 0x61, 0x69, 0x6E, 0x74, 0x20, 0x53, 0x68, 0x6F, 0x70, 0x20, 0x50, 0x72, 0x6F, 0x20, 0x49, + 0x6D, 0x61, 0x67, 0x65, 0x20, 0x46, 0x69, 0x6C, 0x65, 0x0A, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const u8 GenAttHead[4] = { 0x7E, 0x42, 0x4B, 0x00 }; + +typedef u8 ILubyte; +typedef u16 ILushort; +typedef u32 ILuint; +typedef s32 ILint; +typedef double ILdouble; + +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2002 by Denton Woods +// Last modified: 05/02/2002 <--Y2K Compliant! =] +// +// Filename: src-IL/include/il_psp.h +// +// Description: Reads a Paint Shop Pro file. +// +//----------------------------------------------------------------------------- + + +// Block identifiers +enum PSPBlockID { + PSP_IMAGE_BLOCK = 0, // (0) General Image Attributes Block (main) + PSP_CREATOR_BLOCK, // (1) Creator Data Block (main) + PSP_COLOR_BLOCK, // (2) Color Palette Block (main and sub) + PSP_LAYER_START_BLOCK, // (3) Layer Bank Block (main) + PSP_LAYER_BLOCK, // (4) Layer Block (sub) + PSP_CHANNEL_BLOCK, // (5) Channel Block (sub) + PSP_SELECTION_BLOCK, // (6) Selection Block (main) + PSP_ALPHA_BANK_BLOCK, // (7) Alpha Bank Block (main) + PSP_ALPHA_CHANNEL_BLOCK, // (8) Alpha Channel Block (sub) + PSP_COMPOSITE_IMAGE_BLOCK, // (9) Composite Image Block (sub) + PSP_EXTENDED_DATA_BLOCK, // (10) Extended Data Block (main) + PSP_TUBE_BLOCK, // (11) Picture Tube Data Block (main) + PSP_ADJUSTMENT_EXTENSION_BLOCK, // (12) Adjustment Layer Block (sub) + PSP_VECTOR_EXTENSION_BLOCK, // (13) Vector Layer Block (sub) + PSP_SHAPE_BLOCK, // (14) Vector Shape Block (sub) + PSP_PAINTSTYLE_BLOCK, // (15) Paint Style Block (sub) + PSP_COMPOSITE_IMAGE_BANK_BLOCK, // (16) Composite Image Bank (main) + PSP_COMPOSITE_ATTRIBUTES_BLOCK, // (17) Composite Image Attr. (sub) + PSP_JPEG_BLOCK, // (18) JPEG Image Block (sub) + PSP_LINESTYLE_BLOCK, // (19) Line Style Block (sub) + PSP_TABLE_BANK_BLOCK, // (20) Table Bank Block (main) + PSP_TABLE_BLOCK, // (21) Table Block (sub) + PSP_PAPER_BLOCK, // (22) Vector Table Paper Block (sub) + PSP_PATTERN_BLOCK, // (23) Vector Table Pattern Block (sub) +}; + + +// Bitmap type +enum PSPDIBType { + PSP_DIB_IMAGE = 0, // Layer color bitmap + PSP_DIB_TRANS_MASK, // Layer transparency mask bitmap + PSP_DIB_USER_MASK, // Layer user mask bitmap + PSP_DIB_SELECTION, // Selection mask bitmap + PSP_DIB_ALPHA_MASK, // Alpha channel mask bitmap + PSP_DIB_THUMBNAIL // Thumbnail bitmap +}; + +// Channel types +enum PSPChannelType { + PSP_CHANNEL_COMPOSITE = 0, // Channel of single channel bitmap + PSP_CHANNEL_RED, // Red channel of 24 bit bitmap + PSP_CHANNEL_GREEN, // Green channel of 24 bit bitmap + PSP_CHANNEL_BLUE // Blue channel of 24 bit bitmap +}; + +// Possible metrics used to measure resolution +enum PSP_METRIC { + PSP_METRIC_UNDEFINED = 0, // Metric unknown + PSP_METRIC_INCH, // Resolution is in inches + PSP_METRIC_CM // Resolution is in centimeters +}; + + +// Possible types of compression. +enum PSPCompression { + PSP_COMP_NONE = 0, // No compression + PSP_COMP_RLE, // RLE compression + PSP_COMP_LZ77, // LZ77 compression + PSP_COMP_JPEG // JPEG compression (only used by thumbnail and composite image) +}; + +// Picture tube placement mode. +enum TubePlacementMode { + tpmRandom, // Place tube images in random intervals + tpmConstant // Place tube images in constant intervals +}; + +// Picture tube selection mode. +enum TubeSelectionMode { + tsmRandom, // Randomly select the next image in tube to display + tsmIncremental, // Select each tube image in turn + tsmAngular, // Select image based on cursor direction + tsmPressure, // Select image based on pressure (from pressure-sensitive pad) + tsmVelocity // Select image based on cursor speed +}; + +// Extended data field types. +enum PSPExtendedDataID { + PSP_XDATA_TRNS_INDEX = 0 // Transparency index field +}; + +// Creator field types. +enum PSPCreatorFieldID { + PSP_CRTR_FLD_TITLE = 0, // Image document title field + PSP_CRTR_FLD_CRT_DATE, // Creation date field + PSP_CRTR_FLD_MOD_DATE, // Modification date field + PSP_CRTR_FLD_ARTIST, // Artist name field + PSP_CRTR_FLD_CPYRGHT, // Copyright holder name field + PSP_CRTR_FLD_DESC, // Image document description field + PSP_CRTR_FLD_APP_ID, // Creating app id field + PSP_CRTR_FLD_APP_VER, // Creating app version field +}; + +// Creator application identifiers. +enum PSPCreatorAppID { + PSP_CREATOR_APP_UNKNOWN = 0, // Creator application unknown + PSP_CREATOR_APP_PAINT_SHOP_PRO // Creator is Paint Shop Pro +}; + +// Layer types. +enum PSPLayerType { + PSP_LAYER_NORMAL = 0, // Normal layer + PSP_LAYER_FLOATING_SELECTION // Floating selection layer +}; + +struct PSPRECT +{ + ILuint x1,y1,x2,y2; +} PACKED; + +struct PSPHEAD +{ + char FileSig[32]; + ILushort MajorVersion; + ILushort MinorVersion; +} PACKED; + +struct BLOCKHEAD +{ + ILubyte HeadID[4]; + ILushort BlockID; + ILuint BlockLen; +} PACKED; + +struct GENATT_CHUNK +{ + ILint Width; + ILint Height; + ILdouble Resolution; + ILubyte ResMetric; + ILushort Compression; + ILushort BitDepth; + ILushort PlaneCount; + ILuint ColourCount; + ILubyte GreyscaleFlag; + ILuint SizeOfImage; + ILint ActiveLayer; + ILushort LayerCount; + ILuint GraphicContents; +} PACKED; + +struct LAYERINFO_CHUNK +{ + ILubyte LayerType; + PSPRECT ImageRect; + PSPRECT SavedImageRect; + ILubyte Opacity; + ILubyte BlendingMode; + ILubyte LayerFlags; + ILubyte TransProtFlag; + ILubyte LinkID; + PSPRECT MaskRect; + PSPRECT SavedMaskRect; + ILubyte MaskLinked; + ILubyte MaskDisabled; + ILubyte InvertMaskBlend; + ILushort BlendRange; + ILubyte SourceBlend1[4]; + ILubyte DestBlend1[4]; + ILubyte SourceBlend2[4]; + ILubyte DestBlend2[4]; + ILubyte SourceBlend3[4]; + ILubyte DestBlend3[4]; + ILubyte SourceBlend4[4]; + ILubyte DestBlend4[4]; + ILubyte SourceBlend5[4]; + ILubyte DestBlend5[4]; +} PACKED; + +struct LAYERBITMAP_CHUNK +{ + ILushort NumBitmaps; + ILushort NumChannels; +} PACKED; + +struct CHANNEL_CHUNK +{ + ILuint CompLen; + ILuint Length; + ILushort BitmapType; + ILushort ChanType; +} PACKED; + +struct ALPHAINFO_CHUNK +{ + PSPRECT AlphaRect; + PSPRECT AlphaSavedRect; +} PACKED; + +struct ALPHA_CHUNK +{ + ILushort BitmapCount; + ILushort ChannelCount; +} PACKED; + +#endif diff --git a/kernel/kls_pxr/Makefile.am b/kernel/kls_pxr/Makefile.am new file mode 100644 index 0000000..9f3d4d0 --- /dev/null +++ b/kernel/kls_pxr/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_pxr.la + +libkls_pxr_la_SOURCES = fmt_codec_pxr.cpp fmt_codec_pxr_defs.h + +libkls_pxr_la_LDFLAGS = ${SQ_RELEASE} + +libkls_pxr_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_pxr/fmt_codec_pxr.cpp b/kernel/kls_pxr/fmt_codec_pxr.cpp new file mode 100644 index 0000000..5fb1b9f --- /dev/null +++ b/kernel/kls_pxr/fmt_codec_pxr.cpp @@ -0,0 +1,173 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fmt_utils.h" +#include "ksquirrel-libs/fileio.h" + +#include "fmt_codec_pxr_defs.h" +#include "fmt_codec_pxr.h" + +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "../xpm/codec_pxr.xpm" + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.1.0"; + o->name = "Pxrar format"; + o->filter = "*.pxr "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pxr"; + o->pixmap = codec_pxr; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + read_error = false; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + u16 w, h; + u8 bppi; + + frs.seekg(416, ios::beg); + if(!frs.readK(&h, sizeof(u16))) return SQE_R_BADFILE; + if(!frs.readK(&w, sizeof(u16))) return SQE_R_BADFILE; + + frs.seekg(424, ios::beg); + if(!frs.readK(&bppi, sizeof(u8))) return SQE_R_BADFILE; + + fmt_image image; + + image.w = w; + image.h = h; + + if(bppi == 0x08) + image.bpp = 1; + else if(bppi == 0x0E) + image.bpp = 24; + else if(bppi == 0x0F) + image.bpp = 32; + else + return SQE_R_BADFILE; + + image.compression = "-"; + image.colorspace = fmt_utils::colorSpaceByBpp(image.bpp); + + frs.seekg(1024, ios::beg); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(im->bpp) + { + case 1: + { + u8 c; + + for(s32 i = 0;i < im->w;i++) + { + if(!frs.readK(&c, sizeof(u8))) return SQE_R_BADFILE; + + memset(scan+i, c, sizeof(RGB)); + } + } + break; + + case 24: + { + for(s32 i = 0;i < im->w;i++) + { + if(!frs.readK(&rgb, sizeof(RGB))) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + } + break; + + case 32: + { + if(!frs.readK(scan, im->w * sizeof(RGBA))) + return SQE_R_BADFILE; + } + break; + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_pxr/fmt_codec_pxr_defs.h b/kernel/kls_pxr/fmt_codec_pxr_defs.h new file mode 100644 index 0000000..047828b --- /dev/null +++ b/kernel/kls_pxr/fmt_codec_pxr_defs.h @@ -0,0 +1,25 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_pxr +#define KSQUIRREL_CODEC_DEFS_pxr + +#endif diff --git a/kernel/kls_ras/Makefile.am b/kernel/kls_ras/Makefile.am new file mode 100644 index 0000000..3bae1c6 --- /dev/null +++ b/kernel/kls_ras/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_ras.la + +libkls_ras_la_SOURCES = fmt_codec_ras.cpp fmt_codec_ras_defs.h + +libkls_ras_la_LDFLAGS = ${SQ_RELEASE} + +libkls_ras_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_ras/fmt_codec_ras.cpp b/kernel/kls_ras/fmt_codec_ras.cpp new file mode 100644 index 0000000..c932d9b --- /dev/null +++ b/kernel/kls_ras/fmt_codec_ras.cpp @@ -0,0 +1,361 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_ras_defs.h" +#include "fmt_codec_ras.h" + +#include "../xpm/codec_ras.xpm" + +/* + * + * The Sun Raster image file format is the native bitmap format of the Sun + * Microsystems UNIX platforms using the SunOS operating system. This format is + * capable of storing black-and-white, gray-scale, and color bitmapped data of any + * pixel depth. The use of color maps and a simple Run-Length data compression + * are also supported. Typically, most images found on a SunOS system are Sun + * Raster images, and this format is supported by most UNIX imaging applications. + * + */ + +bool fmt_readdata(ifstreamK &, u8 *, u32, bool); + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.6.3"; + o->name = "SUN Raster"; + o->filter = "*.ras "; + o->config = ""; + o->mime = "\x0059\x00A6\x006A\x0095"; + o->mimetype = "image/x-ras"; + o->pixmap = codec_ras; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + rle = false; + isRGB = false; + buf = NULL; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + if(!frs.be_getlong(&rfh.ras_magic)) return SQE_R_BADFILE; + if(!frs.be_getlong(&rfh.ras_width)) return SQE_R_BADFILE; + if(!frs.be_getlong(&rfh.ras_height)) return SQE_R_BADFILE; + if(!frs.be_getlong(&rfh.ras_depth)) return SQE_R_BADFILE; + if(!frs.be_getlong(&rfh.ras_length)) return SQE_R_BADFILE; + if(!frs.be_getlong(&rfh.ras_type)) return SQE_R_BADFILE; + if(!frs.be_getlong(&rfh.ras_maptype)) return SQE_R_BADFILE; + if(!frs.be_getlong(&rfh.ras_maplength)) return SQE_R_BADFILE; + + if(rfh.ras_magic != RAS_MAGIC) return SQE_R_BADFILE; + + if(rfh.ras_type != RAS_OLD && rfh.ras_type != RAS_STANDARD && rfh.ras_type != RAS_BYTE_ENCODED && rfh.ras_type != RAS_RGB && + rfh.ras_type != RAS_TIFF && rfh.ras_type != RAS_IFF && rfh.ras_type != RAS_EXPERIMENTAL) + return SQE_R_BADFILE; + else if(rfh.ras_type == RAS_EXPERIMENTAL) + return SQE_R_NOTSUPPORTED; + + image.w = rfh.ras_width; + image.h = rfh.ras_height; + image.bpp = rfh.ras_depth; + + switch(rfh.ras_maptype) + { + case RMT_NONE : + { + if (rfh.ras_depth < 24) + { + s32 numcolors = 1 << rfh.ras_depth, i; + + for (i = 0; i < numcolors; i++) + { + pal[i].r = (255 * i) / (numcolors - 1); + pal[i].g = (255 * i) / (numcolors - 1); + pal[i].b = (255 * i) / (numcolors - 1); + } + } + + break; + } + + case RMT_EQUAL_RGB: + { + s8 *g, *b; + + s32 numcolors = 1 << rfh.ras_depth; + + s8 r[3 * numcolors]; + + g = r + numcolors; + b = g + numcolors; + + if(!frs.readK(r, 3 * numcolors)) return SQE_R_BADFILE; + + for(s32 i = 0; i < numcolors; i++) + { + pal[i].r = r[i]; + pal[i].g = g[i]; + pal[i].b = b[i]; + } + break; + } + + case RMT_RAW: + { + s8 colormap[rfh.ras_maplength]; + + if(!frs.readK(colormap, rfh.ras_maplength)) return SQE_R_BADFILE; + break; + } + } + + switch(rfh.ras_type) + { + case RAS_OLD: + case RAS_STANDARD: + case RAS_TIFF: + case RAS_IFF: + break; + + case RAS_BYTE_ENCODED: + rle = true; + break; + + case RAS_RGB: + isRGB = true; + break; + } + + if(rfh.ras_depth == 1) + linelength = (short)((rfh.ras_width / 8) + (rfh.ras_width % 8 ? 1 : 0)); + else + linelength = (short)rfh.ras_width; + + fill = (linelength % 2) ? 1 : 0; + + buf = new u8 [rfh.ras_width * sizeof(RGB)]; + + if(!buf) + return SQE_R_NOMEMORY; + + image.compression = ((isRGB) ? "-":"RLE"); + image.colorspace = "RGB"; + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + u32 i; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(im->bpp) + { + case 1: + break; + + case 8: + if(!fmt_readdata(frs, buf, linelength, rle)) + return SQE_R_BADFILE; + + for(i = 0;i < rfh.ras_width;i++) + memcpy(scan+i, &pal[i], sizeof(RGB)); + + if(fill) + { + if(!fmt_readdata(frs, &fillchar, fill, rle)) + return SQE_R_BADFILE; + } + break; + + case 24: + { + u8 *b = buf; + + if(!fmt_readdata(frs, buf, rfh.ras_width * 3, rle)) + return SQE_R_BADFILE; + + if(isRGB) + for (i = 0; i < rfh.ras_width; i++) + { + scan[i].r = *b; + scan[i].g = *(b+1); + scan[i].b = *(b+2); + b += 3; + } + else + for (i = 0; i < rfh.ras_width; i++) + { + scan[i].r = *(b + 2); + scan[i].g = *(b + 1); + scan[i].b = *b; + b += 3; + } + + if(fill) + { + if(!fmt_readdata(frs, &fillchar, fill, rle)) + return SQE_R_BADFILE; + } + } + break; + + case 32: + { + u8 *b = buf; + + if(!fmt_readdata(frs, buf, rfh.ras_width * 4, rle)) + return SQE_R_BADFILE; + + if(isRGB) + for (i = 0; i < rfh.ras_width; i++) + { + scan[i].a = *b; + scan[i].r = *(b+1); + scan[i].g = *(b+2); + scan[i].b = *(b+3); + b += 4; + } + else + for (i = 0; i < rfh.ras_width; i++) + { + scan[i].r = *(b + 3); + scan[i].g = *(b + 2); + scan[i].b = *(b + 1); + scan[i].a = *b; + b += 4; + } + + if(fill) + { + if(!fmt_readdata(frs, &fillchar, fill, rle)) + return SQE_R_BADFILE; + } + + } + break; + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + delete [] buf; + buf = NULL; + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool fmt_readdata(ifstreamK &ff, u8 *_buf, u32 length, bool rle) +{ + u8 repchar, remaining = 0; + + if(rle) + { + while(length--) + { + if (remaining) + { + remaining--; + *(_buf++)= repchar; + } + else + { + if(!ff.readK(&repchar, 1)) return false; + + if(repchar == RESC) + { + if(!ff.readK(&remaining, 1)) return false; + + if (remaining == 0) + *(_buf++) = RESC; + else + { + if(!ff.readK(&repchar, 1)) return false; + *(_buf++) = repchar; + } + } + else + *(_buf++) = repchar; + } + } + } + else + { + if(!ff.readK(_buf, length)) return false; + + } + + return true; +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_ras/fmt_codec_ras_defs.h b/kernel/kls_ras/fmt_codec_ras_defs.h new file mode 100644 index 0000000..aca1829 --- /dev/null +++ b/kernel/kls_ras/fmt_codec_ras_defs.h @@ -0,0 +1,54 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_ras +#define KSQUIRREL_READ_IMAGE_ras + +struct RAS_HEADER +{ + u32 ras_magic; + u32 ras_width; + u32 ras_height; + u32 ras_depth; + u32 ras_length; + u32 ras_type; + u32 ras_maptype; + u32 ras_maplength; + +}PACKED; + +#define RAS_MAGIC 0x59A66A95 // Magic number for Sun rasterfiles + +#define RAS_OLD 0 // Old format (raw image in 68000 byte order) +#define RAS_STANDARD 1 // Raw image in 68000 byte order +#define RAS_BYTE_ENCODED 2 // Run-length encoding of bytes +#define RAS_RGB 3 // XRGB or RGB instead of XBGR or BGR +#define RAS_TIFF 4 // TIFF <-> standard rasterfile +#define RAS_IFF 5 // IFF (TAAC format) <-> standard rasterfile + +#define RAS_EXPERIMENTAL 0xffff // Reserved for testing + +#define RMT_NONE 0 // maplength is expected to be 0 +#define RMT_EQUAL_RGB 1 // red[maplength/3], green[maplength/3], blue[maplength/3] +#define RMT_RAW 2 // Raw colormap +#define RESC 128 // Run-length encoding escape character + +#endif diff --git a/kernel/kls_rawrgb/Makefile.am b/kernel/kls_rawrgb/Makefile.am new file mode 100644 index 0000000..a12c81e --- /dev/null +++ b/kernel/kls_rawrgb/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_rawrgb.la + +libkls_rawrgb_la_SOURCES = fmt_codec_rawrgb.cpp fmt_codec_rawrgb_defs.h + +libkls_rawrgb_la_LDFLAGS = ${SQ_RELEASE} + +libkls_rawrgb_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_rawrgb/fmt_codec_rawrgb.cpp b/kernel/kls_rawrgb/fmt_codec_rawrgb.cpp new file mode 100644 index 0000000..2379974 --- /dev/null +++ b/kernel/kls_rawrgb/fmt_codec_rawrgb.cpp @@ -0,0 +1,229 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_rawrgb_defs.h" +#include "fmt_codec_rawrgb.h" + +#include "../xpm/codec_rawrgb.xpm" + +/* + * + * This is a codec to read and write internal raw image format. + * This format has a simple header folowed by uncompressed image data in + * 24 or 32 bit format. Width, height and bit depth are integers (unsigned int, or u32). + * + * File structure: + * + * + * + * + * Example: + * + * [ 32][ 32][ 24] + * [RGB][RGB][RGB][RGB]... + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "1.0.0"; + o->name = "Raw uncompressed RGB image"; + o->filter = "*.rawrgb "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-rawrgb"; + o->pixmap = codec_rawrgb; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + u32 w, h, bpp; + frs.readK(&w, sizeof(u32)); + frs.readK(&h, sizeof(u32)); + frs.readK(&bpp, sizeof(u32)); + + if(bpp != 32 && bpp != 24) + return SQE_R_BADFILE; + + image.w = w; + image.h = h; + image.bpp = bpp; + image.compression = "-"; + image.colorspace = (bpp == 24 ? "RGB" : "RGBA"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + RGBA rgba; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + if(im->bpp == 32) + for(s32 i = 0;i < im->w;i++) + { + frs.readK(&rgba, sizeof(RGBA)); + memcpy(scan+i, &rgba, sizeof(RGBA)); + } + else + for(s32 i = 0;i < im->w;i++) + { + frs.readK(&rgb, sizeof(RGB)); + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + s32 bpp = 32; + + if(!fws.writeK(&writeimage.w, sizeof(s32))) return SQE_W_ERROR; + if(!fws.writeK(&writeimage.h, sizeof(s32))) return SQE_W_ERROR; + if(!fws.writeK(&bpp, sizeof(s32))) return SQE_W_ERROR; + + return SQE_OK; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + u8 *p, a; + + for(s32 j = 0;j < writeimage.w;j++) + { + p = (u8 *)(scan +j); + + fws.writeK(p, sizeof(u8)); + fws.writeK(p+1, sizeof(u8)); + fws.writeK(p+2, sizeof(u8)); + + a = (writeopt.alpha) ? *(p+3) : 255; + + if(!fws.writeK(&a, sizeof(u8))) return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("rawrgb"); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_rawrgb/fmt_codec_rawrgb_defs.h b/kernel/kls_rawrgb/fmt_codec_rawrgb_defs.h new file mode 100644 index 0000000..afe6292 --- /dev/null +++ b/kernel/kls_rawrgb/fmt_codec_rawrgb_defs.h @@ -0,0 +1,27 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_rawrgb +#define KSQUIRREL_READ_IMAGE_rawrgb + +// define constants here + +#endif diff --git a/kernel/kls_sct/Makefile.am b/kernel/kls_sct/Makefile.am new file mode 100644 index 0000000..826c167 --- /dev/null +++ b/kernel/kls_sct/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_sct.la + +libkls_sct_la_SOURCES = fmt_codec_sct.cpp fmt_codec_sct_defs.h + +libkls_sct_la_LDFLAGS = ${SQ_RELEASE} + +libkls_sct_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_sct/fmt_codec_sct.cpp b/kernel/kls_sct/fmt_codec_sct.cpp new file mode 100644 index 0000000..90048e4 --- /dev/null +++ b/kernel/kls_sct/fmt_codec_sct.cpp @@ -0,0 +1,232 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_sct_defs.h" +#include "fmt_codec_sct.h" + +#include "ksquirrel-libs/error.h" + +#include "../xpm/codec_sct.xpm" + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.2.2"; + o->name = "Scitex CT"; + o->filter = "*.sct *.ct "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-sct"; + o->pixmap = codec_sct; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + read_error = false; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 comment[0x50 + 1], sig[2]; + + if(!frs.readK(comment, sizeof(comment) - 1)) return SQE_R_BADFILE; + if(!frs.readK(sig, sizeof(sig))) return SQE_R_BADFILE; + + comment[0x50] = '\0'; + + frs.seekg(0x400, ios::beg); + + if(!frs.readK(&sct, sizeof(sct_header))) return SQE_R_BADFILE; + + sct.format = fmt_utils::konvertWord(sct.format); + + if(sct.format != SCT_FORMAT_RGB && sct.format != SCT_FORMAT_GRAY && sct.format != SCT_FORMAT_CMYK) + return SQE_R_BADFILE; + + if(sct.format == SCT_FORMAT_RGB && sct.channels != 3) + return SQE_R_BADFILE; + + if(sct.format == SCT_FORMAT_GRAY && sct.channels != 1) + return SQE_R_BADFILE; + + if(sct.format == SCT_FORMAT_CMYK && sct.channels != 4) + return SQE_R_BADFILE; + + if((sct.width[0] != '+' && sct.width[0] != '-') || (sct.height[0] != '+' && sct.height[0] != '-')) + return SQE_R_BADFILE; + + std::string buf; + + buf.assign(sct.width, sizeof(sct.width)); + + std::stringstream ss(buf); + + ss.setf(ios::hex); + + ss >> image.h; + + buf.assign(sct.height, sizeof(sct.height)); + + std::stringstream ss1(buf); + + ss1.setf(ios::hex); + + ss1 >> image.w; + + image.compression = "-"; + + switch(sct.format) + { + case SCT_FORMAT_RGB: + image.colorspace = "RGB"; + image.bpp = 24; + break; + + case SCT_FORMAT_GRAY: + image.colorspace = "Grayscale"; + image.bpp = 8; + break; + + case SCT_FORMAT_CMYK: + image.colorspace = "CMYK"; + image.bpp = 32; + break; + } + + fmt_metaentry mt; + + mt.group = "Comment"; + mt.data = comment; + + addmeta(mt); + + finfo.image.push_back(image); + + frs.seekg(0x800, ios::beg); + + return (frs.good()) ? SQE_OK : SQE_R_BADFILE; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + RGBA rgba; + u8 c, *p; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(sct.format) + { + case SCT_FORMAT_RGB: + for(s32 ch = 0;ch < 3;ch++) + for(s32 i = 0;i < im->w;i++) + { + if(!frs.readK(&c, sizeof(u8))) return SQE_R_BADFILE; + + p = (u8 *)(scan + i); + *(p + ch) = c; + } + break; + + case SCT_FORMAT_GRAY: + for(s32 i = 0;i < im->w;i++) + { + if(!frs.readK(&c, sizeof(c))) return SQE_R_BADFILE; + + (scan+i)->r = c; + (scan+i)->g = c; + (scan+i)->b = c; + } + break; + + case SCT_FORMAT_CMYK: + for(s32 ch = 0;ch < 4;ch++) + for(s32 i = 0;i < im->w;i++) + { + if(!frs.readK(&c, sizeof(u8))) return SQE_R_BADFILE; + + p = (u8 *)(scan + i); + *(p + ch) = c; + } + + for(s32 i = 0;i < im->w;i++) + { + scan[i].r = (scan[i].r * scan[i].a) >> 8; + scan[i].g = (scan[i].g * scan[i].a) >> 8; + scan[i].b = (scan[i].b * scan[i].a) >> 8; + scan[i].a = 255; + } + break; + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_sct/fmt_codec_sct_defs.h b/kernel/kls_sct/fmt_codec_sct_defs.h new file mode 100644 index 0000000..bffa9f2 --- /dev/null +++ b/kernel/kls_sct/fmt_codec_sct_defs.h @@ -0,0 +1,51 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_sct +#define KSQUIRREL_CODEC_DEFS_sct + +#define SCT_UNITS_MM 0 +#define SCT_UNITS_INCH 1 + +#define SCT_FORMAT_RGB 7 +#define SCT_FORMAT_GRAY 8 +#define SCT_FORMAT_CMYK 0xf + +// +// SCT header starts from offset 0x400. Before it +// comes comment string (50 symbols, offset 0x0) +// and signature "CT" (offset 0x50). +// +// Image pixels are stored from file offset 0x800 +// + +struct sct_header +{ + u8 units; // units (0=MM,1=INCH) + u8 channels; // number of channels + u16 format; // format (7=RGB, 8=GREYSCALE, 0xF=CMYK) + s8 wh_units[28]; // width and height in units stored as a Scitex FP (not used) + s8 width[12]; // width in pixels stored as 12 digits of text including sign ("%+012d"). + s8 height[12]; // height in pixels stored as 12 digits of text including sign ("%+012d"). + +}PACKED; + +#endif diff --git a/kernel/kls_sgi/Makefile.am b/kernel/kls_sgi/Makefile.am new file mode 100644 index 0000000..6284c4c --- /dev/null +++ b/kernel/kls_sgi/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_sgi.la + +libkls_sgi_la_SOURCES = fmt_codec_sgi.cpp fmt_codec_sgi_defs.h + +libkls_sgi_la_LDFLAGS = ${SQ_RELEASE} + +libkls_sgi_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_sgi/fmt_codec_sgi.cpp b/kernel/kls_sgi/fmt_codec_sgi.cpp new file mode 100644 index 0000000..0ec1ea4 --- /dev/null +++ b/kernel/kls_sgi/fmt_codec_sgi.cpp @@ -0,0 +1,341 @@ +/* This file is part of SQuirrel (http://ksquirrel.sf.net) libraries + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fmt_utils.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" + +#include "fmt_codec_sgi_defs.h" +#include "fmt_codec_sgi.h" + +#include "../xpm/codec_sgi.xpm" + +/* + * + * The SGI image file format is actually part of the SGI image library found on + * all Silicon Graphics machines. SGI image files may store black-and-white (.BW + * extension), color RGB (.RGB extension), + * or color RGB with alpha channel data (.RGBA extension) + * images. SGI image files may also have the generic extension .SGI as well. + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.9.4"; + o->name = "SGI Format"; + o->filter = "*.rgb *.rgba *.bw"; + o->config = ""; + o->mime = "\001\332.[\001\002]"; + o->mimetype = "image/x-rgb"; + o->pixmap = codec_sgi; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + starttab = NULL; + lengthtab = NULL; + channel[0] = channel[1] = channel[2] = channel[3] = NULL; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + if(!frs.be_getshort(&sfh.Magik)) return SQE_R_BADFILE; + if(!frs.readK(&sfh.StorageFormat, 1)) return SQE_R_BADFILE; + if(!frs.readK(&sfh.bpc, 1)) return SQE_R_BADFILE; + if(!frs.be_getshort(&sfh.Dimensions)) return SQE_R_BADFILE; + if(!frs.be_getshort(&sfh.x)) return SQE_R_BADFILE; + if(!frs.be_getshort(&sfh.y)) return SQE_R_BADFILE; + if(!frs.be_getshort(&sfh.z)) return SQE_R_BADFILE; + if(!frs.be_getlong(&sfh.pixmin)) return SQE_R_BADFILE; + if(!frs.be_getlong(&sfh.pixmax)) return SQE_R_BADFILE; + if(!frs.be_getlong(&sfh.dummy)) return SQE_R_BADFILE; + + if(!frs.readK(sfh.name, sizeof(sfh.name))) return SQE_R_BADFILE; + + if(!frs.be_getlong(&sfh.ColormapID)) return SQE_R_BADFILE; + + if(!frs.readK(&sfh.dummy2, sizeof(sfh.dummy2))) return SQE_R_BADFILE; + + image.w = sfh.x; + image.h = sfh.y; + image.bpp = sfh.bpc * sfh.z * 8; + + if(image.bpp == 32) image.hasalpha = true; + + if(sfh.Magik != 474 || (sfh.StorageFormat != 0 && sfh.StorageFormat != 1) || (sfh.Dimensions != 1 && sfh.Dimensions != 2 && sfh.Dimensions != 3) || (sfh.bpc != 1 && sfh.bpc != 2)) + return SQE_R_BADFILE; + + if(sfh.bpc == 2 || sfh.ColormapID > 0) + return SQE_R_NOTSUPPORTED; + + for(s32 i = 0;i < 4;i++) + { + channel[i] = new s8 [sfh.x]; + + if(!channel[i]) + return SQE_R_NOMEMORY; + } + + if(sfh.StorageFormat == 1) + { + s32 sz = sfh.y * sfh.z, i; + lengthtab = new u32 [sz]; + starttab = new u32 [sz]; + + if(!lengthtab || !starttab) + return SQE_R_NOMEMORY; + + frs.seekg(512, ios::beg); + + for(i = 0;i < sz;i++) + if(!frs.be_getlong(&starttab[i])) + return SQE_R_BADFILE; + + for(i = 0;i < sz;i++) + if(!frs.be_getlong(&lengthtab[i])) + return SQE_R_BADFILE; + } + + rle_row = 0; + + if(strlen(sfh.name)) + { + fmt_metaentry mt; + + mt.group = "Image Name"; + mt.data = sfh.name; + + addmeta(mt); + } + + image.needflip = true; + image.compression = (sfh.StorageFormat ? "RLE" : "-"); + image.colorspace = fmt_utils::colorSpaceByBpp(image.bpp); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + const s32 sz = sfh.x; + s32 i = 0, j = 0; + s32 len; + fstream::pos_type pos; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + s8 bt; + + memset(channel[3], 255, sz); + + switch(sfh.z) + { + case 1: + { + if(sfh.StorageFormat) + { + j = 0; + + frs.seekg(starttab[rle_row], ios::beg); + len = lengthtab[rle_row]; + + for(;;) + { + s8 count; + + if(!frs.readK(&bt, 1)) return SQE_R_BADFILE; + count = bt&0x7f; + + if(!count) break; + + if(bt & 0x80) + while(count--) + { + if(!frs.readK(&channel[0][j], 1)) return SQE_R_BADFILE; + + j++; + + if(!len--) goto ex1; + } + else + { + if(!frs.readK(&bt, 1)) return SQE_R_BADFILE; + + if(!len--) goto ex1; + + while(count--) + channel[0][j++] = bt; + } + } + ex1: + len = len; // some stuff: get rid of compile warning + + rle_row++; + } + else + { + if(!frs.readK(channel[0], sz)) return SQE_R_BADFILE; + } + + memcpy(channel[1], channel[0], sz); + memcpy(channel[2], channel[0], sz); + } + break; + + + case 3: + case 4: + { + if(sfh.StorageFormat) + { + for(i = 0;i < sfh.z;i++) + { + j = 0; + + frs.seekg(starttab[rle_row + i*im->h], ios::beg); + len = lengthtab[rle_row + i*im->h]; + + for(;;) + { + s8 count; + + if(!frs.readK(&bt, 1)) return SQE_R_BADFILE; + + count = bt&0x7f; + + if(!count) break; + + if(bt & 0x80) + while(count--) + { + if(!frs.readK(&channel[i][j], 1)) return SQE_R_BADFILE; + j++; + if(!len--) goto ex; + } + else + { + if(!frs.readK(&bt, 1)) return SQE_R_BADFILE; + + if(!len--) goto ex; + + while(count--) + channel[i][j++] = bt; + } + } + ex: + len = len; // some stuff: get rid of compile warning + } + rle_row++; + } + else + { + if(!frs.readK(channel[0], sz)) return SQE_R_BADFILE; + + pos = frs.tellg(); + frs.seekg(im->w * (im->h - 1), ios::cur); + if(!frs.readK(channel[1], sz)) return SQE_R_BADFILE; + + frs.seekg(im->w * (im->h - 1), ios::cur); + if(!frs.readK(channel[2], sz)) return SQE_R_BADFILE; + + frs.seekg(im->w * (im->h - 1), ios::cur); + if(!frs.readK(channel[3], sz)) return SQE_R_BADFILE; + + frs.seekg(pos); + } + + } + break; + } + + for(i = 0;i < sz;i++) + { + scan[i].r = channel[0][i]; + scan[i].g = channel[1][i]; + scan[i].b = channel[2][i]; + scan[i].a = channel[3][i]; + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + delete [] starttab; + starttab = NULL; + + delete [] lengthtab; + lengthtab = NULL; + + for(s32 i = 0;i < 4;i++) + { + delete [] channel[i]; + channel[i] = NULL; + } + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_sgi/fmt_codec_sgi_defs.h b/kernel/kls_sgi/fmt_codec_sgi_defs.h new file mode 100644 index 0000000..3573d4e --- /dev/null +++ b/kernel/kls_sgi/fmt_codec_sgi_defs.h @@ -0,0 +1,50 @@ +/* This file is part of SQuirrel (http://ksquirrel.sf.net) libraries + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_sgi +#define KSQUIRREL_READ_IMAGE_sgi + +struct SGI_HEADER +{ + u16 Magik; /* should be 474 */ + u8 StorageFormat; /* 1 == RLE, 0 = Verbatim */ + u8 bpc; /* 1|2 */ + u16 Dimensions; /* 1|2|3 1==1channle+1scanline, 2==1channle+some scanlines, 3==number of channels */ + u16 x; + u16 y; + u16 z; + u32 pixmin; + u32 pixmax; + u32 dummy; + char name[80]; /* ascii string */ + u32 ColormapID; + + /* 0=Normal + 1=Dither. RGB==3:3:2 per byte, 1 channel + 2=Screen. Obsolete + 3=Colormap. Has ONLY colormap, nothing else. + */ + + u8 dummy2[404]; + +}PACKED; + +#endif diff --git a/kernel/kls_sun/Makefile.am b/kernel/kls_sun/Makefile.am new file mode 100644 index 0000000..b7b3b16 --- /dev/null +++ b/kernel/kls_sun/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_sun.la + +libkls_sun_la_SOURCES = fmt_codec_sun.cpp fmt_codec_sun_defs.h + +libkls_sun_la_LDFLAGS = ${SQ_RELEASE} + +libkls_sun_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_sun/fmt_codec_sun.cpp b/kernel/kls_sun/fmt_codec_sun.cpp new file mode 100644 index 0000000..d12612d --- /dev/null +++ b/kernel/kls_sun/fmt_codec_sun.cpp @@ -0,0 +1,235 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fmt_utils.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" + +#include "fmt_codec_sun_defs.h" +#include "fmt_codec_sun.h" + +#include "../xpm/codec_sun.xpm" + +/* + * + * The icons found in the Open Look and SunView Graphical User Interfaces available + * on the Sun Microsystems UNIX-based platforms are stored in a simple format known + * as the Sun Icon format + * + */ + +static const RGB mono[2] = { RGB(255,255,255), RGB(0,0,0) }; + +static const char * lex[5] = +{ + "Format_version", + "Width", + "Height", + "Depth", + "Valid_bits_per_item" +}; + +// internal function +bool scanForLex(ifstreamK &f, bool digit = false); + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.9.1"; + o->name = "SUN Icon"; + o->filter = "*.sun "; + o->config = ""; + o->mime = "/\\* Format_"; + o->mimetype = "image/x-sun"; + o->pixmap = codec_sun; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[128]; + u32 var, ver; + + u32 * pointers[5] = + { + &ver, + (u32 *)&image.w, + (u32 *)&image.h, + (u32 *)&image.bpp, + &validbits + }; + + for(s32 i = 0;i < 5;i++) + { + if(!scanForLex(frs)) + return SQE_R_BADFILE; + + frs.getline(str, 127, '='); + + if(!frs.good()) + return SQE_R_BADFILE; + + if(strncmp(lex[i], str, strlen(lex[i]))) + return SQE_R_BADFILE; + + frs >> var; + + *(pointers[i]) = var; + } + + if(ver != SUN_ICON_VERSION) + return SQE_R_BADFILE; + + // ignore images with width != 64 or height != 64 + // TODO: get rid of this if() + if(image.w != 64 || image.h != 64) + return SQE_R_NOTSUPPORTED; + + if(image.bpp != 1) + return SQE_R_NOTSUPPORTED; + + if(validbits != 16 && validbits != 32) + return SQE_R_BADFILE; + + if(!scanForLex(frs, true)) + return SQE_R_BADFILE; + + image.compression = "-"; + image.colorspace = "Monochrome"; + + finfo.image.push_back(image); + + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + RGBA rgba; + u32 var, i = 0, j = 0; + s32 decoded = 0; + u8 indexes[32]; + bool lasthex; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + line++; + + while(decoded < im->w) + { + if(!frs.readCHex(var)) + return SQE_R_BADFILE; + + if(validbits == 16) + fmt_utils::expandMono2Byte(var, indexes); + else + fmt_utils::expandMono4Byte(var, indexes); + + decoded += validbits; + + lasthex = (decoded >= im->w && line == im->h-1); + + if(!scanForLex(frs, true) && !lasthex) + return SQE_R_BADFILE; + + j = i + validbits; + + for(u32 k = 0;i < j;i++,k++) + memcpy(scan+i, mono+indexes[k], sizeof(RGB)); + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool scanForLex(ifstreamK &f, bool digit) +{ + u8 c; + bool found = false; + + while(f.readK(&c, sizeof(u8))) + { +// cout << "Read " << c << endl; + + if((!digit && isalpha(c)) || (digit && isdigit(c))) + { + found = true; + break; + } + } + + if(found) + f.seekg(-1, ios::cur); + + return found; +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_sun/fmt_codec_sun_defs.h b/kernel/kls_sun/fmt_codec_sun_defs.h new file mode 100644 index 0000000..bab52a6 --- /dev/null +++ b/kernel/kls_sun/fmt_codec_sun_defs.h @@ -0,0 +1,27 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_sun +#define KSQUIRREL_READ_IMAGE_sun + +#define SUN_ICON_VERSION 1 + +#endif diff --git a/kernel/kls_svg/Makefile.am b/kernel/kls_svg/Makefile.am new file mode 100644 index 0000000..2bbc93d --- /dev/null +++ b/kernel/kls_svg/Makefile.am @@ -0,0 +1,19 @@ +INCLUDES = -I../include -I../kls_png + +bin_SCRIPTS = ksquirrel-libs-svg2png + +pkglib_LTLIBRARIES = libkls_svg.la + +libkls_svg_la_SOURCES = fmt_codec_png.cpp fmt_codec_png_defs.h + +libkls_svg_la_LDFLAGS = ${SQ_RELEASE} + +libkls_svg_la_LIBADD = ${SQ_LOCAL_RPATH} -L../kls_png/ksquirrel-libs-png -lksquirrel-libs-png + +AM_CXXFLAGS = -DCODEC_SVG -DCODEC_ANOTHER -DSVG_UI=\"${pkgdatadir}/libkls_svg.so.ui\" -DRSVG=\"${RSVG}\" -DSVG2PNG=\"${bindir}/ksquirrel-libs-svg2png\" + +EXTRA_DIST = libkls_svg.so.ui ksquirrel-libs-svg2png.in + +install-data-am: + $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) + $(INSTALL) --mode=0644 libkls_svg.so.ui $(DESTDIR)$(pkgdatadir)/libkls_svg.so.ui diff --git a/kernel/kls_svg/fmt_codec_png.cpp b/kernel/kls_svg/fmt_codec_png.cpp new file mode 100644 index 0000000..66c43ee --- /dev/null +++ b/kernel/kls_svg/fmt_codec_png.cpp @@ -0,0 +1,655 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs-png/png.h" + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_png_defs.h" +#include "fmt_codec_png.h" + +#if defined CODEC_SVG || defined CODEC_DICOM +#include +#include +#include +#include +#endif + +#ifdef CODEC_SVG +#include "../xpm/codec_svg.xpm" +#elif defined CODEC_DICOM +#include "../xpm/codec_dicom.xpm" +#else +#include "../xpm/codec_png.xpm" +#endif + +/* + * + * PNG (pronounced "ping") is a bitmap file format used to transmit and + * store bitmapped images. PNG supports the capability of storing up to + * 16 bits (gray-scale) or 48 bits (truecolor) per pixel, and up to 16 bits + * of alpha data. It handles the progressive display + * of image data and the storage of gamma, + * transparency and textual information, and it uses an efficient and + * lossless form of data compression. + * + */ + +inline bool MALLOC_ROWS(png_bytep **A, const int RB, const int H) +{ + *A = (png_bytep*)malloc(H * sizeof(png_bytep*)); + + if(!*A) + return false; + + for(s32 row = 0; row < H; row++) + (*A)[row] = 0; + + for(s32 row = 0; row < (s32)H; row++) + { + (*A)[row] = (png_bytep)malloc(RB); + + if(!(*A)[row]) + return false; + + memset((*A)[row], 0, RB); + } + + return true; +} + +inline void FREE_ROWS(png_bytep **A, const int H) +{ + if(*A) + { + for(s32 i = 0;i < H;i++) + { + if((*A)[i]) + free((*A)[i]); + } + + free(*A); + *A = 0; + } +} + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ +#ifdef CODEC_SVG + o->version = "0.1.2"; + o->name = "Scalable Vector Graphics"; + o->filter = "*.svg *.svgz "; + o->config = std::string(SVG_UI); // SVG_UI comes from Makefile.am + o->mime = ""; + o->mimetype = "image/svg+xml"; + o->pixmap = codec_svg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DICOM + o->version = "1.1.3"; + o->name = "DICOM"; + o->filter = "*.dcm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-dicom"; + o->pixmap = codec_dicom; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "1.1.3"; + o->name = "Portable Network Graphics"; + o->filter = "*.png "; + o->config = ""; + o->mime = "\x0089\x0050\x004E\x0047\x000D\x000A\x001A\x000A"; + o->mimetype = "image/png"; + o->pixmap = codec_png; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#ifdef CODEC_ANOTHER +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_int; + val.iVal = 1; + + m_settings["scale"] = val; +} +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + png_ptr = 0; + info_ptr = 0; + fptr = 0; + frame = 0; + prev = 0; + cur = 0; + zerror = false; + +#ifdef CODEC_SVG + int status; + + fmt_settings::iterator it = m_settings.find("scale"); + + // percents / 100 + int scale = (it == m_settings.end() || (*it).second.type != settings_value::v_int) + ? 1 : (*it).second.iVal; + + if(scale < 1 || scale > 10) + scale = 1; + + char z[32]; + snprintf(z, 32, "%d", scale); + + pid_t pid = fork(); + + if(!pid) + { + execlp(SVG2PNG, SVG2PNG, "--binary", RSVG, "--input", file.c_str(), "--output", tmp.c_str(), "-z", z, (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DICOM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(DICOM, DICOM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#else + fptr = fopen(file.c_str(), "rb"); +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + if((png_ptr = my_png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0)) == NULL) + { + zerror = true; + return SQE_R_NOMEMORY; + } + + if((info_ptr = my_png_create_info_struct(png_ptr)) == NULL) + { + zerror = true; + return SQE_R_NOMEMORY; + } + + if(setjmp(png_jmpbuf(png_ptr))) + { + zerror = true; + return SQE_R_BADFILE; + } + + my_png_init_io(png_ptr, fptr); + my_png_read_info(png_ptr, info_ptr); + my_png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, (int*)0, (int*)0); + + img.w = next_frame_width = width; + img.h = next_frame_height = height; + img.bpp = bit_depth; + + if(img.bpp == 16) + my_png_set_strip_16(png_ptr); + + if(img.bpp < 8) + my_png_set_packing(png_ptr); + + if(color_type == PNG_COLOR_TYPE_GRAY && img.bpp < 8) + my_png_set_gray_1_2_4_to_8(png_ptr); + + if(color_type == PNG_COLOR_TYPE_PALETTE) + my_png_set_palette_to_rgb(png_ptr); + + if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + my_png_set_gray_to_rgb(png_ptr); + + if(my_png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + my_png_set_tRNS_to_alpha(png_ptr); + + my_png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + + number_passes = my_png_set_interlace_handling(png_ptr); + + my_png_read_update_info(png_ptr, info_ptr); + + finfo.animated = !!my_png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL); + + frames = finfo.animated ? my_png_get_num_frames(png_ptr, info_ptr) : 1; + + if(!frames) return SQE_R_BADFILE; + + img.interlaced = number_passes > 1; + img.passes = finfo.animated ? 1 : number_passes; + + if(finfo.animated) + { + if(!MALLOC_ROWS(&prev, width * sizeof(RGBA), height)) + return SQE_R_NOMEMORY; + + if(!MALLOC_ROWS(&cur, width * sizeof(RGBA), height)) + return SQE_R_NOMEMORY; + } + + std::string color_; + + img.hasalpha = (color_type & PNG_COLOR_MASK_ALPHA); + + switch((color_type & ~PNG_COLOR_MASK_ALPHA)) + { + case PNG_COLOR_TYPE_RGB: color_ = "RGB"; break; + case PNG_COLOR_TYPE_PALETTE: color_ = "Color indexed"; break; + case PNG_COLOR_TYPE_GRAY: color_ = "Grayscale"; break; + + default: + color_ = "Unknown"; + } + + if(img.hasalpha) + color_ += " with ALPHA"; + + img.compression = "Deflate method 8, 32K window"; + img.colorspace = color_; + if(!finfo.animated) img.delay = 0; + +#ifdef PNG_TEXT_SUPPORTED + png_textp lines = info_ptr->text; + + if(!lines || !info_ptr->num_text) + return SQE_OK; + + for(s32 i = 0;i < info_ptr->num_text;i++) + { + fmt_metaentry mt; + + mt.group = lines[i].key; + mt.data = lines[i].text; + + addmeta(mt); + } +#endif + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage == frames) + return SQE_NOTOK; + + if(setjmp(png_jmpbuf(png_ptr))) + { + zerror = true; + return SQE_R_BADFILE; + } + + if(finfo.animated) + { + if(currentImage) + { + if(next_frame_dispose_op == PNG_DISPOSE_OP_BACKGROUND) + { + for(u32 j = next_frame_y_offset,i = 0;i < next_frame_height;j++,i++) + memset(cur[j]+next_frame_x_offset*sizeof(RGBA), 0, next_frame_width * sizeof(RGBA)); + } + else if(next_frame_dispose_op == PNG_DISPOSE_OP_PREVIOUS) + { + for(u32 i = 0;i < height;i++) + memcpy(cur[i], prev[i], width*sizeof(RGBA)); + } + else // next_frame_dispose_op == PNG_DISPOSE_OP_NONE + { + } + + for(u32 i = 0;i < height;i++) + memcpy(prev[i], cur[i], width*sizeof(RGBA)); + } + else if(my_png_get_first_frame_is_hidden(png_ptr, info_ptr)) + { + if(!MALLOC_ROWS(&frame, width * sizeof(RGBA), height)) + return SQE_R_NOMEMORY; + + my_png_read_frame_head(png_ptr, info_ptr); + my_png_read_image(png_ptr, frame); + + FREE_ROWS(&frame, height); + + frames--; + + if(frames == 1) + { + my_png_read_frame_head(png_ptr, info_ptr); + finfo.animated = false; + img.passes = number_passes; + finfo.image.push_back(img); + return SQE_OK; + } + else if(!frames) + return SQE_R_BADFILE; // oops? + } + + FREE_ROWS(&frame, next_frame_height); + + my_png_read_frame_head(png_ptr, info_ptr); + + if(my_png_get_valid(png_ptr, info_ptr, PNG_INFO_fcTL)) + { + my_png_get_next_frame_fcTL(png_ptr, info_ptr, + &next_frame_width, &next_frame_height, + &next_frame_x_offset, &next_frame_y_offset, + &next_frame_delay_num, &next_frame_delay_den, + &next_frame_dispose_op, &next_frame_blend_op); + } + else + { + next_frame_width = width; + next_frame_height = height; + next_frame_x_offset = 0; + next_frame_y_offset = 0; + next_frame_dispose_op = PNG_DISPOSE_OP_BACKGROUND; + next_frame_blend_op = PNG_BLEND_OP_SOURCE; + } + + if(!next_frame_delay_den) next_frame_delay_den = 100; + + img.delay = (s32)(((double)next_frame_delay_num / next_frame_delay_den) * 1000); + + if(next_frame_width + next_frame_x_offset > width || next_frame_height + next_frame_y_offset > height) + return SQE_R_BADFILE; + + if(!MALLOC_ROWS(&frame, next_frame_width * sizeof(RGBA), next_frame_height)) + return SQE_R_NOMEMORY; + + my_png_read_image(png_ptr, frame); + + // copy all pixel values including alpha + if(!currentImage || next_frame_blend_op == PNG_BLEND_OP_SOURCE) + { + for(u32 j = next_frame_y_offset,i = 0;i < next_frame_height;j++,i++) + memcpy(cur[j]+next_frame_x_offset*sizeof(RGBA), frame[i], next_frame_width * sizeof(RGBA)); + } + else // over + { + RGBA *src, *dst; + + for(u32 j = next_frame_y_offset,i = 0;i < next_frame_height;j++,i++) + { + src = (RGBA *)frame[i]; + dst = (RGBA *)(cur[j]+next_frame_x_offset*sizeof(RGBA)); + u32 k = next_frame_width; + + while(k--) + { + // fully transparent foreground + if(src->a == 0) + ; + else if(src->a == 255 || dst->a == 0) + *dst = *src; + else // composite + { + dst->r = ((src->a * (src->r - dst->r))>>8) + dst->r; + dst->g = ((src->a * (src->g - dst->g))>>8) + dst->g; + dst->b = ((src->a * (src->b - dst->b))>>8) + dst->b; + //dst->a = ((src->a * (src->a - dst->a))>>8) + dst->a; + } + + src++; + dst++; + } + } + } + } + + finfo.image.push_back(img); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + fmt_image *im = image(currentImage); + + line++; + + if(zerror || setjmp(png_jmpbuf(png_ptr))) + { + zerror = true; + return SQE_R_BADFILE; + } + + if(finfo.animated) + memcpy(scan, cur[line], im->w * sizeof(RGBA)); + else + my_png_read_row(png_ptr, (png_bytep)scan, png_bytep_NULL); + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(png_ptr) my_png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); + + if(fptr) fclose(fptr); + + FREE_ROWS(&frame, next_frame_height); + FREE_ROWS(&prev, height); + FREE_ROWS(&cur, height); + + finfo.meta.clear(); + finfo.image.clear(); +} + +#ifdef CODEC_PNG + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = true; + opt->compression_scheme = CompressionInternal; + opt->compression_min = 1; + opt->compression_max = 9; + opt->compression_def = 7; + opt->passes = 8; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + m_png_ptr = 0; + m_info_ptr = 0; + m_fptr = 0; + m_zerror = false; + + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + m_fptr = fopen(file.c_str(), "wb"); + + if(!m_fptr) + return SQE_W_NOFILE; + + m_png_ptr = my_png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + + if(!m_png_ptr) + { + m_zerror = true; + return SQE_W_NOMEMORY; + } + + m_info_ptr = my_png_create_info_struct(m_png_ptr); + + if(!m_info_ptr) + { + m_zerror = true; + return SQE_W_NOMEMORY; + } + + if(setjmp(png_jmpbuf(m_png_ptr))) + { + m_zerror = true; + return SQE_W_ERROR; + } + + my_png_init_io(m_png_ptr, m_fptr); + + my_png_set_IHDR(m_png_ptr, m_info_ptr, writeimage.w, writeimage.h, 8, PNG_COLOR_TYPE_RGB_ALPHA, + ((writeopt.interlaced) ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE), + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_color_8 sig_bit; + + sig_bit.red = 8; + sig_bit.green = 8; + sig_bit.blue = 8; + sig_bit.alpha = 8; + + my_png_set_sBIT(m_png_ptr, m_info_ptr, &sig_bit); + + s32 factor = (writeopt.compression_level < 1 || writeopt.compression_level > 9) ? 1 : writeopt.compression_level; + + my_png_set_compression_level(m_png_ptr, factor); + + my_png_write_info(m_png_ptr, m_info_ptr); + + my_png_set_shift(m_png_ptr, &sig_bit); + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + my_png_set_swap(m_png_ptr); + + my_png_set_packswap(m_png_ptr); + + my_png_set_interlace_handling(m_png_ptr); + + return SQE_OK; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + if(m_zerror || setjmp(png_jmpbuf(m_png_ptr))) + { + m_zerror = true; + return SQE_W_ERROR; + } + + m_row_pointer = (png_bytep)scan; + + my_png_write_rows(m_png_ptr, &m_row_pointer, 1); + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + if(m_png_ptr && !m_zerror) my_png_write_end(m_png_ptr, m_info_ptr); + if(m_png_ptr) my_png_destroy_write_struct(&m_png_ptr, &m_info_ptr); + if(m_fptr) fclose(m_fptr); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("png"); +} + +#endif + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_svg/fmt_codec_png_defs.h b/kernel/kls_svg/fmt_codec_png_defs.h new file mode 100644 index 0000000..afef4ac --- /dev/null +++ b/kernel/kls_svg/fmt_codec_png_defs.h @@ -0,0 +1,27 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_png +#define KSQUIRREL_READ_IMAGE_png + +// Nothing to define at this moment :) + +#endif diff --git a/kernel/kls_svg/ksquirrel-libs-svg2png.in b/kernel/kls_svg/ksquirrel-libs-svg2png.in new file mode 100644 index 0000000..b921e6d --- /dev/null +++ b/kernel/kls_svg/ksquirrel-libs-svg2png.in @@ -0,0 +1,20 @@ +#!/bin/sh + +kls_svg_i="" +kls_svg_o="" +kls_svg_bin="" +kls_svg_params="" + +while [ "$1" ] ; do + + case "$1" in + "--input") kls_svg_i="$2" shift ;; + "--output") kls_svg_o="$2" shift ;; + "--binary") kls_svg_bin="$2" shift ;; + *) kls_svg_params="$kls_svg_params $1" ;; + esac + +shift +done + +$kls_svg_bin $kls_svg_params "$kls_svg_i" > "$kls_svg_o" \ No newline at end of file diff --git a/kernel/kls_svg/libkls_svg.so.ui b/kernel/kls_svg/libkls_svg.so.ui new file mode 100644 index 0000000..cd454c9 --- /dev/null +++ b/kernel/kls_svg/libkls_svg.so.ui @@ -0,0 +1,120 @@ + +Form1 + + + Form1 + + + + 0 + 0 + 287 + 63 + + + + Form1 + + + + unnamed + + + 0 + + + + no_spinBox + + + x + + + 10 + + + 1 + + + 1 + + + + + scale + + + 1 + + + 10 + + + 2 + + + 1 + + + Horizontal + + + Below + + + 1 + + + + + layout1 + + + + unnamed + + + 0 + + + + textLabel2 + + + <b>Scaling factor:</b> + + + + + line1 + + + HLine + + + Sunken + + + Horizontal + + + + + + + + + scale + valueChanged(int) + no_spinBox + setValue(int) + + + no_spinBox + valueChanged(int) + scale + setValue(int) + + + + diff --git a/kernel/kls_tga/Makefile.am b/kernel/kls_tga/Makefile.am new file mode 100644 index 0000000..c7b8423 --- /dev/null +++ b/kernel/kls_tga/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_tga.la + +libkls_tga_la_SOURCES = fmt_codec_tga.cpp fmt_codec_tga_defs.h + +libkls_tga_la_LDFLAGS = ${SQ_RELEASE} + +libkls_tga_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_tga/fmt_codec_tga.cpp b/kernel/kls_tga/fmt_codec_tga.cpp new file mode 100644 index 0000000..8a79229 --- /dev/null +++ b/kernel/kls_tga/fmt_codec_tga.cpp @@ -0,0 +1,411 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_tga_defs.h" +#include "fmt_codec_tga.h" + +#include "../xpm/codec_tga.xpm" + +/* + * + * The TGA (Truevision Graphics Adapter) format + * is used widely in paint, graphics, and imaging applications that + * require the storage of image data containing up to 32 bits per + * pixel. TGA is associated with the Truevision + * product line of Targa, Vista, NuVista, and Targa 2000 graphics + * adapters for the PC and Macintosh, all of which can capture + * NTSC and/or PAL video image signals and store them in a digital frame buffer. + * For this reason, TGA has also become popular in the world of + * still-video editing. + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.7.2"; + o->name = "TarGA"; + o->filter = "*.tga "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-targa"; + o->pixmap = codec_tga; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + pal_entr = 0; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + if(!frs.readK(&tfh, sizeof(TGA_FILEHEADER))) return SQE_R_BADFILE; + + image.w = tfh.ImageSpecW; + image.h = tfh.ImageSpecH; + image.bpp = tfh.ImageSpecDepth; + pal_entr = 0; + + if(tfh.IDlength) + { + s8 data[tfh.IDlength]; + + if(!frs.readK(data, tfh.IDlength)) return SQE_R_BADFILE; + + fmt_metaentry mt; + + mt.group = "TGA image identification field"; + + mt.data = data; + + addmeta(mt); + } + + if(tfh.ColorMapType) + { + pal_entr = tfh.ColorMapSpecLength; + +// if((pal = (RGB*)calloc(pal_entr, sizeof(RGB))) == 0) +// return SQE_R_NOMEMORY; + +// s8 sz = tfh.ColorMapSpecEntrySize; + s32 i; +// u16 word; + + for(i = 0;i < pal_entr;i++) + { + /*if(sz==24)*/ if(!frs.readK(pal+i, sizeof(RGB))) return SQE_R_BADFILE; +/* alpha ingored *//*else if(sz==32) { fread(finfo.pal+i, sizeof(RGB), 1, fptr); fgetc(fptr); } + else if(sz==16) + { + fread(&word, 2, 1, fptr); + (finfo.pal)[i].b = (word&0x1f) << 3; + (finfo.pal)[i].g = ((word&0x3e0) >> 5) << 3; + (finfo.pal)[i].r = ((word&0x7c00)>>10) << 3; + }*/ + + } + } +// else +// pal = 0; + + if(tfh.ImageType == 0) + return SQE_R_BADFILE; + + std::string comp, type; + + fliph = (bool)(tfh.ImageSpecDescriptor & 0x10); + image.needflip = !(bool)(tfh.ImageSpecDescriptor & 0x20); + image.hasalpha = (image.bpp == 32); + + switch(tfh.ImageType) + { + case 1: + comp = "-"; + type = "Color indexed"; + break; + + case 2: + comp = "-"; + type = (( image.bpp == 32) ? "RGBA":"RGB"); + break; + + case 3: + comp = "-"; + type = "Monochrome"; + break; + + case 9: + comp = "RLE"; + type = "Color indexed"; + break; + + case 10: + comp = "RLE"; + type = (( image.bpp == 32) ? "RGBA":"RGB"); + break; + + case 11: + comp = "RLE"; + type = "Monochrome"; + break; + } + + image.compression = comp; + image.colorspace = type; + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + s32 j, counter = 0; + RGB rgb; + RGBA rgba; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(tfh.ImageType) + { + case 0: + break; + + case 1: + { + } + break; + + case 2: + { + if(tfh.ImageSpecDepth==24) + { + for(j = 0;j < im->w;j++) + { + if(!frs.readK(&rgb, sizeof(RGB))) return SQE_R_BADFILE; + + (scan+counter)->r = rgb.b; + (scan+counter)->g = rgb.g; + (scan+counter)->b = rgb.r; + counter++; + } + } + else if(tfh.ImageSpecDepth==32) + { + for(j = 0;j < im->w;j++) + { + if(!frs.readK(&rgba, sizeof(RGBA))) return SQE_R_BADFILE; + + (scan+counter)->r = rgba.b; + (scan+counter)->g = rgba.g; + (scan+counter)->b = rgba.r; + counter++; + } + } + else if(tfh.ImageSpecDepth==16) + { + u16 word; + + for(j = 0;j < im->w;j++) + { + if(!frs.readK(&word, 2)) return SQE_R_BADFILE; + + scan[counter].b = (word&0x1f) << 3; + scan[counter].g = ((word&0x3e0) >> 5) << 3; + scan[counter++].r = ((word&0x7c00)>>10) << 3; + } + } + } + break; + + case 3: + break; + + // RLE + color mapped + case 9: + break; + + // RLE + true color + case 10: + { + u8 bt, count; + ushort counter = 0, word; + RGBA rgba; + + for(;;) + { + if(!frs.readK(&bt, 1)) return SQE_R_BADFILE; + + count = (bt&127) + 1; + + // RLE packet + if(bt >= 128) + { + switch(im->bpp) + { + case 16: + if(!frs.readK(&word, 2)) return SQE_R_BADFILE; + + rgb.b = (word&0x1f) << 3; + rgb.g = ((word&0x3e0) >> 5) << 3; + rgb.r = ((word&0x7c00)>>10) << 3; + + for(j = 0;j < count;j++) + { + memcpy(scan+(counter++), &rgb, sizeof(RGB)); + if(counter >= im->w-1) goto lts; + } + break; + + case 24: + if(!frs.readK(&rgb, sizeof(RGB))) return SQE_R_BADFILE; + + for(j = 0;j < count;j++) + { + (scan+counter)->r = rgb.b; + (scan+counter)->g = rgb.g; + (scan+counter)->b = rgb.r; + counter++; + + if(counter >= im->w-1) goto lts; + } + break; + + case 32: + if(!frs.readK(&rgba, sizeof(RGBA))) return SQE_R_BADFILE; + + for(j = 0;j < count;j++) + { + (scan+counter)->r = rgba.b; + (scan+counter)->g = rgba.g; + (scan+counter)->b = rgba.r; + counter++; + + if(counter >= im->w-1) goto lts; + } + break; + } + } + else // Raw packet + { + switch(im->bpp) + { + case 16: + + for(j = 0;j < count;j++) + { + if(!frs.readK(&word, 2)) return SQE_R_BADFILE; + + rgb.b = (word&0x1f) << 3; + rgb.g = ((word&0x3e0) >> 5) << 3; + rgb.r = ((word&0x7c00)>>10) << 3; + + memcpy(scan+(counter++), &rgb, sizeof(RGB)); + if(counter >= im->w-1) goto lts; + } + break; + + case 24: + for(j = 0;j < count;j++) + { + if(!frs.readK(&rgb, sizeof(RGB))) return SQE_R_BADFILE; + + (scan+counter)->r = rgb.b; + (scan+counter)->g = rgb.g; + (scan+counter)->b = rgb.r; + counter++; + + if(counter >= im->w-1) goto lts; + } + break; + + case 32: + for(j = 0;j < count;j++) + { + if(!frs.readK(&rgba, sizeof(RGBA))) return SQE_R_BADFILE; + + (scan+counter)->r = rgba.b; + (scan+counter)->g = rgba.g; + (scan+counter)->b = rgba.r; + counter++; + if(counter >= im->w-1) goto lts; + } + break; + } + } + } + } + lts: + break; + + // RLE + B&W + case 11: + break; + } + + if(fliph) + { + RGBA t; + s32 ww = im->w; + + for(j = 0;j < ww / 2;j++) + { + t = *(scan+j); + *(scan+j) = *(scan+ww-j-1); + *(scan+ww-j-1) = t; + } + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_tga/fmt_codec_tga_defs.h b/kernel/kls_tga/fmt_codec_tga_defs.h new file mode 100644 index 0000000..4cc7f52 --- /dev/null +++ b/kernel/kls_tga/fmt_codec_tga_defs.h @@ -0,0 +1,70 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_tga +#define KSQUIRREL_READ_IMAGE_tga + +struct TGA_FILEHEADER +{ + u8 IDlength; + u8 ColorMapType; /* 1==we have colormap, 0==no */ + u8 ImageType; + /* 0==no image data + 1==uncompressed+color map + 2==uncompressed+true color + 3==uncompressed+B&W + 9==RLE+color map + 10==RLE+true color + 11==RLE+B&W + */ + u16 ColorMapSpecFirstEntryIndex; + u16 ColorMapSpecLength; + u8 ColorMapSpecEntrySize; /* 15,16,24,32 */ + u16 ImageSpecX; + u16 ImageSpecY; + u16 ImageSpecW; + u16 ImageSpecH; + u8 ImageSpecDepth; /* 8 or 16 or 24 or 32 */ + u8 ImageSpecDescriptor; /* 7 6 5 4 3 2 1 0 */ + +}PACKED; + +struct TGA_IMAGEDATA +{ + u8 *ID; /* length of this == TGA_FILEHEADER::IDlength */ + u8 *ColorMapData; /* -//- */ + u8 *Image; /* widthxheigth pixels */ + +}PACKED; + +struct TGA_FOOTER +{ + u32 ExtensionAreaOffset; + u32 DeveloperDirectoryOffset; + u8 Signature[16]; /* "TRUEVISION-XFILE" */ + u8 punct; /* '.' */ + u8 TGAnull; /* 0x0 */ + +}PACKED; + +/* we'll skip "developer area" & "extension area", we don't need to read them. */ + +#endif diff --git a/kernel/kls_tiff/Makefile.am b/kernel/kls_tiff/Makefile.am new file mode 100644 index 0000000..822a862 --- /dev/null +++ b/kernel/kls_tiff/Makefile.am @@ -0,0 +1,17 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_tiff.la + +libkls_tiff_la_SOURCES = fmt_codec_tiff.cpp fmt_codec_tiff_defs.h + +libkls_tiff_la_LDFLAGS = ${SQ_RELEASE} + +libkls_tiff_la_LIBADD = ${SQ_LOCAL_RPATH} -ltiff + +EXTRA_DIST = libkls_tiff.so.ui + +install-data-am: + $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) + $(INSTALL) --mode=0644 libkls_tiff.so.ui $(DESTDIR)$(pkgdatadir)/libkls_tiff.so.ui + +AM_CXXFLAGS = -DTIFF_UI=\"${pkgdatadir}/libkls_tiff.so.ui\" diff --git a/kernel/kls_tiff/fmt_codec_tiff.cpp b/kernel/kls_tiff/fmt_codec_tiff.cpp new file mode 100644 index 0000000..e22cb70 --- /dev/null +++ b/kernel/kls_tiff/fmt_codec_tiff.cpp @@ -0,0 +1,298 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fmt_utils.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" + +#include "fmt_codec_tiff_defs.h" +#include "fmt_codec_tiff.h" + +#include "../xpm/codec_tiff.xpm" + +/* + * + * The TIFF specification was originally released in + * 1986 by Aldus Corporation as a standard method of storing + * black-and-white images created by scanners and desktop publishing + * applications. This first public release of TIFF was + * the third major revision of the TIFF format, and + * although it was not assigned a specific version number, this release + * may be thought of as TIFF Revision 3.0. The first + * widely used revision of TIFF, 4.0, was released in + * April 1987. TIFF 4.0 added support for uncompressed + * RGB color images and was quickly followed by the + * release of TIFF Revision 5.0 in August + * 1988. TIFF 5.0 was the first revision to add the + * capability of storing palette color images and support for the + * LZW compression algorithm. TIFF 6.0 was released in June + * 1992 and added support for CMYK and YCbCr color + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{ + compr[COMPRESSION_NONE] = "None"; + compr[COMPRESSION_CCITTRLE] = "CCITTRLE"; + compr[COMPRESSION_CCITTFAX3] = "CCITTFAX3"; + compr[COMPRESSION_CCITT_T4] = "CCITT_T4"; + compr[COMPRESSION_CCITTFAX4] = "CCITTFAX4"; + compr[COMPRESSION_CCITT_T6] = "CCITT_T6"; + compr[COMPRESSION_LZW] = "LZW"; + compr[COMPRESSION_OJPEG] = "OJPEG"; + compr[COMPRESSION_JPEG] = "JPEG"; + compr[COMPRESSION_NEXT] = "NEXT"; + compr[COMPRESSION_CCITTRLEW] = "CCITTRLEW"; + compr[COMPRESSION_PACKBITS] = "PACKBITS"; + compr[COMPRESSION_THUNDERSCAN] = "THUNDERSCAN"; + compr[COMPRESSION_IT8CTPAD] = "IT8CTPAD"; + compr[COMPRESSION_IT8LW] = "IT8LW"; + compr[COMPRESSION_IT8MP] = "IT8MP"; + compr[COMPRESSION_IT8BL] = "IT8BL"; + compr[COMPRESSION_PIXARFILM] = "PIXARFILM"; + compr[COMPRESSION_PIXARLOG] = "PIXARLOG"; + compr[COMPRESSION_DEFLATE] = "DEFLATE"; + compr[COMPRESSION_ADOBE_DEFLATE] = "Adobe DEFLATE"; + compr[COMPRESSION_DCS] = "DCS"; + compr[COMPRESSION_JBIG] = "JBIG"; + compr[COMPRESSION_SGILOG] = "SGILOG"; + compr[COMPRESSION_SGILOG24] = "SGILOG24"; + compr[COMPRESSION_JP2000] = "JP2000"; +} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "1.0.1"; + o->name = "Tagged Image File Format"; + o->filter = "*.tif *.tiff "; + o->config = std::string(TIFF_UI); + o->mime = ""; + o->mimetype = "image/tiff"; + o->pixmap = codec_tiff; + o->readable = true; + o->canbemultiple = true; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +} + +void fmt_codec::fill_default_settings() +{ + settings_value val; + + val.type = settings_value::v_int; + val.iVal = 1; + + m_settings["pages"] = val; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + currentImage = -1; + + if((ftiff = TIFFOpen(file.c_str(), "r")) == NULL) + return SQE_R_BADFILE; + + TIFFSetWarningHandler(NULL); + TIFFSetErrorHandler(NULL); + + finfo.animated = false; + + fmt_settings::iterator it = m_settings.find("pages"); + + pages = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(pages < 1 || pages > 1000) + pages = 1; + + dircount = 0; + + while(TIFFReadDirectory(ftiff)) + dircount++; + + TIFFSetDirectory(ftiff, 0); + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage == pages) + return SQE_NOTOK; + + if(dircount) + { + if(currentImage == dircount) + return SQE_NOTOK; + } + else + if(currentImage) + return SQE_NOTOK; + + if(dircount != 1 && dircount != 0) + if(!TIFFReadDirectory(ftiff)) + return SQE_R_BADFILE; + + if(currentImage) + TIFFRGBAImageEnd(&img); + + fmt_image image; + + s32 bps, spp; + + TIFFGetField(ftiff, TIFFTAG_IMAGEWIDTH, &image.w); + TIFFGetField(ftiff, TIFFTAG_IMAGELENGTH, &image.h); + + memset(&img, 0, sizeof(TIFFRGBAImage)); + + TIFFRGBAImageBegin(&img, ftiff, 1, 0); + + bps = img.bitspersample; + spp = img.samplesperpixel; + + s16 cmp; + TIFFGetField(ftiff, TIFFTAG_COMPRESSION, &cmp); + std::map::iterator it = compr.find(cmp); + + image.bpp = bps * spp; + image.compression = (it == compr.end() ? "Unknown" : (*it).second); + image.hasalpha = true; + image.colorspace = fmt_utils::colorSpaceByBpp(image.bpp); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + fmt_image *im = image(currentImage); + const s32 W = im->w * sizeof(RGBA); + + uint32 buf[W]; + + TIFFRGBAImageGet(&img, buf, im->w, 1); + + memcpy(scan, buf, W); + + img.row_offset++; + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + TIFFRGBAImageEnd(&img); + TIFFClose(ftiff); + + finfo.meta.clear(); + finfo.image.clear(); +} + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionRLE; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + out = TIFFOpen(file.c_str(), "w"); + + if(!out) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + TIFFSetField(out, TIFFTAG_IMAGEWIDTH, writeimage.w); + TIFFSetField(out, TIFFTAG_IMAGELENGTH, writeimage.h); + TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 4); + TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + TIFFSetField(out, TIFFTAG_COMPRESSION, (writeopt.compression_scheme == CompressionRLE ? COMPRESSION_PACKBITS : COMPRESSION_NONE)); + TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(out, (uint32) -1)); + + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + ++line; + + if(TIFFWriteScanline(out, (u8 *)scan, line, 0) < 0) + return SQE_W_ERROR; + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + TIFFClose(out); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("tiff"); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_tiff/fmt_codec_tiff_defs.h b/kernel/kls_tiff/fmt_codec_tiff_defs.h new file mode 100644 index 0000000..bc625a1 --- /dev/null +++ b/kernel/kls_tiff/fmt_codec_tiff_defs.h @@ -0,0 +1,27 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_tiff +#define KSQUIRREL_READ_IMAGE_tiff + +// Nothing to define + +#endif diff --git a/kernel/kls_tiff/libkls_tiff.so.ui b/kernel/kls_tiff/libkls_tiff.so.ui new file mode 100644 index 0000000..c7275da --- /dev/null +++ b/kernel/kls_tiff/libkls_tiff.so.ui @@ -0,0 +1,135 @@ + +Form1 + + + Form1 + + + + 0 + 0 + 313 + 74 + + + + Form1 + + + + unnamed + + + 0 + + + + layout1 + + + + unnamed + + + 0 + + + + textLabel2 + + + <b>Read no more than ... pages:</b> + + + + + line1 + + + HLine + + + Sunken + + + Horizontal + + + + + + + pages + + + 1 + + + 1000 + + + Horizontal + + + Below + + + 40 + + + + + no_pages + + + 1000 + + + 1 + + + + + layout1_2 + + + + unnamed + + + 0 + + + + line1_2 + + + HLine + + + Sunken + + + Horizontal + + + + + + + + + pages + valueChanged(int) + no_pages + setValue(int) + + + no_pages + valueChanged(int) + pages + setValue(int) + + + + diff --git a/kernel/kls_ttf/Makefile.am b/kernel/kls_ttf/Makefile.am new file mode 100644 index 0000000..10d2efe --- /dev/null +++ b/kernel/kls_ttf/Makefile.am @@ -0,0 +1,19 @@ +SUBDIRS = ftview + +INCLUDES = -I../include -Iftview @SQ_FT_CFLAGS@ + +bin_PROGRAMS = ksquirrel-libs-ttf2pnm + +ksquirrel_libs_ttf2pnm_SOURCES = ttf2pnm.cpp ftcommon.cpp + +ksquirrel_libs_ttf2pnm_LDADD = @SQ_FT_LDFLAGS@ -Lftview -lftview + +pkglib_LTLIBRARIES = libkls_ttf.la + +libkls_ttf_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_ttf_la_LDFLAGS = ${SQ_RELEASE} + +libkls_ttf_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DCODEC_TTF -DTTF2PNM=\"${bindir}/ksquirrel-libs-ttf2pnm\" diff --git a/kernel/kls_ttf/fmt_codec_pnm.cpp b/kernel/kls_ttf/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_ttf/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_ttf/fmt_codec_pnm_defs.h b/kernel/kls_ttf/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_ttf/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_ttf/ftcommon.cpp b/kernel/kls_ttf/ftcommon.cpp new file mode 100644 index 0000000..d162452 --- /dev/null +++ b/kernel/kls_ttf/ftcommon.cpp @@ -0,0 +1,1333 @@ +/****************************************************************************/ +/* */ +/* The FreeType project -- a free and portable quality TrueType renderer. */ +/* */ +/* Copyright 2005, 2006 by */ +/* D. Turner, R.Wilhelm, and W. Lemberg */ +/* */ +/* */ +/* ftcommon.c - common routines for the FreeType demo programs. */ +/* */ +/****************************************************************************/ +#include +#include +#include + +#include +#include FT_FREETYPE_H + +#include FT_CACHE_H +#include FT_CACHE_MANAGER_H + +#include FT_BITMAP_H + +#include "ftcommon.h" + +#include +#include +#include +#include + + FT_Error error; + + /* PanicZ */ + void + PanicZ( const char * ) + { + /*fprintf( stderr, "%s\n error = 0x%04x\n", message, error );*/ + exit( 1 ); + } + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** DISPLAY-SPECIFIC DEFINITIONS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + +#define DIM_X 600 +#define DIM_Y 450 + + grBitmap* + FTDemo_Display_New(void) + { + grBitmap *bit = (grBitmap *)malloc(sizeof(grBitmap)); + + if(!bit) + return NULL; + + bit->mode = gr_pixel_mode_rgb24; + bit->width = DIM_X; + bit->rows = DIM_Y; + bit->grays = 256; + + grNewBitmap(bit->mode, bit->grays, bit->width, bit->rows, bit); + + grSetGlyphGamma(1.0); + + return bit; + } + + + void + FTDemo_Display_Done(grBitmap *bit) + { + grDoneBitmap(bit); + } + + void + FTDemo_Display_Clear(grBitmap *bit) + { + int image_size = bit->width * bit->rows * 3; + + memset(bit->buffer, 255, image_size); + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** FREETYPE-SPECIFIC DEFINITIONS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + +#define FLOOR( x ) ( (x) & -64 ) +#define CEIL( x ) ( ( (x) + 63 ) & -64 ) +#define ROUND( x ) ( ( (x) + 32 ) & -64 ) +#define TRUNC( x ) ( (x) >> 6 ) + + + + static + const char* file_suffixes[] = + { + ".ttf", + ".ttc", + ".otf", + ".pfa", + ".pfb", + 0 + }; + + + /*************************************************************************/ + /* */ + /* The face requester is a function provided by the client application */ + /* to the cache manager, whose role is to translate an `abstract' face */ + /* ID into a real FT_Face object. */ + /* */ + /* In this program, the face IDs are simply pointers to TFont objects. */ + /* */ + static FT_Error + my_face_requester( FTC_FaceID face_id, + FT_Library lib, + FT_Pointer request_data, + FT_Face* aface ) + { + PFont font = (PFont)face_id; + + FT_UNUSED( request_data ); + + if ( font->file_address != NULL ) + error = FT_New_Memory_Face( lib, (FT_Byte*)font->file_address, font->file_size, + font->face_index, aface ); + else + error = FT_New_Face( lib, + font->filepathname, + font->face_index, + aface ); + if ( !error ) + { + const char* suffix_rchr; + char orig[4]; + + suffix_rchr = strrchr( font->filepathname, '.' ); + char* suffix = new char[strlen(font->filepathname) + 1]; + strcpy(suffix, suffix_rchr); + + if ( suffix && ( strcasecmp( suffix, ".pfa" ) == 0 || + strcasecmp( suffix, ".pfb" ) == 0 ) ) + { + suffix++; + + memcpy( orig, suffix, 4 ); + memcpy( suffix, "afm", 4 ); + FT_Attach_File( *aface, font->filepathname ); + + memcpy( suffix, "pfm", 4 ); + FT_Attach_File( *aface, font->filepathname ); + memcpy( suffix, orig, 4 ); + } + + if ( (*aface)->charmaps ) + (*aface)->charmap = (*aface)->charmaps[font->cmap_index]; + } + + return error; + } + + + FTDemo_Handle* + FTDemo_New( FT_Encoding encoding ) + { + FTDemo_Handle* handle; + + + handle = (FTDemo_Handle *)malloc( sizeof( FTDemo_Handle ) ); + if ( !handle ) + return NULL; + + memset( handle, 0, sizeof( FTDemo_Handle ) ); + + error = FT_Init_FreeType( &handle->library ); + if ( error ) + PanicZ( "could not initialize FreeType" ); + + error = FTC_Manager_New( handle->library, 0, 0, 0, + my_face_requester, 0, &handle->cache_manager ); + if ( error ) + PanicZ( "could not initialize cache manager" ); + + error = FTC_SBitCache_New( handle->cache_manager, &handle->sbits_cache ); + if ( error ) + PanicZ( "could not initialize small bitmaps cache" ); + + error = FTC_ImageCache_New( handle->cache_manager, &handle->image_cache ); + if ( error ) + PanicZ( "could not initialize glyph image cache" ); + + error = FTC_CMapCache_New( handle->cache_manager, &handle->cmap_cache ); + if ( error ) + PanicZ( "could not initialize charmap cache" ); + + + FT_Bitmap_New( &handle->bitmap ); + + handle->encoding = encoding; + + handle->hinted = 1; + handle->antialias = 1; + handle->use_sbits = 1; + handle->low_prec = 0; + handle->autohint = 0; + handle->lcd_mode = 0; + + handle->use_sbits_cache = 1; + + /* string_init */ + memset( handle->string, 0, sizeof( TGlyph ) * MAX_GLYPHS ); + handle->string_length = 0; + handle->string_reload = 1; + + return handle; + } + + + void + FTDemo_Done( FTDemo_Handle* handle ) + { + int i; + + + for ( i = 0; i < handle->max_fonts; i++ ) + { + if ( handle->fonts[i] ) + { + if ( handle->fonts[i]->filepathname ) + free( (void*)handle->fonts[i]->filepathname ); + free( handle->fonts[i] ); + } + } + free( handle->fonts ); + + /* string_done */ + for ( i = 0; i < MAX_GLYPHS; i++ ) + { + PGlyph glyph = handle->string + i; + + + if ( glyph->image ) + FT_Done_Glyph( glyph->image ); + } + + FT_Bitmap_Done( handle->library, &handle->bitmap ); + FTC_Manager_Done( handle->cache_manager ); + FT_Done_FreeType( handle->library ); + + free( handle ); + } + + + FT_Error + FTDemo_Install_Font( FTDemo_Handle* handle, + const char* filepath ) + { + static char filename[1024 + 5]; + int i, len, num_faces; + FT_Face face; + + + len = strlen( filepath ); + if ( len > 1024 ) + len = 1024; + + strncpy( filename, filepath, len ); + filename[len] = 0; + + error = FT_New_Face( handle->library, filename, 0, &face ); + +#ifndef macintosh + /* could not open the file directly; we will now try various */ + /* suffixes like `.ttf' or `.pfb' */ + if ( error ) + { + const char** suffix; + char* p; + int found = 0; + + suffix = file_suffixes; + p = filename + len - 1; + + while ( p >= filename && *p != '\\' && *p != '/' ) + { + if ( *p == '.' ) + break; + + p--; + } + + /* no suffix found */ + if ( p < filename || *p != '.' ) + p = filename + len; + + for ( suffix = file_suffixes; suffix[0]; suffix++ ) + { + /* try with current suffix */ + strcpy( p, suffix[0] ); + + error = FT_New_Face( handle->library, filename, 0, &face ); + if ( !error ) + { + found = 1; + + break; + } + } + + /* really couldn't open this file */ + if ( !found ) + return error; + } +#endif /* !macintosh */ + + /* allocate new font object */ + num_faces = face->num_faces; + for ( i = 0; i < num_faces; i++ ) + { + PFont font; + + + if ( i > 0 ) + { + error = FT_New_Face( handle->library, filename, i, &face ); + if ( error ) + continue; + } + + if ( handle->encoding != FT_ENCODING_NONE ) + { + error = FT_Select_Charmap( face, handle->encoding ); + if ( error ) + { + FT_Done_Face( face ); + return error; + } + } + + font = (PFont)malloc( sizeof ( *font ) ); + + font->filepathname = (char*)malloc( strlen( filename ) + 1 ); + strcpy( (char*)font->filepathname, filename ); + + font->face_index = i; + font->cmap_index = face->charmap ? FT_Get_Charmap_Index( face->charmap ) + : 0; + + if ( handle->preload ) + { + FILE* file = fopen( filename, "rb" ); + size_t file_size; + + if ( file == NULL ) /* shouldn't happen */ + { + free( font ); + return FT_Err_Invalid_Argument; + } + + fseek( file, 0, SEEK_END ); + file_size = ftell( file ); + fseek( file, 0, SEEK_SET ); + + font->file_address = malloc( file_size ); + fread( font->file_address, 1, file_size, file ); + + font->file_size = file_size; + + fclose( file ); + } + else + { + font->file_address = NULL; + font->file_size = 0; + } + + switch ( handle->encoding ) + { + case FT_ENCODING_NONE: + font->num_indices = face->num_glyphs; + break; + + case FT_ENCODING_UNICODE: + font->num_indices = 0x110000L; + break; + + case FT_ENCODING_MS_SYMBOL: + case FT_ENCODING_ADOBE_LATIN_1: + case FT_ENCODING_ADOBE_STANDARD: + case FT_ENCODING_ADOBE_EXPERT: + case FT_ENCODING_ADOBE_CUSTOM: + case FT_ENCODING_APPLE_ROMAN: + font->num_indices = 0x100L; + break; + + default: + font->num_indices = 0x10000L; + } + + FT_Done_Face( face ); + face = NULL; + + if ( handle->max_fonts == 0 ) + { + handle->max_fonts = 16; + handle->fonts = (PFont*)calloc( handle->max_fonts, + sizeof ( PFont ) ); + } + else if ( handle->num_fonts >= handle->max_fonts ) + { + handle->max_fonts *= 2; + handle->fonts = (PFont*)realloc( handle->fonts, + handle->max_fonts * + sizeof ( PFont ) ); + + memset( &handle->fonts[handle->num_fonts], 0, + ( handle->max_fonts - handle->num_fonts ) * + sizeof ( PFont ) ); + } + + handle->fonts[handle->num_fonts++] = font; + } + + return FT_Err_Ok; + } + + + void + FTDemo_Set_Current_Font( FTDemo_Handle* handle, + PFont font ) + { + handle->current_font = font; + handle->image_type.face_id = (FTC_FaceID)font; + + handle->string_reload = 1; + } + + + void + FTDemo_Set_Current_Size( FTDemo_Handle* handle, + int pixel_size ) + { + if ( pixel_size > 0xFFFF ) + pixel_size = 0xFFFF; + + handle->image_type.width = (FT_UShort)pixel_size; + handle->image_type.height = (FT_UShort)pixel_size; + + handle->string_reload = 1; + } + + void + FTDemo_Set_Preload( FTDemo_Handle* handle, + int preload ) + { + handle->preload = !!preload; + } + + void + FTDemo_Set_Current_Pointsize( FTDemo_Handle* handle, + int point_size, + int res ) + { + FTDemo_Set_Current_Size( handle, ( point_size * res + 36 ) / 72 ); + } + + + void + FTDemo_Update_Current_Flags( FTDemo_Handle* handle ) + { + FT_UInt32 flags, target; + + flags = FT_LOAD_DEFAULT; /* really 0 */ + + flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; + + if ( handle->autohint ) + flags |= FT_LOAD_FORCE_AUTOHINT; + + if ( !handle->use_sbits ) + flags |= FT_LOAD_NO_BITMAP; + + if ( handle->hinted ) + { + target = 0; + + if ( handle->antialias ) + { + switch ( handle->lcd_mode ) + { + case LCD_MODE_LIGHT: + target = FT_LOAD_TARGET_LIGHT; + break; + + case LCD_MODE_RGB: + case LCD_MODE_BGR: + target = FT_LOAD_TARGET_LCD; + break; + + case LCD_MODE_VRGB: + case LCD_MODE_VBGR: + target = FT_LOAD_TARGET_LCD_V; + break; + + default: + target = FT_LOAD_TARGET_NORMAL; + } + } + else + target = FT_LOAD_TARGET_MONO; + + flags |= target; + } + else + flags |= FT_LOAD_NO_HINTING; + + handle->image_type.flags = flags; + handle->string_reload = 1; + } + + + FT_UInt + FTDemo_Get_Index( FTDemo_Handle* handle, + FT_UInt32 charcode ) + { + FTC_FaceID face_id = handle->image_type.face_id; + PFont font = handle->current_font; + + + return FTC_CMapCache_Lookup( handle->cmap_cache, face_id, + font->cmap_index, charcode ); + } + + + FT_Error + FTDemo_Get_Size( FTDemo_Handle* handle, + FT_Size* asize ) + { + FTC_ScalerRec scaler; + FT_Size size; + + scaler.face_id = handle->image_type.face_id; + scaler.width = handle->image_type.width; + scaler.height = handle->image_type.height; + scaler.pixel = 1; + + error = FTC_Manager_LookupSize( handle->cache_manager, &scaler, &size ); + + if ( !error ) + *asize = size; + + return error; + } + + + FT_Error + FTDemo_Glyph_To_Bitmap( FTDemo_Handle* handle, + FT_Glyph glyf, + grBitmap* target, + int* left, + int* top, + int* x_advance, + int* y_advance, + FT_Glyph* aglyf ) + { + FT_BitmapGlyph bitmap; + FT_Bitmap* source; + + + *aglyf = NULL; + + error = FT_Err_Ok; + + if ( glyf->format == FT_GLYPH_FORMAT_OUTLINE ) + { + FT_Render_Mode render_mode = FT_RENDER_MODE_MONO; + + + if ( handle->antialias ) + { + if ( handle->lcd_mode == 0 ) + render_mode = FT_RENDER_MODE_NORMAL; + else if ( handle->lcd_mode == 1 ) + render_mode = FT_RENDER_MODE_LIGHT; + else if ( handle->lcd_mode <= 3 ) + render_mode = FT_RENDER_MODE_LCD; + else + render_mode = FT_RENDER_MODE_LCD_V; + } + + /* render the glyph to a bitmap, don't destroy original */ + error = FT_Glyph_To_Bitmap( &glyf, render_mode, NULL, 0 ); + if ( error ) + return error; + + *aglyf = glyf; + } + + if ( glyf->format != FT_GLYPH_FORMAT_BITMAP ) + PanicZ( "invalid glyph format returned!" ); + + bitmap = (FT_BitmapGlyph)glyf; + source = &bitmap->bitmap; + + target->rows = source->rows; + target->width = source->width; + target->pitch = source->pitch; + target->buffer = source->buffer; + target->grays = source->num_grays; + + switch ( source->pixel_mode ) + { + case FT_PIXEL_MODE_MONO: + target->mode = gr_pixel_mode_mono; + break; + + case FT_PIXEL_MODE_GRAY: + target->mode = gr_pixel_mode_gray; + target->grays = source->num_grays; + break; + + case FT_PIXEL_MODE_GRAY2: + case FT_PIXEL_MODE_GRAY4: + (void)FT_Bitmap_Convert( handle->library, source, &handle->bitmap, 1 ); + target->pitch = handle->bitmap.pitch; + target->buffer = handle->bitmap.buffer; + target->mode = gr_pixel_mode_gray; + target->grays = handle->bitmap.num_grays; + break; + + case FT_PIXEL_MODE_LCD: + target->mode = handle->lcd_mode == 2 ? gr_pixel_mode_lcd + : gr_pixel_mode_lcd2; + target->grays = source->num_grays; + break; + + case FT_PIXEL_MODE_LCD_V: + target->mode = handle->lcd_mode == 4 ? gr_pixel_mode_lcdv + : gr_pixel_mode_lcdv2; + target->grays = source->num_grays; + break; + + default: + return FT_Err_Invalid_Glyph_Format; + } + + *left = bitmap->left; + *top = bitmap->top; + + *x_advance = ( glyf->advance.x + 0x8000 ) >> 16; + *y_advance = ( glyf->advance.y + 0x8000 ) >> 16; + + return error; + } + + + FT_Error + FTDemo_Index_To_Bitmap( FTDemo_Handle* handle, + FT_ULong Index, + grBitmap* target, + int* left, + int* top, + int* x_advance, + int* y_advance, + FT_Glyph* aglyf ) + { + int cached_bitmap = 1; + + *aglyf = NULL; + + /* use the SBits cache to store small glyph bitmaps; this is a lot */ + /* more memory-efficient */ + /* */ + if ( handle->use_sbits_cache && + handle->image_type.width < 48 && + handle->image_type.height < 48 ) + { + FTC_SBit sbit; + FT_Bitmap source; + + + error = FTC_SBitCache_Lookup( handle->sbits_cache, + &handle->image_type, + Index, + &sbit, + NULL ); + if ( error ) + goto Exit; + + if ( sbit->buffer ) + { + target->rows = sbit->height; + target->width = sbit->width; + target->pitch = sbit->pitch; + target->buffer = sbit->buffer; + target->grays = sbit->max_grays + 1; + + switch ( sbit->format ) + { + case FT_PIXEL_MODE_MONO: + target->mode = gr_pixel_mode_mono; + break; + + case FT_PIXEL_MODE_GRAY: + target->mode = gr_pixel_mode_gray; + target->grays = sbit->max_grays + 1; + break; + + case FT_PIXEL_MODE_GRAY2: + case FT_PIXEL_MODE_GRAY4: + source.rows = sbit->height; + source.width = sbit->width; + source.pitch = sbit->pitch; + source.buffer = sbit->buffer; + source.pixel_mode = sbit->format; + + (void)FT_Bitmap_Convert( handle->library, &source, + &handle->bitmap, 1 ); + + target->pitch = handle->bitmap.pitch; + target->buffer = handle->bitmap.buffer; + target->mode = gr_pixel_mode_gray; + target->grays = handle->bitmap.num_grays; + + cached_bitmap = 0; + break; + + case FT_PIXEL_MODE_LCD: + target->mode = handle->lcd_mode == 2 ? gr_pixel_mode_lcd + : gr_pixel_mode_lcd2; + target->grays = sbit->max_grays + 1; + break; + + case FT_PIXEL_MODE_LCD_V: + target->mode = handle->lcd_mode == 4 ? gr_pixel_mode_lcdv + : gr_pixel_mode_lcdv2; + target->grays = sbit->max_grays + 1; + break; + + default: + return FT_Err_Invalid_Glyph_Format; + } + + + *left = sbit->left; + *top = sbit->top; + *x_advance = sbit->xadvance; + *y_advance = sbit->yadvance; + + goto Exit; + } + } + + /* otherwise, use an image cache to store glyph outlines, and render */ + /* them on demand. we can thus support very large sizes easily.. */ + { + FT_Glyph glyf; + + error = FTC_ImageCache_Lookup( handle->image_cache, + &handle->image_type, + Index, + &glyf, + NULL ); + + if ( !error ) + error = FTDemo_Glyph_To_Bitmap( handle, glyf, target, left, top, + x_advance, y_advance, aglyf ); + } + + Exit: + +#ifdef FT_RGB_FILTER_H + /* note that we apply the RGB filter to each cached glyph, which is + * a performance killer, but that's better than modifying the cache + * at the moment + */ + if ( !error ) + { + if ( target->mode == gr_pixel_mode_lcd || + target->mode == gr_pixel_mode_lcdv ) + { + /* copy the bitmap before filtering it, we don't want to touch + * the content of cache nodes at all + */ + { + } + } + } + +#endif /* FT_RGB_FILTER_H */ + + /* don't accept a `missing' character with zero or negative width */ + if ( Index == 0 && *x_advance <= 0 ) + *x_advance = 1; + + return error; + } + + + FT_Error + FTDemo_Draw_Index( FTDemo_Handle* handle, + grBitmap* bitmap, + int gindex, + int* pen_x, + int* pen_y ) + { + int left, top, x_advance, y_advance; + grBitmap bit3; + FT_Glyph glyf; + + grColor c; + memset(&c, 0, sizeof(grColor)); + + error = FTDemo_Index_To_Bitmap(handle, gindex, &bit3, &left, &top, + &x_advance, &y_advance, &glyf); + if(error) + return error; + + /* now render the bitmap into the display surface */ + grBlitGlyphToBitmap( bitmap, &bit3, *pen_x + left, + *pen_y - top, c ); + + if ( glyf ) + FT_Done_Glyph( glyf ); + + *pen_x += x_advance + 1; + + return FT_Err_Ok; + } + + + FT_Error + FTDemo_Draw_Glyph( FTDemo_Handle* handle, + FTDemo_Display* display, + FT_Glyph glyph, + int* pen_x, + int* pen_y ) + { + int left, top, x_advance, y_advance; + grBitmap bit3; + FT_Glyph glyf; + + + error = FTDemo_Glyph_To_Bitmap( handle, glyph, &bit3, &left, &top, + &x_advance, &y_advance, &glyf ); + if ( error ) + { + FT_Done_Glyph( glyph ); + + return error; + } + + /* now render the bitmap into the display surface */ + grBlitGlyphToBitmap( display->bitmap, &bit3, *pen_x + left, + *pen_y - top, display->fore_color ); + + if ( glyf ) + FT_Done_Glyph( glyf ); + + *pen_x += x_advance + 1; + + return FT_Err_Ok; + } + + + FT_Error + FTDemo_Draw_Slot( FTDemo_Handle* handle, + FTDemo_Display* display, + FT_GlyphSlot slot, + int* pen_x, + int* pen_y ) + { + FT_Glyph glyph; + + + error = FT_Get_Glyph( slot, &glyph ); + if ( error ) + return error; + + error = FTDemo_Draw_Glyph( handle, display, glyph, pen_x, pen_y ); + + FT_Done_Glyph( glyph ); + + return error; + } + + + void + FTDemo_String_Set( FTDemo_Handle* handle, + const unsigned char* string ) + { + const unsigned char* p = string; + unsigned long codepoint; + unsigned char in_code; + int expect; + PGlyph glyph = handle->string; + + + handle->string_length = 0; + codepoint = expect = 0; + + while ( *p ) + { + in_code = *p++ ; + + if ( in_code >= 0xC0 ) + { + if ( in_code < 0xE0 ) /* U+0080 - U+07FF */ + { + expect = 1; + codepoint = in_code & 0x1F; + } + else if ( in_code < 0xF0 ) /* U+0800 - U+FFFF */ + { + expect = 2; + codepoint = in_code & 0x0F; + } + else if ( in_code < 0xF8 ) /* U+10000 - U+10FFFF */ + { + expect = 3; + codepoint = in_code & 0x07; + } + continue; + } + else if ( in_code >= 0x80 ) + { + --expect; + + if ( expect >= 0 ) + { + codepoint <<= 6; + codepoint += in_code & 0x3F; + } + if ( expect > 0 ) + continue; + + expect = 0; + } + else /* ASCII, U+0000 - U+007F */ + codepoint = in_code; + + if ( handle->encoding != FT_ENCODING_NONE ) + glyph->glyph_index = FTDemo_Get_Index( handle, codepoint ); + else + glyph->glyph_index = codepoint; + + glyph++; + handle->string_length++; + + if ( handle->string_length >= MAX_GLYPHS ) + break; + } + + handle->string_reload = 1; + } + + + static FT_Error + string_load( FTDemo_Handle* handle ) + { + int n; + FT_Size size; + FT_Face face; + FT_Pos prev_rsb_delta = 0; + + + error = FTDemo_Get_Size( handle, &size ); + if ( error ) + return error; + + face = size->face; + + for ( n = 0; n < handle->string_length; n++ ) + { + PGlyph glyph = handle->string + n; + + + /* clear existing image if there is one */ + if ( glyph->image ) + { + FT_Done_Glyph( glyph->image ); + glyph->image = NULL; + } + + /* load the glyph and get the image */ + if ( !FT_Load_Glyph( face, glyph->glyph_index, + handle->image_type.flags ) && + !FT_Get_Glyph( face->glyph, &glyph->image ) ) + { + FT_Glyph_Metrics* metrics = &face->glyph->metrics; + + + /* note that in vertical layout, y-positive goes downwards */ + + glyph->vvector.x = metrics->vertBearingX - metrics->horiBearingX; + glyph->vvector.y = -metrics->vertBearingY - metrics->horiBearingY; + + glyph->vadvance.x = 0; + glyph->vadvance.y = -metrics->vertAdvance; + + if ( prev_rsb_delta - face->glyph->lsb_delta >= 32 ) + glyph->delta = -1 << 6; + else if ( prev_rsb_delta - face->glyph->lsb_delta < -32 ) + glyph->delta = 1 << 6; + else + glyph->delta = 0; + } + } + + return FT_Err_Ok; + } + + + FT_Error + string_render_prepare( FTDemo_Handle* handle, + FTDemo_String_Context* sc, + FT_Vector* advances ) + { + FT_Face face; + FT_Size size; + PGlyph glyph; + FT_Pos track_kern = 0; + FT_UInt prev_index = 0; + FT_Vector* prev_advance = NULL; + FT_Vector extent = {0, 0}; + FT_Int i; + + + error = FTDemo_Get_Size( handle, &size ); + if ( error ) + return error; + + face = size->face; + + if ( !sc->vertical && sc->kerning_degree ) + { + FT_Fixed ptsize; + + + ptsize = FT_MulFix( face->units_per_EM, face->size->metrics.x_scale ); + + if ( FT_Get_Track_Kerning( face, ptsize << 10, + -sc->kerning_degree, + &track_kern ) ) + track_kern = 0; + else + track_kern >>= 10; + } + + for ( i = 0; i < handle->string_length; i++ ) + { + glyph = handle->string + i; + + if ( !glyph->image ) + continue; + + if ( sc->vertical ) + advances[i] = glyph->vadvance; + else + { + advances[i] = glyph->image->advance; + advances[i].x >>= 10; + advances[i].y >>= 10; + + if ( prev_advance ) + { + prev_advance->x += track_kern; + + if ( sc->kerning_mode ) + { + FT_Vector kern; + + + FT_Get_Kerning( face, prev_index, glyph->glyph_index, + FT_KERNING_UNFITTED, &kern ); + + prev_advance->x += kern.x; + prev_advance->y += kern.y; + + if ( sc->kerning_mode > KERNING_MODE_NORMAL ) + prev_advance->x += glyph->delta; + } + } + } + + if ( prev_advance ) + { + if ( handle->hinted ) + { + prev_advance->x = ROUND( prev_advance->x ); + prev_advance->y = ROUND( prev_advance->y ); + } + + extent.x += prev_advance->x; + extent.y += prev_advance->y; + } + + prev_index = glyph->glyph_index; + prev_advance = advances + i; + } + + if ( prev_advance ) + { + if ( handle->hinted ) + { + prev_advance->x = ROUND( prev_advance->x ); + prev_advance->y = ROUND( prev_advance->y ); + } + + extent.x += prev_advance->x; + extent.y += prev_advance->y; + + /*store the extent in the last slot */ + i = handle->string_length - 1; + advances[i] = extent; + } + + return FT_Err_Ok; + } + + + static void + gamma_ramp_apply( FT_Byte gamma_ramp[256], + grBitmap* bitmap ) + { + int i, j; + FT_Byte* p = (FT_Byte*)bitmap->buffer; + + if ( bitmap->pitch < 0 ) + p += -bitmap->pitch * ( bitmap->rows - 1 ); + + for ( i = 0; i < bitmap->rows; i++ ) + { + for ( j = 0; j < bitmap->width; j++ ) + p[j] = gamma_ramp[p[j]]; + + p += bitmap->pitch; + } + } + + + FT_Error + FTDemo_String_Draw( FTDemo_Handle* handle, + FTDemo_Display* display, + FTDemo_String_Context* sc, + int x, + int y ) + { + int n; + FT_Vector pen, advances[MAX_GLYPHS]; + FT_Size size; + FT_Face face; + + + if ( !sc || + x < 0 || + y < 0 || + x > display->bitmap->width || + y > display->bitmap->rows ) + return FT_Err_Invalid_Argument; + + error = FTDemo_Get_Size( handle, &size ); + if ( error ) + return error; + + face = size->face; + + if ( handle->string_reload ) + { + error = string_load( handle ); + if ( error ) + return error; + + handle->string_reload = 0; + } + + error = string_render_prepare( handle, sc, advances ); + if ( error ) + return error; + + /* change to Cartesian coordinates */ + y = display->bitmap->rows - y; + + /* get the extent, which we store in the last slot */ + pen = advances[handle->string_length - 1]; + + pen.x = FT_MulFix( pen.x, sc->center ); + pen.y = FT_MulFix( pen.y, sc->center ); + + /* XXX sbits */ + /* get pen position */ + if ( sc->matrix && FT_IS_SCALABLE( face ) ) + { + FT_Vector_Transform( &pen, sc->matrix ); + pen.x = ( x << 6 ) - pen.x; + pen.y = ( y << 6 ) - pen.y; + } + else + { + pen.x = ROUND( ( x << 6 ) - pen.x ); + pen.y = ROUND( ( y << 6 ) - pen.y ); + } + + for ( n = 0; n < handle->string_length; n++ ) + { + PGlyph glyph = handle->string + n; + FT_Glyph image; + FT_BBox bbox; + + + if ( !glyph->image ) + continue; + + /* copy image */ + error = FT_Glyph_Copy( glyph->image, &image ); + if ( error ) + continue; + + if ( image->format != FT_GLYPH_FORMAT_BITMAP ) + { + if ( sc->vertical ) + error = FT_Glyph_Transform( image, NULL, &glyph->vvector ); + + if ( !error ) + error = FT_Glyph_Transform( image, sc->matrix, &pen ); + + if ( error ) + { + FT_Done_Glyph( image ); + continue; + } + } + else + { + FT_BitmapGlyph bitmap = (FT_BitmapGlyph)image; + + + if ( sc->vertical ) + { + bitmap->left += ( glyph->vvector.x + pen.x ) >> 6; + bitmap->top += ( glyph->vvector.x + pen.y ) >> 6; + } + else + { + bitmap->left += pen.x >> 6; + bitmap->top += pen.y >> 6; + } + } + + if ( sc->matrix ) + FT_Vector_Transform( advances + n, sc->matrix ); + + pen.x += advances[n].x; + pen.y += advances[n].y; + + FT_Glyph_Get_CBox( image, FT_GLYPH_BBOX_PIXELS, &bbox ); + +#if 0 + if ( n == 0 ) + { + fprintf( stderr, "bbox = [%ld %ld %ld %ld]\n", + bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax ); + } +#endif + + /* check bounding box; if it is completely outside the */ + /* display surface, we don't need to render it */ + if ( bbox.xMax > 0 && + bbox.yMax > 0 && + bbox.xMin < display->bitmap->width && + bbox.yMin < display->bitmap->rows ) + { + int left, top, dummy1, dummy2; + grBitmap bit3; + FT_Glyph glyf; + + + error = FTDemo_Glyph_To_Bitmap( handle, image, &bit3, &left, &top, + &dummy1, &dummy2, &glyf ); + if ( !error ) + { + if ( sc->gamma_ramp ) + gamma_ramp_apply( sc->gamma_ramp, &bit3 ); + + /* change back to the usual coordinates */ + top = display->bitmap->rows - top; + + /* now render the bitmap into the display surface */ + grBlitGlyphToBitmap( display->bitmap, &bit3, left, top, + display->fore_color ); + + if ( glyf ) + FT_Done_Glyph( glyf ); + } + } + + FT_Done_Glyph( image ); + } + + return error; + } + + + FT_Encoding + FTDemo_Make_Encoding_Tag( const char* s ) + { + int i; + unsigned long l = 0; + + + for ( i = 0; i < 4; i++ ) + { + if ( !s[i] ) + break; + l <<= 8; + l += (unsigned long)s[i]; + } + + return (FT_Encoding)l; + } + + +/* End */ diff --git a/kernel/kls_ttf/ftcommon.h b/kernel/kls_ttf/ftcommon.h new file mode 100644 index 0000000..304527f --- /dev/null +++ b/kernel/kls_ttf/ftcommon.h @@ -0,0 +1,307 @@ +/****************************************************************************/ +/* */ +/* The FreeType project -- a free and portable quality TrueType renderer. */ +/* */ +/* Copyright 2005, 2006 by */ +/* D. Turner, R.Wilhelm, and W. Lemberg */ +/* */ +/* */ +/* ftcommon.h - common routines for the FreeType demo programs. */ +/* */ +/****************************************************************************/ + +#ifndef _FT_COMMON_H_ +#define _FT_COMMON_H_ + + +#include +#include FT_FREETYPE_H + +#include FT_CACHE_H +#include FT_CACHE_MANAGER_H + +#include FT_GLYPH_H +#include FT_BITMAP_H + +#include +#include + + extern FT_Error error; + + /* forward declarations */ + extern void PanicZ( const char* message ); + +#undef NODEBUG + +#define LOG( x ) /* */ + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** DISPLAY-SPECIFIC DEFINITIONS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + +#include "graph.h" +#include "grobjs.h" +#include "grfont.h" + + typedef struct + { + grSurface* surface; + grBitmap* bitmap; + grColor fore_color; + grColor back_color; + + } FTDemo_Display; + + grBitmap* + FTDemo_Display_New(void); + + + void + FTDemo_Display_Done(grBitmap *); + + + /* fill the bitmap with background color */ + void + FTDemo_Display_Clear(grBitmap *); + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** FREETYPE-SPECIFIC DEFINITIONS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + +#define MAX_GLYPHS 512 /* at most 512 glyphs in the string */ +#define MAX_GLYPH_BYTES 150000 /* 150kB for the glyph image cache */ + + + typedef struct TGlyph_ + { + FT_UInt glyph_index; + FT_Glyph image; /* the glyph image */ + + FT_Pos delta; /* delta caused by hinting */ + FT_Vector vvector; /* vert. origin => hori. origin */ + FT_Vector vadvance; /* vertical advance */ + + } TGlyph, *PGlyph; + + /* this simple record is used to model a given `installed' face */ + typedef struct TFont_ + { + const char* filepathname; + int face_index; + int cmap_index; + int num_indices; + void* file_address; /* for preloaded files */ + size_t file_size; + + } TFont, *PFont; + + enum { + LCD_MODE_AA = 0, + LCD_MODE_LIGHT, + LCD_MODE_RGB, + LCD_MODE_BGR, + LCD_MODE_VRGB, + LCD_MODE_VBGR, + N_LCD_MODES + }; + + enum { + KERNING_DEGREE_NONE = 0, + KERNING_DEGREE_LIGHT, + KERNING_DEGREE_MEDIUM, + KERNING_DEGREE_TIGHT, + N_KERNING_DEGREES, + }; + + enum { + KERNING_MODE_NONE = 0, /* 0: no kerning; */ + KERNING_MODE_NORMAL, /* 1: `kern' values */ + KERNING_MODE_SMART, /* 2: `kern' + side bearing errors */ + N_KERNING_MODES + }; + + typedef struct + { + int kerning_mode; + int kerning_degree; + FT_Fixed center; /* 0..1 */ + int vertical; /* displayed vertically? */ + FT_Matrix* matrix; /* string transformation */ + FT_Byte* gamma_ramp; /* an array of size 256 */ + + } FTDemo_String_Context; + + typedef struct + { + FT_Library library; /* the FreeType library */ + FTC_Manager cache_manager; /* the cache manager */ + FTC_ImageCache image_cache; /* the glyph image cache */ + FTC_SBitCache sbits_cache; /* the glyph small bitmaps cache */ + FTC_CMapCache cmap_cache; /* the charmap cache.. */ + + PFont* fonts; /* installed fonts */ + int num_fonts; + int max_fonts; + + int use_sbits_cache; /* toggle sbits cache */ + + /* use FTDemo_Set_Current_XXX to set the following two fields */ + PFont current_font; /* selected font */ + FTC_ImageTypeRec image_type; + + /* call FTDemo_Update_Current_Flags after setting any of the following fields */ + int hinted; /* is glyph hinting active? */ + int antialias; /* is anti-aliasing active? */ + int use_sbits; /* do we use embedded bitmaps? */ + int low_prec; /* force low precision */ + int autohint; /* force auto-hinting */ + int lcd_mode; + int preload; /* force font file preloading */ + + /* don't touch the following fields! */ + + /* used for string rendering */ + TGlyph string[MAX_GLYPHS]; + int string_length; + int string_reload; + + FT_Encoding encoding; + FT_Bitmap bitmap; /* used as bitmap conversion buffer */ + + } FTDemo_Handle; + + + FTDemo_Handle* + FTDemo_New( FT_Encoding encoding ); + + + void + FTDemo_Done( FTDemo_Handle* handle ); + + + /* install a font */ + FT_Error + FTDemo_Install_Font( FTDemo_Handle* handle, + const char* filepath ); + + + void + FTDemo_Set_Preload( FTDemo_Handle* handle, + int preload ); + + void + FTDemo_Set_Current_Font( FTDemo_Handle* handle, + PFont font ); + + void + FTDemo_Set_Current_Size( FTDemo_Handle* handle, + int pixel_size ); + + void + FTDemo_Set_Current_Pointsize( FTDemo_Handle* handle, + int point_size, + int res ); + + void + FTDemo_Update_Current_Flags( FTDemo_Handle* handle ); + + + /* charcode => glyph index of current font */ + FT_UInt + FTDemo_Get_Index( FTDemo_Handle* handle, + FT_UInt32 charcode ); + + + /* get FT_Size of current font */ + FT_Error + FTDemo_Get_Size( FTDemo_Handle* handle, + FT_Size* asize ); + + + /* convert a FT_Glyph to a grBitmap (don't free target->buffer) */ + /* if aglyf != NULL, you should FT_Glyph_Done the aglyf */ + FT_Error + FTDemo_Glyph_To_Bitmap( FTDemo_Handle* handle, + FT_Glyph glyf, + grBitmap* target, + int* left, + int* top, + int* x_advance, + int* y_advance, + FT_Glyph* aglyf ); + + /* get a grBitmap from glyph index (don't free target->buffer) */ + /* if aglyf != NULL, you should FT_Glyph_Done the aglyf */ + FT_Error + FTDemo_Index_To_Bitmap( FTDemo_Handle* handle, + FT_ULong Index, + grBitmap* target, + int* left, + int* top, + int* x_advance, + int* y_advance, + FT_Glyph* aglyf ); + + + /* given glyph index, draw a glyph on the display */ + FT_Error + FTDemo_Draw_Index( FTDemo_Handle* handle, + grBitmap* display, + int gindex, + int* pen_x, + int* pen_y); + + + /* given FT_Glyph, draw a glyph on the display */ + FT_Error + FTDemo_Draw_Glyph( FTDemo_Handle* handle, + FTDemo_Display* display, + FT_Glyph glyph, + int* pen_x, + int* pen_y); + + + /* given FT_GlyphSlot, draw a glyph on the display */ + FT_Error + FTDemo_Draw_Slot( FTDemo_Handle* handle, + FTDemo_Display* display, + FT_GlyphSlot slot, + int* pen_x, + int* pen_y); + + + /* set the string to be drawn */ + void + FTDemo_String_Set( FTDemo_Handle* handle, + const unsigned char* string ); + + + /* draw a string centered at (center_x, center_y) -- */ + /* note that handle->use_sbits_cache is not supported */ + FT_Error + FTDemo_String_Draw( FTDemo_Handle* handle, + FTDemo_Display* display, + FTDemo_String_Context* sc, + int center_x, + int center_y ); + + + /* make a FT_Encoding tag from a string */ + FT_Encoding + FTDemo_Make_Encoding_Tag( const char* s ); + + +#endif /* _FTCOMMON_H_ */ + +/* End */ diff --git a/kernel/kls_ttf/ftview/Makefile.am b/kernel/kls_ttf/ftview/Makefile.am new file mode 100644 index 0000000..d744d11 --- /dev/null +++ b/kernel/kls_ttf/ftview/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I. @SQ_FT_CFLAGS@ + +noinst_LTLIBRARIES = libftview.la + +libftview_la_SOURCES = gblblit.cpp gblender.cpp grblit.cpp grfont.cpp grobjs.cpp + +EXTRA_DIST = gblblit.h gblender.h gblvbgr.h grblit.cpp grevents.h grobjs.cpp \ +gblany.h gblcolor.h gblhbgr.h gblvrgb.h grblit.h grfont.cpp grobjs.h README \ +gblblit.cpp gblender.cpp gblhrgb.h graph.h grconfig.h grfont.h grtypes.h diff --git a/kernel/kls_ttf/ftview/README b/kernel/kls_ttf/ftview/README new file mode 100644 index 0000000..61dba91 --- /dev/null +++ b/kernel/kls_ttf/ftview/README @@ -0,0 +1 @@ +All code in this directory is taken from ftdemos-2.1.10 \ No newline at end of file diff --git a/kernel/kls_ttf/ftview/gblany.h b/kernel/kls_ttf/ftview/gblany.h new file mode 100644 index 0000000..a0bc750 --- /dev/null +++ b/kernel/kls_ttf/ftview/gblany.h @@ -0,0 +1,133 @@ +/* check that all macros are correctly set + */ +#ifndef GDST_INCR +#error "GDST_INCR not defined" +#endif + +#ifndef GDST_TYPE +#error "GDST_TYPE not defined" +#endif + +#ifndef GDST_READ +#error "GDST_READ not defined" +#endif + +#ifdef GBLENDER_STORE_BYTES +# ifndef GDST_STOREB +# error "GDST_STOREB not defined" +# endif +#else +# ifndef GDST_STOREP +# error "GDST_STOREP not defined" +# endif +#endif /* !STORE_BYTES */ + +#ifndef GDST_STOREC +#error "GDST_STOREC not defined" +#endif + +#ifndef GDST_COPY +#error "GDST_COPY not defined" +#endif + +#ifndef GDST_COPY_VAR +#error "GDST_COPY_VAR not defined" +#endif + +#undef GCONCAT +#undef GCONCATX +#define GCONCAT(x,y) GCONCATX(x,y) +#define GCONCATX(x,y) x ## y + + +#include + +static void +GCONCAT( _gblender_blit_gray8_, GDST_TYPE )( GBlenderBlit blit, + GBlenderPixel color ) +{ + + GBlender blender = blit->blender; + int r = (color >> 16) & 255; + int g = (color >> 8) & 255; + int b = (color) & 255; + + GDST_COPY_VAR + +#include "gblcolor.h" + +} + + +static void +GCONCAT( _gblender_blit_hrgb_, GDST_TYPE )( GBlenderBlit blit, + GBlenderPixel color ) +{ + GBlender blender = blit->blender; + int r = (color >> 16) & 255; + int g = (color >> 8) & 255; + int b = (color) & 255; + + GDST_COPY_VAR + +#include "gblhrgb.h" +} + + +static void +GCONCAT( _gblender_blit_hbgr_, GDST_TYPE )( GBlenderBlit blit, + GBlenderPixel color ) +{ + GBlender blender = blit->blender; + int r = (color >> 16) & 255; + int g = (color >> 8) & 255; + int b = (color) & 255; + + GDST_COPY_VAR + +#include "gblhbgr.h" +} + + +static void +GCONCAT( _gblender_blit_vrgb_, GDST_TYPE )( GBlenderBlit blit, + GBlenderPixel color ) +{ + GBlender blender = blit->blender; + int r = (color >> 16) & 255; + int g = (color >> 8) & 255; + int b = (color) & 255; + + GDST_COPY_VAR + +#include "gblvrgb.h" +} + +static void +GCONCAT( _gblender_blit_vbgr_, GDST_TYPE )( GBlenderBlit blit, + GBlenderPixel color ) +{ + GBlender blender = blit->blender; + int r = (color >> 16) & 255; + int g = (color >> 8) & 255; + int b = (color) & 255; + + GDST_COPY_VAR + +#include "gblvbgr.h" +} + +/* unset the macros, to prevent accidental re-use + */ + +#undef GCONCATX +#undef GCONCAT +#undef GDST_TYPE +#undef GDST_INCR +#undef GDST_READ +#undef GDST_COPY +#undef GDST_STOREB +#undef GDST_STOREP +#undef GDST_STOREC +#undef GDST_COPY_VAR +/* EOF */ diff --git a/kernel/kls_ttf/ftview/gblblit.cpp b/kernel/kls_ttf/ftview/gblblit.cpp new file mode 100644 index 0000000..afb363d --- /dev/null +++ b/kernel/kls_ttf/ftview/gblblit.cpp @@ -0,0 +1,318 @@ +#include "gblblit.h" + +#include + +/* blitting gray glyphs + */ + +/* generic macros + */ +#define GRGB_PACK(r,g,b) ( ((GBlenderPixel)(r) << 16) | \ + ((GBlenderPixel)(g) << 8) | \ + (GBlenderPixel)(b) ) + +#define GDST_STORE3(d,r,g,b) (d)[0] = (unsigned char)(r); \ + (d)[1] = (unsigned char)(g); \ + (d)[2] = (unsigned char)(b) + +/* */ + +#define GRGB_TO_RGB565(r,g,b) ((unsigned short)( ((r << 8) & 0xF800) | \ + ((g << 3) & 0x07E0) | \ + ((b >> 3) & 0x001F) ) ) + +#define GRGB565_TO_RGB24(p) ( ( ((p) << 8) & 0xF80000 ) | \ + ( ((p) << 3) & 0x0700F8 ) | \ + ( ((p) << 5) & 0x00FC00 ) | \ + ( ((p) >> 1) & 0x000300 ) | \ + ( ((p) >> 2) & 0x000007 ) ) + +#define GRGB24_TO_RGB565(p) ( (unsigned short)( (((p) >> 8) & 0xF800 ) | \ + (((p) >> 5) & 0x07E0 ) | \ + (((p) >> 3) & 0x001F ) ) ) + +/* */ + +#define GRGB_TO_BGR565(r,g,b) GRGB_TO_RGB565(b,g,r) + +#define GBGR565_TO_RGB24(p) ( ( ((p) << 19) & 0xF80000 ) | \ + ( ((p) << 12) & 0x070000 ) | \ + ( ((p) << 5) & 0x00FC00 ) | \ + ( ((p) >> 1) & 0x000300 ) | \ + ( ((p) >> 8) & 0x0000F8 ) | \ + ( ((p) >> 13) & 0x000007 ) ) + +#define GRGB24_TO_BGR565(p) ( (unsigned short)( (((p) << 8) & 0xF800 ) | \ + (((p) >> 5) & 0x07E0 ) | \ + (((p) >> 19) & 0x001F ) ) ) + +/* */ + +/* Rgb32 blitting routines + */ + +#define GDST_TYPE rgb32 +#define GDST_INCR 4 +#define GDST_READ(d,p) (p) = *(GBlenderPixel*)(d) & 0xFFFFFF +#define GDST_COPY(d) *(GBlenderPixel*)(d) = color +#define GDST_STOREP(d,cells,a) *(GBlenderPixel*)(d) = (cells)[(a)] +#define GDST_STOREB(d,cells,a) \ + { \ + GBlenderCell* _g = (cells) + (a)*3; \ + \ + GDST_STOREC(d,_g[0],_g[1],_g[2]); \ + } +#define GDST_STOREC(d,r,g,b) *(GBlenderPixel*)(d) = GRGB_PACK(r,g,b) +#define GDST_COPY_VAR /* nothing */ + +#include "gblany.h" + +/* Rgb24 blitting routines + */ + +#define GDST_TYPE rgb24 +#define GDST_INCR 3 +#define GDST_READ(d,p) (p) = GRGB_PACK((d)[0],(d)[1],(d)[2]) +#define GDST_COPY(d) GDST_STORE3(d,r,g,b) +#define GDST_STOREC(d,r,g,b) GDST_STORE3(d,r,g,b) + +#define GDST_STOREB(d,cells,a) \ + { \ + GBlenderCell* _g = (cells) + (a)*3; \ + \ + (d)[0] = _g[0]; \ + (d)[1] = _g[1]; \ + (d)[2] = _g[2]; \ + } + +#define GDST_STOREP(d,cells,a) \ + { \ + GBlenderPixel _pix = (cells)[(a)]; \ + \ + GDST_STORE3(d,_pix >> 16,_pix >> 8,_pix); \ + } + +#define GDST_COPY_VAR /* nothing */ + +#include "gblany.h" + +/* Rgb565 blitting routines + */ + +#define GDST_TYPE rgb565 +#define GDST_INCR 2 + +#define GDST_READ(d,p) p = (GBlenderPixel)*(unsigned short*)(d); \ + p = GRGB565_TO_RGB24(p) + +#define GDST_COPY_VAR unsigned short pix = GRGB_TO_RGB565(r,g,b); +#define GDST_COPY(d) *(unsigned short*)(d) = pix + +#define GDST_STOREB(d,cells,a) \ + { \ + GBlenderCell* _g = (cells) + (a)*3; \ + \ + *(unsigned short*)(d) = GRGB_TO_RGB565(_g[0],_g[1],_g[2]); \ + } + +#define GDST_STOREP(d,cells,a) \ + { \ + GBlenderPixel _pix = (cells)[(a)]; \ + \ + *(unsigned short*)(d) = GRGB24_TO_RGB565(_pix); \ + } + +#define GDST_STOREC(d,r,g,b) *(unsigned short*)(d) = GRGB_TO_RGB565(r,g,b) + +#include "gblany.h" + +/* Bgr565 blitting routines + */ +#define GDST_TYPE bgr565 +#define GDST_INCR 2 + +#define GDST_READ(d,p) p = (GBlenderPixel)*(unsigned short*)(d); \ + p = GBGR565_TO_RGB24(p) + +#define GDST_COPY_VAR unsigned short pix = GRGB_TO_BGR565(r,g,b); +#define GDST_COPY(d) *(d) = pix + +#define GDST_STOREB(d,cells,a) \ + { \ + GBlenderCell* _g = (cells) + (a)*3; \ + \ + *(unsigned short*)(d) = GRGB_TO_BGR565(_g[0],_g[1],_g[2]); \ + } + +#define GDST_STOREP(d,cells,a) \ + { \ + GBlenderPixel _pix = (cells)[(a)]; \ + \ + *(unsigned short*)(d) = GRGB24_TO_BGR565(_pix); \ + } + +#define GDST_STOREC(d,r,g,b) *(unsigned short*)(d) = GRGB_TO_BGR565(r,g,b) + +#include "gblany.h" + +/* */ + +static void +_gblender_blit_dummy( GBlenderBlit blit, + GBlenderPixel color ) +{ + (blit)=(blit); + (color)=(color); +} + + +GBLENDER_APIDEF( int ) +gblender_blit_init( GBlenderBlit blit, + GBlender blender, + int dst_x, + int dst_y, + GBlenderSourceFormat src_format, + const unsigned char* src_buffer, + int src_pitch, + int src_width, + int src_height, + GBlenderTargetFormat dst_format, + unsigned char* dst_buffer, + int dst_pitch, + int dst_width, + int dst_height ) +{ + int src_x = 0; + int src_y = 0; + int delta; + GBlenderBlitFunc blit_func = 0; + + switch ( src_format ) + { + case GBLENDER_SOURCE_GRAY8: + switch ( dst_format ) + { + case GBLENDER_TARGET_RGB32: blit_func = _gblender_blit_gray8_rgb32; break; + case GBLENDER_TARGET_RGB24: blit_func = _gblender_blit_gray8_rgb24; break; + case GBLENDER_TARGET_RGB565: blit_func = _gblender_blit_gray8_rgb565; break; + case GBLENDER_TARGET_BGR565: blit_func = _gblender_blit_gray8_bgr565; break; + default: + ; + } + break; + + case GBLENDER_SOURCE_HRGB: + switch ( dst_format ) + { + case GBLENDER_TARGET_RGB32: blit_func = _gblender_blit_hrgb_rgb32; break; + case GBLENDER_TARGET_RGB24: blit_func = _gblender_blit_hrgb_rgb24; break; + case GBLENDER_TARGET_RGB565: blit_func = _gblender_blit_hrgb_rgb565; break; + case GBLENDER_TARGET_BGR565: blit_func = _gblender_blit_hrgb_bgr565; break; + default: + ; + } + break; + + case GBLENDER_SOURCE_HBGR: + switch ( dst_format ) + { + case GBLENDER_TARGET_RGB32: blit_func = _gblender_blit_hbgr_rgb32; break; + case GBLENDER_TARGET_RGB24: blit_func = _gblender_blit_hbgr_rgb24; break; + case GBLENDER_TARGET_RGB565: blit_func = _gblender_blit_hbgr_rgb565; break; + case GBLENDER_TARGET_BGR565: blit_func = _gblender_blit_hbgr_bgr565; break; + default: + ; + } + break; + + case GBLENDER_SOURCE_VRGB: + switch ( dst_format ) + { + case GBLENDER_TARGET_RGB32: blit_func = _gblender_blit_vrgb_rgb32; break; + case GBLENDER_TARGET_RGB24: blit_func = _gblender_blit_vrgb_rgb24; break; + case GBLENDER_TARGET_RGB565: blit_func = _gblender_blit_vrgb_rgb565; break; + case GBLENDER_TARGET_BGR565: blit_func = _gblender_blit_vrgb_bgr565; break; + default: + ; + } + break; + + case GBLENDER_SOURCE_VBGR: + switch ( dst_format ) + { + case GBLENDER_TARGET_RGB32: blit_func = _gblender_blit_vbgr_rgb32; break; + case GBLENDER_TARGET_RGB24: blit_func = _gblender_blit_vbgr_rgb24; break; + case GBLENDER_TARGET_RGB565: blit_func = _gblender_blit_vbgr_rgb565; break; + case GBLENDER_TARGET_BGR565: blit_func = _gblender_blit_vbgr_bgr565; break; + default: + ; + } + break; + + default: + ; + } + + blit->blender = blender; + blit->blit_func = blit_func; + + if ( blit_func == 0 ) + { + /* unsupported blit mode + */ + blit->blit_func = _gblender_blit_dummy; + return -2; + } + + if ( dst_x < 0 ) + { + src_width += dst_x; + src_x -= dst_x; + dst_x = 0; + } + + delta = dst_x + src_width - dst_width; + if ( delta > 0 ) + src_width -= delta; + + if ( dst_y < 0 ) + { + src_height += dst_y; + src_y -= dst_y; + dst_y = 0; + } + + delta = dst_y + src_height - dst_height; + if ( delta > 0 ) + src_height -= delta; + + /* nothing to blit + */ + if ( src_width <= 0 || src_height <= 0 ) + { + blit->blit_func = _gblender_blit_dummy; + return -1; + } + + blit->width = src_width; + blit->height = src_height; + blit->src_format = src_format; + blit->dst_format = dst_format; + + blit->src_x = src_x; + blit->src_y = src_y; + blit->src_line = src_buffer + src_pitch*src_y; + blit->src_pitch = src_pitch; + if ( src_pitch < 0 ) + blit->src_line -= (src_height-1)*src_pitch; + + blit->dst_x = dst_x; + blit->dst_y = dst_y; + blit->dst_line = dst_buffer + dst_pitch*dst_y; + blit->dst_pitch = dst_pitch; + if ( dst_pitch < 0 ) + blit->dst_line -= (dst_height-1)*dst_pitch; + + return 0; +} + diff --git a/kernel/kls_ttf/ftview/gblblit.h b/kernel/kls_ttf/ftview/gblblit.h new file mode 100644 index 0000000..564a21d --- /dev/null +++ b/kernel/kls_ttf/ftview/gblblit.h @@ -0,0 +1,82 @@ +#ifndef __GBLENDER_BLIT_H__ +#define __GBLENDER_BLIT_H__ + +#include "gblender.h" + +/* + * blitting interface + * + */ + +typedef enum +{ + GBLENDER_SOURCE_GRAY8 = 0, + GBLENDER_SOURCE_HRGB, + GBLENDER_SOURCE_HBGR, + GBLENDER_SOURCE_VRGB, + GBLENDER_SOURCE_VBGR, + + GBLENDER_SOURCE_MAX + +} GBlenderSourceFormat; + + +typedef enum +{ + GBLENDER_TARGET_GRAY8 = 0, + GBLENDER_TARGET_RGB32, + GBLENDER_TARGET_RGB24, + GBLENDER_TARGET_RGB565, + GBLENDER_TARGET_BGR565, + + GBLENDER_TARGET_MAX + +} GBlenderTargetFormat; + +typedef struct GBlenderBlitRec_* GBlenderBlit; + +typedef void (*GBlenderBlitFunc)( GBlenderBlit blit, + GBlenderPixel color ); + +typedef struct GBlenderBlitRec_ +{ + int width; + int height; + const unsigned char* src_line; + int src_pitch; + int src_x; + int src_y; + unsigned char* dst_line; + int dst_pitch; + int dst_x; + int dst_y; + GBlenderSourceFormat src_format; + GBlenderTargetFormat dst_format; + + GBlender blender; + GBlenderBlitFunc blit_func; + +} GBlenderBlitRec; + + + +GBLENDER_API( int ) +gblender_blit_init( GBlenderBlit blit, + GBlender blender, + int dst_x, + int dst_y, + GBlenderSourceFormat src_format, + const unsigned char* src_buffer, + int src_pitch, + int src_width, + int src_height, + GBlenderTargetFormat dst_format, + unsigned char* dst_buffer, + int dst_pitch, + int dst_width, + int dst_height ); + +#define gblender_blit_run(b,color) (b)->blit_func( (b), (color) ) + + +#endif /* __GBLENDER_BLIT_H__ */ diff --git a/kernel/kls_ttf/ftview/gblcolor.h b/kernel/kls_ttf/ftview/gblcolor.h new file mode 100644 index 0000000..0aa2b6d --- /dev/null +++ b/kernel/kls_ttf/ftview/gblcolor.h @@ -0,0 +1,56 @@ + + GBLENDER_VARS(blender,color); + + int h = blit->height; + const unsigned char* src_line = blit->src_line; + unsigned char* dst_line = blit->dst_line; + + /* make compiler happy */ + (r)=(r); + (g)=(g); + (b)=(b); + + do + { + const unsigned char* src = src_line + (blit->src_x); + unsigned char* dst = dst_line + blit->dst_x*GDST_INCR; + int w = blit->width; + + do + { + int a = GBLENDER_SHADE_INDEX(src[0]); + + if ( a == 0 ) + { + /* nothing */ + } + else if ( a == GBLENDER_SHADE_COUNT ) + { + GDST_COPY(dst); + } + else + { + GBlenderPixel back; + + GDST_READ(dst,back); + + GBLENDER_LOOKUP( blender, back ); + +#ifdef GBLENDER_STORE_BYTES + GDST_STOREB(dst,_gcells,a); +#else + GDST_STOREP(dst,_gcells,a); +#endif + } + + src += 1; + dst += GDST_INCR; + } + while (--w > 0); + + src_line += blit->src_pitch; + dst_line += blit->dst_pitch; + } + while (--h > 0); + + GBLENDER_CLOSE(blender); diff --git a/kernel/kls_ttf/ftview/gblender.cpp b/kernel/kls_ttf/ftview/gblender.cpp new file mode 100644 index 0000000..a0f204d --- /dev/null +++ b/kernel/kls_ttf/ftview/gblender.cpp @@ -0,0 +1,381 @@ +#include "gblender.h" +#include +#include + +static void +gblender_set_gamma_table( double gamma_value, + unsigned short* gamma_ramp, + unsigned char* gamma_ramp_inv ) +{ + int gmax = (256 << GBLENDER_GAMMA_SHIFT)-1; + + if ( gamma_value <= 0 ) /* special case for sRGB */ + { + int ii; + + for ( ii = 0; ii < 256; ii++ ) + { + double x = (double)ii / 255.0; + + if ( x <= 0.03926 ) + x = x/12.92; + else + x = pow( (x+0.055)/ 1.055, 2.4 ); + + gamma_ramp[ii] = (unsigned short)(gmax*x); + } + + for ( ii = 0; ii < gmax; ii++ ) + { + double x = (double)ii / gmax; + + if ( x <= 0.00304 ) + x = 12.92*x; + else + x = 1.055*pow(x,1/2.4) - 0.055; + + gamma_ramp_inv[ii] = (unsigned char)(255*x); + } + } + else + { + int ii; + double gamma_inv = 1.0f / gamma_value; + + /* voltage to linear */ + for ( ii = 0; ii < 256; ii++ ) + gamma_ramp[ii] = (unsigned short)( pow( (double)ii/255.0f, gamma_value )*gmax ); + + /* linear to voltage */ + for ( ii = 0; ii < gmax; ii++ ) + gamma_ramp_inv[ii] = (unsigned char)( pow( (double)ii/gmax, gamma_inv ) * 255.0f ); + } +} + + +/* clear the cache + */ +static void +gblender_clear( GBlender blender ) +{ + int nn; + GBlenderKey keys = blender->keys; + + if ( blender->channels ) + { + GBlenderChanKey chan_keys = (GBlenderChanKey) blender->keys; + + for ( nn = 0; nn < GBLENDER_KEY_COUNT; nn++ ) + chan_keys[nn].index = -1; + } + else + { + for ( nn = 0; nn < GBLENDER_KEY_COUNT; nn++ ) + keys[nn].cells = NULL; + } +} + +GBLENDER_APIDEF( void ) +gblender_reset( GBlender blender ) +{ + gblender_clear( blender ); + + blender->cache_r_back = -1; + blender->cache_r_fore = -1; + blender->cache_r_cells = 0; + + blender->cache_r_back = -1; + blender->cache_r_fore = -1; + blender->cache_r_cells = 0; + + blender->cache_back = 0; + blender->cache_fore = 0xFFFFFF; + blender->cache_cells = gblender_lookup( blender, + blender->cache_back, + blender->cache_fore ); + +#ifdef GBLENDER_STATS + blender->stat_hits = 0; + blender->stat_lookups = 0; + blender->stat_keys = 0; + blender->stat_clears = 0; +#endif +} + +GBLENDER_APIDEF( void ) +gblender_init( GBlender blender, + double gamma_value ) +{ + blender->channels = 0; + + gblender_set_gamma_table ( gamma_value, + blender->gamma_ramp, + blender->gamma_ramp_inv ); + + gblender_reset( blender ); +} + +/* recompute the grade levels of a given key + */ +static void +gblender_reset_key( GBlender blender, + GBlenderKey key ) +{ + GBlenderPixel back = key->background; + GBlenderPixel fore = key->foreground; + GBlenderCell* gr = key->cells; + int nn; + int gmax = (256 << GBLENDER_GAMMA_SHIFT)-1; + + const unsigned char* gamma_ramp_inv = blender->gamma_ramp_inv; + const unsigned short* gamma_ramp = blender->gamma_ramp; + + int r1,g1,b1,r2,g2,b2; + + r1 = ( back >> 16 ) & 255; + g1 = ( back >> 8 ) & 255; + b1 = ( back ) & 255; + + r2 = ( fore >> 16 ) & 255; + g2 = ( fore >> 8 ) & 255; + b2 = ( fore ) & 255; + +#ifdef GBLENDER_STORE_BYTES + gr[0] = (unsigned char)r1; + gr[1] = (unsigned char)g1; + gr[2] = (unsigned char)b1; + gr += 3; +#else + gr[0] = back; + gr += 1; +#endif + + r1 = gamma_ramp[r1]; + g1 = gamma_ramp[g1]; + b1 = gamma_ramp[b1]; + + r2 = gamma_ramp[r2]; + g2 = gamma_ramp[g2]; + b2 = gamma_ramp[b2]; + + for ( nn = 1; nn < GBLENDER_SHADE_COUNT; nn++ ) + { + int a = (nn << GBLENDER_SHADE_BITS); + int r = ((r2-r1)*a + 128); + int g = ((g2-g1)*a + 128); + int b = ((g2-g1)*a + 128); + + r = (r + (r >> 8)) >> 8; + g = (g + (g >> 8)) >> 8; + b = (b + (b >> 8)) >> 8; + + r += r1; + g += g1; + b += b1; + +#if 0 + r = ( r | -(r >> 8) ) & 255; + g = ( g | -(g >> 8) ) & 255; + b = ( b | -(b >> 8) ) & 255; +#else + if ( r < 0 ) r = 0; else if ( r > gmax ) r = gmax; + if ( g < 0 ) g = 0; else if ( g > gmax ) g = gmax; + if ( b < 0 ) b = 0; else if ( b > gmax ) b = gmax; +#endif + + r = gamma_ramp_inv[r]; + g = gamma_ramp_inv[g]; + b = gamma_ramp_inv[b]; + +#ifdef GBLENDER_STORE_BYTES + gr[0] = (unsigned char)r; + gr[1] = (unsigned char)g; + gr[2] = (unsigned char)b; + gr += 3; +#else + gr[0] = (( r & 255 ) << 16) | + (( g & 255 ) << 8 ) | + (( b & 255 ) ) ; + gr ++; +#endif + } +} + + /* lookup the grades of a given (background,foreground) couple + */ +GBLENDER_APIDEF( GBlenderCell* ) +gblender_lookup( GBlender blender, + GBlenderPixel background, + GBlenderPixel foreground ) +{ + int idx, idx0; + GBlenderKey key; + +#ifdef GBLENDER_STATS + blender->stat_hits--; + blender->stat_lookups++; +#endif + + if ( blender->channels ) + { + /* set to normal mode */ + blender->channels = 0; + gblender_reset( blender ); + } + + idx0 = ( background + foreground*63 ) % GBLENDER_KEY_COUNT; + idx = idx0; + do + { + key = blender->keys + idx; + + if ( key->cells == NULL ) + goto NewNode; + + if ( key->background == background && + key->foreground == foreground ) + goto Exit; + + idx = (idx+1) % GBLENDER_KEY_COUNT; + } + while ( idx != idx0 ); + + /* the cache is full, clear it completely + */ +#ifdef GBLENDER_STATS + blender->stat_clears++; + gblender_clear( blender ); +#endif + +NewNode: + key->background = background; + key->foreground = foreground; + key->cells = blender->cells + \ + idx0*(GBLENDER_SHADE_COUNT*GBLENDER_CELL_SIZE); + + gblender_reset_key( blender, key ); + +#ifdef GBLENDER_STATS + blender->stat_keys++; +#endif + +Exit: + return key->cells; +} + + +static void +gblender_reset_channel_key( GBlender blender, + GBlenderChanKey key ) +{ + int back = key->backfore & 255; + int fore = (key->backfore >> 8) & 255; + unsigned char* gr = (unsigned char*)blender->cells + key->index; + int nn; + + const unsigned char* gamma_ramp_inv = blender->gamma_ramp_inv; + const unsigned short* gamma_ramp = blender->gamma_ramp; + + int r1,r2; + int gmax = (256 << GBLENDER_GAMMA_SHIFT)-1; + + r1 = back; + r2 = fore; + + gr[0] = r1; + gr++; + + + r1 = gamma_ramp[r1]; + r2 = gamma_ramp[r2]; + + for ( nn = 1; nn < GBLENDER_SHADE_COUNT; nn++ ) + { + int a = (nn << GBLENDER_SHADE_BITS); + int r = ((r2-r1)*a + 128); + + r = (r + (r >> 8)) >> 8; + r += r1; + if ( r < 0 ) r = 0; else if ( r > gmax ) r = gmax; + r = gamma_ramp_inv[r]; + + gr[0] = (unsigned char)r; + gr++; + } +} + + +GBLENDER_APIDEF( unsigned char* ) +gblender_lookup_channel( GBlender blender, + int background, + int foreground ) +{ + int idx, idx0; + unsigned short backfore = (unsigned short)((foreground << 8) | background); + GBlenderChanKey key; + +#ifdef GBLENDER_STATS + blender->stat_hits--; + blender->stat_lookups++; +#endif + + if ( !blender->channels ) + { + /* set to normal mode */ + blender->channels = 1; + gblender_reset( blender ); + } + + idx0 = ( background + foreground*63 ) % (2*GBLENDER_KEY_COUNT); + idx = idx0; + do + { + key = (GBlenderChanKey)blender->keys + idx; + + if ( key->index < 0 ) + goto NewNode; + + if ( key->backfore == backfore ) + goto Exit; + + idx = (idx+1) % (2*GBLENDER_KEY_COUNT); + } + while ( idx != idx0 ); + + /* the cache is full, clear it completely + */ +#ifdef GBLENDER_STATS + blender->stat_clears++; + gblender_clear( blender ); +#endif + +NewNode: + key->backfore = backfore; + key->index = (signed short)( idx0 * GBLENDER_SHADE_COUNT ); + + gblender_reset_channel_key( blender, key ); + +#ifdef GBLENDER_STATS + blender->stat_keys++; +#endif + +Exit: + return (unsigned char*)blender->cells + key->index; +} + + + +#ifdef GBLENDER_STATS +#include +GBLENDER_APIDEF( void ) +gblender_dump_stats( GBlender blender ) +{ + printf( "hits = %ld, miss1 = %ld, miss2 = %ld, rate1=%.2f%%, rate2=%.2f%%\n", + blender->stat_hits, + blender->stat_lookups, + blender->stat_keys, + (100.0*blender->stat_hits) / (double)(blender->stat_hits + blender->stat_lookups), + (100.0*blender->stat_lookups) / (double)( blender->stat_lookups + blender->stat_keys) + ); +} +#endif diff --git a/kernel/kls_ttf/ftview/gblender.h b/kernel/kls_ttf/ftview/gblender.h new file mode 100644 index 0000000..b519b3c --- /dev/null +++ b/kernel/kls_ttf/ftview/gblender.h @@ -0,0 +1,216 @@ +/**************************************************************************** + * + * Gamma-correct alpha blending of text + * + * (C) 2004 David Turner + * + */ + +#ifndef __GBLENDER_H__ +#define __GBLENDER_H__ + +#ifndef GBLENDER_API +#define GBLENDER_API(x) extern x +#endif + +#ifndef GBLENDER_APIDEF +#define GBLENDER_APIDEF(x) x +#endif + +#define GBLENDER_SHADE_BITS 4 /* must be <= 7 !! */ +#define GBLENDER_SHADE_COUNT ( 1 << GBLENDER_SHADE_BITS ) +#define GBLENDER_SHADE_INDEX(n) ((n + (GBLENDER_SHADE_COUNT/2)) >> GBLENDER_SHADE_BITS) +#define GBLENDER_KEY_COUNT 256 +#define GBLENDER_GAMMA_SHIFT 2 + +#define xGBLENDER_STORE_BYTES /* define this to store (R,G,B) values on 3 \ + * bytes, instead of a single 32-bit integer.\ + * surprisingly, this can speed up \ + * the blender on certain machines. \ + * Go figure what's really happenning though :-) \ + */ + +#define GBLENDER_STATS /* define this to collect statistics in the \ + * blender \ + */ + + typedef unsigned int GBlenderPixel; /* needs 32-bits here !! */ + +#ifdef GBLENDER_STORE_BYTES + typedef unsigned char GBlenderCell; +# define GBLENDER_CELL_SIZE 3 +#else + typedef GBlenderPixel GBlenderCell; +# define GBLENDER_CELL_SIZE 1 +#endif + + + typedef struct + { + GBlenderPixel background; + GBlenderPixel foreground; + GBlenderCell* cells; + + } GBlenderKeyRec, *GBlenderKey; + + + typedef struct + { + unsigned short backfore; /* (fore << 8) | back */ + signed short index; /* offset in (unsigned char*)cells */ + + } GBlenderChanKeyRec, *GBlenderChanKey; + + + typedef struct GBlenderRec_ + { + GBlenderKeyRec keys [ GBLENDER_KEY_COUNT ]; + GBlenderCell cells[ GBLENDER_KEY_COUNT*GBLENDER_SHADE_COUNT*GBLENDER_CELL_SIZE ]; + + /* a small cache for normal modes + */ + GBlenderPixel cache_back; + GBlenderPixel cache_fore; + GBlenderCell* cache_cells; + + /* a small cache for RGB channels modes + */ + int cache_r_back; + int cache_r_fore; + unsigned char* cache_r_cells; + + int cache_g_back; + int cache_g_fore; + unsigned char* cache_g_cells; + + int cache_b_back; + int cache_b_fore; + unsigned char* cache_b_cells; + + /* are we in color or channel mode ? + */ + int channels; + + /* the gamma table + */ + unsigned short gamma_ramp[256]; /* voltage to linear */ + unsigned char gamma_ramp_inv[256 << GBLENDER_GAMMA_SHIFT]; /* linear to voltage */ + +#ifdef GBLENDER_STATS + long stat_hits; /* number of direct hits */ + long stat_lookups; /* number of table lookups */ + long stat_keys; /* number of table key recomputation */ + long stat_clears; /* number of table clears */ +#endif + + } GBlenderRec, *GBlender; + + + /* initialize with a given gamma */ + GBLENDER_API( void ) + gblender_init( GBlender blender, + double gamma ); + + + /* clear blender, and reset stats */ + GBLENDER_API( void ) + gblender_reset( GBlender reset ); + + + /* lookup a cell range for a given (background,foreground) pair + */ + GBLENDER_API( GBlenderCell* ) + gblender_lookup( GBlender blender, + GBlenderPixel background, + GBlenderPixel foreground ); + + GBLENDER_API( unsigned char* ) + gblender_lookup_channel( GBlender blender, + int background, + int foreground ); + +#ifdef GBLENDER_STATS + GBLENDER_API( void ) + gblender_dump_stats( GBlender blender ); +#else +# define gblender_dump_stats(b) do { } while (0); +#endif + + + /* no final `;'! */ +#define GBLENDER_VARS(_gb,_fore) \ + GBlenderPixel _gback = (_gb)->cache_back; \ + GBlenderCell* _gcells = ( (_fore) == (_gb)->cache_fore ? (_gb)->cache_cells : gblender_lookup( (_gb), _gback, _fore ) ); \ + GBlenderPixel _gfore = (_fore) + +#define GBLENDER_CLOSE(_gb) \ + (_gb)->cache_back = _gback; \ + (_gb)->cache_fore = _gfore; \ + (_gb)->cache_cells = _gcells; + + + + /* no final `;'! */ +#define GBLENDER_CHANNEL_VARS(_gb,_rfore,_gfore,_bfore) \ + int _grback = (_gb)->cache_r_back; \ + unsigned char* _grcells = ( (_rfore) == (_gb)->cache_r_fore ? (_gb)->cache_r_cells : gblender_lookup_channel( (_gb), _grback, _rfore )); \ + int _grfore = (_rfore); \ + int _ggback = (_gb)->cache_g_back; \ + unsigned char* _ggcells = ( (_gfore) == (_gb)->cache_g_fore ? (_gb)->cache_g_cells : gblender_lookup_channel( (_gb), _ggback, _gfore )); \ + int _ggfore = (_rfore); \ + int _gbback = (_gb)->cache_b_back; \ + unsigned char* _gbcells = ( (_bfore) == (_gb)->cache_b_fore ? (_gb)->cache_b_cells : gblender_lookup_channel( (_gb), _gbback, _bfore )); \ + int _gbfore = (_bfore) + +#define GBLENDER_CHANNEL_CLOSE(_gb) \ + (_gb)->cache_r_back = _grback; \ + (_gb)->cache_r_fore = _grfore; \ + (_gb)->cache_r_cells = _grcells; \ + (_gb)->cache_g_back = _ggback; \ + (_gb)->cache_g_fore = _ggfore; \ + (_gb)->cache_g_cells = _ggcells; \ + (_gb)->cache_b_back = _gbback; \ + (_gb)->cache_b_fore = _gbfore; \ + (_gb)->cache_b_cells = _gbcells; + + +#ifdef GBLENDER_STATS +#define GBLENDER_STAT_HIT(gb) (gb)->stat_hits++ +#else +#define GBLENDER_STAT_HIT(gb) /* nothing */ +#endif + +#define GBLENDER_LOOKUP(gb,back) \ + GBLENDER_STAT_HIT(gb); \ + if ( _gback != (GBlenderPixel)(back) ) \ + { \ + _gback = (GBlenderPixel)(back); \ + _gcells = gblender_lookup( (gb), _gback, _gfore ); \ + } + +#define GBLENDER_LOOKUP_R(gb,back) \ + GBLENDER_STAT_HIT(gb); \ + if ( _grback != (int)(back) ) \ + { \ + _grback = (GBlenderPixel)(back); \ + _grcells = gblender_lookup_channel( (gb), _grback, _grfore ); \ + } + +#define GBLENDER_LOOKUP_G(gb,back) \ + GBLENDER_STAT_HIT(gb); \ + if ( _ggback != (int)(back) ) \ + { \ + _ggback = (GBlenderPixel)(back); \ + _ggcells = gblender_lookup_channel( (gb), _ggback, _ggfore ); \ + } + +#define GBLENDER_LOOKUP_B(gb,back) \ + GBLENDER_STAT_HIT(gb); \ + if ( _gbback != (int)(back) ) \ + { \ + _gbback = (GBlenderPixel)(back); \ + _gbcells = gblender_lookup_channel( (gb), _gbback, _gbfore ); \ + } + + +#endif /* __GBENCH_CACHE_H__ */ diff --git a/kernel/kls_ttf/ftview/gblhbgr.h b/kernel/kls_ttf/ftview/gblhbgr.h new file mode 100644 index 0000000..a2740ab --- /dev/null +++ b/kernel/kls_ttf/ftview/gblhbgr.h @@ -0,0 +1,74 @@ + GBLENDER_CHANNEL_VARS(blender,r,g,b); + + int h = blit->height; + const unsigned char* src_line = blit->src_line; + unsigned char* dst_line = blit->dst_line; + + do + { + const unsigned char* src = src_line + blit->src_x*3; + unsigned char* dst = dst_line + blit->dst_x*GDST_INCR; + int w = blit->width; + + do + { + int ab = GBLENDER_SHADE_INDEX(src[0]); + int ag = GBLENDER_SHADE_INDEX(src[1]); + int ar = GBLENDER_SHADE_INDEX(src[2]); + int aa = (ar << 16) | (ag << 8) | ab; + + if ( aa == 0 ) + { + /* nothing */ + } + else if ( aa == ((GBLENDER_SHADE_COUNT << 16) | + (GBLENDER_SHADE_COUNT << 8) | + (GBLENDER_SHADE_COUNT) ) ) + { + GDST_COPY(dst); + } + else + { + GBlenderPixel back; + int pix_r, pix_g, pix_b; + + GDST_READ(dst,back); + + { + int back_r = (back >> 16) & 255; + + GBLENDER_LOOKUP_R( blender, back_r ); + + pix_r = _grcells[ar]; + } + + { + int back_g = (back >> 8) & 255; + + GBLENDER_LOOKUP_G( blender, back_g ); + + pix_g = _ggcells[ag]; + } + + { + int back_b = (back) & 255; + + GBLENDER_LOOKUP_B( blender, back_b ); + + pix_b = _gbcells[ab]; + } + + GDST_STOREC(dst,pix_r,pix_g,pix_b); + } + + src += 3; + dst += GDST_INCR; + } + while (--w > 0); + + src_line += blit->src_pitch; + dst_line += blit->dst_pitch; + } + while (--h > 0); + + GBLENDER_CHANNEL_CLOSE(blender); diff --git a/kernel/kls_ttf/ftview/gblhrgb.h b/kernel/kls_ttf/ftview/gblhrgb.h new file mode 100644 index 0000000..930a6c9 --- /dev/null +++ b/kernel/kls_ttf/ftview/gblhrgb.h @@ -0,0 +1,76 @@ + + GBLENDER_CHANNEL_VARS(blender,r,g,b); + + int h = blit->height; + const unsigned char* src_line = blit->src_line; + unsigned char* dst_line = blit->dst_line; + + do + { + const unsigned char* src = src_line + blit->src_x*3; + unsigned char* dst = dst_line + blit->dst_x*GDST_INCR; + int w = blit->width; + + do + { + int ar = GBLENDER_SHADE_INDEX(src[0]); + int ag = GBLENDER_SHADE_INDEX(src[1]); + int ab = GBLENDER_SHADE_INDEX(src[2]); + int aa = (ar << 16) | (ag << 8) | ab; + + if ( aa == 0 ) + { + /* nothing */ + } + else if ( aa == ((GBLENDER_SHADE_COUNT << 16) | + (GBLENDER_SHADE_COUNT << 8) | + (GBLENDER_SHADE_COUNT) ) ) + { + GDST_COPY(dst); + } + else + { + GBlenderPixel back; + int pix_r, pix_g, pix_b; + + GDST_READ(dst,back); + + { + int back_r = (back >> 16) & 255; + + GBLENDER_LOOKUP_R( blender, back_r ); + + pix_r = _grcells[ar]; + } + + { + int back_g = (back >> 8) & 255; + + GBLENDER_LOOKUP_G( blender, back_g ); + + pix_g = _ggcells[ag]; + } + + { + int back_b = (back) & 255; + + GBLENDER_LOOKUP_B( blender, back_b ); + + pix_b = _gbcells[ab]; + } + + GDST_STOREC(dst,pix_r,pix_g,pix_b); + } + + src += 3; + dst += GDST_INCR; + } + while (--w > 0); + + src_line += blit->src_pitch; + dst_line += blit->dst_pitch; + } + while (--h > 0); + + GBLENDER_CHANNEL_CLOSE(blender); + diff --git a/kernel/kls_ttf/ftview/gblvbgr.h b/kernel/kls_ttf/ftview/gblvbgr.h new file mode 100644 index 0000000..48565ff --- /dev/null +++ b/kernel/kls_ttf/ftview/gblvbgr.h @@ -0,0 +1,76 @@ + + GBLENDER_CHANNEL_VARS(blender,r,g,b); + + int h = blit->height; + const unsigned char* src_line = blit->src_line; + int src_pitch = blit->src_pitch; + unsigned char* dst_line = blit->dst_line; + + do + { + const unsigned char* src = src_line + blit->src_x; + unsigned char* dst = dst_line + blit->dst_x*GDST_INCR; + int w = blit->width; + + do + { + int ab = GBLENDER_SHADE_INDEX(src[0]); + int ag = GBLENDER_SHADE_INDEX(src[src_pitch]); + int ar = GBLENDER_SHADE_INDEX(src[src_pitch << 1]); + GBlenderPixel aa = ((GBlenderPixel)ar << 16) | (ag << 8) | ab; + + if ( aa == 0 ) + { + /* nothing */ + } + else if ( aa == ((GBLENDER_SHADE_COUNT << 16) | + (GBLENDER_SHADE_COUNT << 8) | + (GBLENDER_SHADE_COUNT) ) ) + { + GDST_COPY(dst); + } + else + { + GBlenderPixel back; + int pix_r, pix_g, pix_b; + + GDST_READ(dst,back); + + { + int back_r = (back >> 16) & 255; + + GBLENDER_LOOKUP_R( blender, back_r ); + + pix_r = _grcells[ar]; + } + + { + int back_g = (back >> 8) & 255; + + GBLENDER_LOOKUP_G( blender, back_g ); + + pix_g = _ggcells[ag]; + } + + { + int back_b = (back) & 255; + + GBLENDER_LOOKUP_B( blender, back_b ); + + pix_b = _gbcells[ab]; + } + + GDST_STOREC(dst,pix_r,pix_g,pix_b); + } + + src += 1; + dst += GDST_INCR; + } + while (--w > 0); + + src_line += blit->src_pitch*3; + dst_line += blit->dst_pitch; + } + while (--h > 0); + + GBLENDER_CHANNEL_CLOSE(blender); diff --git a/kernel/kls_ttf/ftview/gblvrgb.h b/kernel/kls_ttf/ftview/gblvrgb.h new file mode 100644 index 0000000..d31aaa9 --- /dev/null +++ b/kernel/kls_ttf/ftview/gblvrgb.h @@ -0,0 +1,76 @@ + + GBLENDER_CHANNEL_VARS(blender,r,g,b); + + int h = blit->height; + const unsigned char* src_line = blit->src_line; + int src_pitch = blit->src_pitch; + unsigned char* dst_line = blit->dst_line; + + do + { + const unsigned char* src = src_line + blit->src_x; + unsigned char* dst = dst_line + blit->dst_x*GDST_INCR; + int w = blit->width; + + do + { + int ar = GBLENDER_SHADE_INDEX(src[0]); + int ag = GBLENDER_SHADE_INDEX(src[src_pitch]); + int ab = GBLENDER_SHADE_INDEX(src[src_pitch << 1]); + GBlenderPixel aa = ((GBlenderPixel)ar << 16) | (ag << 8) | ab; + + if ( aa == 0 ) + { + /* nothing */ + } + else if ( aa == ((GBLENDER_SHADE_COUNT << 16) | + (GBLENDER_SHADE_COUNT << 8) | + (GBLENDER_SHADE_COUNT) ) ) + { + GDST_COPY(dst); + } + else + { + GBlenderPixel back; + int pix_r, pix_g, pix_b; + + GDST_READ(dst,back); + + { + int back_r = (back >> 16) & 255; + + GBLENDER_LOOKUP_R( blender, back_r ); + + pix_r = _grcells[ar]; + } + + { + int back_g = (back >> 8) & 255; + + GBLENDER_LOOKUP_G( blender, back_g ); + + pix_g = _ggcells[ag]; + } + + { + int back_b = (back) & 255; + + GBLENDER_LOOKUP_B( blender, back_b ); + + pix_b = _gbcells[ab]; + } + + GDST_STOREC(dst,pix_r,pix_g,pix_b); + } + + src += 1; + dst += GDST_INCR; + } + while (--w > 0); + + src_line += blit->src_pitch*3; + dst_line += blit->dst_pitch; + } + while (--h > 0); + + GBLENDER_CHANNEL_CLOSE(blender); diff --git a/kernel/kls_ttf/ftview/graph.h b/kernel/kls_ttf/ftview/graph.h new file mode 100644 index 0000000..81f1716 --- /dev/null +++ b/kernel/kls_ttf/ftview/graph.h @@ -0,0 +1,653 @@ +/*************************************************************************** + * + * graph.h + * + * Graphics Subsystem interface + * + * Copyright 1999, 2000, 2001, 2002 + * - The FreeType Development Team - www.freetype.org + * + ***************************************************************************/ + +#ifndef GRAPH_H +#define GRAPH_H + +#include "grevents.h" + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /******** ********/ + /******** GENERAL DEFINITIONS AND BLITTING ROUTINES ********/ + /******** ********/ + /******** ********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* define the global error variable */ + extern int grError; + + /* initialisation */ + extern int grInit( void ); + + /* finalisation */ + extern void grDone( void ); + + + /* pixel mode constants */ + typedef enum grPixelMode + { + gr_pixel_mode_none = 0, + gr_pixel_mode_mono, /* monochrome bitmaps */ + gr_pixel_mode_pal4, /* 4-bit paletted - 16 colors */ + gr_pixel_mode_pal8, /* 8-bit paletted - 256 colors */ + gr_pixel_mode_gray, /* 8-bit gray levels */ + gr_pixel_mode_rgb555, /* 15-bits mode - 32768 colors */ + gr_pixel_mode_rgb565, /* 16-bits mode - 65536 colors */ + gr_pixel_mode_rgb24, /* 24-bits mode - 16 million colors */ + gr_pixel_mode_rgb32, /* 32-bits mode - 16 million colors */ + gr_pixel_mode_lcd, /* horizontal RGB-decimated */ + gr_pixel_mode_lcdv, /* vertical RGB-decimated */ + gr_pixel_mode_lcd2, /* horizontal BGR-decimated */ + gr_pixel_mode_lcdv2, /* vertical BGR-decimated */ + + gr_pixel_mode_max /* don't remove */ + + } grPixelMode; + + + /* forward declaration of the surface class */ + typedef struct grSurface_ grSurface; + + + /********************************************************************* + * + * + * grBitmap + * + * + * a simple bitmap descriptor + * + * + * rows :: height in pixels + * width :: width in pixels + * pitch :: + or - the number of bytes per row + * mode :: pixel mode of bitmap buffer + * grays :: number of grays in palette for PAL8 mode. 0 otherwise + * buffer :: pointer to pixel buffer + * + * + * the 'pitch' is positive for downward flows, and negative otherwise + * Its absolute value is always the number of bytes taken by each + * bitmap row. + * + * All drawing operations will be performed within the first + * "width" pixels of each row (clipping is always performed). + * + ********************************************************************/ + + typedef struct grBitmap_ + { + int rows; + int width; + int pitch; + grPixelMode mode; + int grays; + unsigned char* buffer; + + } grBitmap; + + + + typedef long grPos; + typedef char grBool; + + typedef struct grVector_ + { + grPos x; + grPos y; + + } grVector; + + + typedef union grColor_ + { + long value; + unsigned char chroma[4]; + + } grColor; + + + + /********************************************************************** + * + * + * grNewBitmap + * + * + * creates a new bitmap + * + * + * pixel_mode :: the target surface's pixel_mode + * num_grays :: number of grays levels for PAL8 pixel mode + * width :: width in pixels + * height :: height in pixels + * + * + * bit :: descriptor of the new bitmap + * + * + * Error code. 0 means success. + * + * + * This function really allocates a pixel buffer, zero it, then + * returns a descriptor for it. + * + * Call grDoneBitmap when you're done with it.. + * + **********************************************************************/ + + extern int grNewBitmap( grPixelMode pixel_mode, + int num_grays, + int width, + int height, + grBitmap *bit ); + + + /********************************************************************** + * + * + * grBlitGlyphToBitmap + * + * + * writes a given glyph bitmap to a target surface. + * + * + * target :: handle to target bitmap + * glyph :: handle to source glyph bitmap + * x :: position of left-most pixel of glyph image in target surface + * y :: position of top-most pixel of glyph image in target surface + * color :: color to be used to draw a monochrome glyph + * + * + * Error code. 0 means success + * + * + * There are only two supported source pixel modes : monochrome + * and gray. The 8-bit images can have any number of grays between + * 2 and 128, and conversions to the target surface is handled + * _automatically_. + * + * Note however that you should avoid blitting a gray glyph to a gray + * bitmap with fewer levels of grays, as this would much probably + * give unpleasant results.. + * + * This function performs clipping + * + **********************************************************************/ + + extern int + grBlitGlyphToBitmap( grBitmap* target, + grBitmap* glyph, + grPos x, + grPos y, + grColor color ); + + + /********************************************************************** + * + * + * grFillRectangle + * + * + * this function is used to fill a given rectangle on a surface + * + * + * surface :: handle to target surface + * x :: x coordinate of the top-left corner of the rectangle + * y :: y coordinate of the top-left corner of the rectangle + * width :: rectangle width in pixels + * height :: rectangle height in pixels + * color :: fill color + * + **********************************************************************/ + + extern void grFillRectangle( grBitmap* surface, + grPos x, + grPos y, + grPos width, + grPos height, + grColor color ); + + + + /********************************************************************** + * + * + * grWriteCellChar + * + * + * The graphics sub-system contains an internal Latin1 8x8 font + * which can be used to display simple strings of text without + * using FreeType. + * + * This function writes a single 8x8 character on the target bitmap. + * + * + * target :: handle to target surface + * x :: x pixel position of character cell's top left corner + * y :: y pixel position of character cell's top left corner + * charcode :: Latin-1 character code + * color :: color to be used to draw the character + * + **********************************************************************/ + + extern + void grWriteCellChar( grBitmap* target, + int x, + int y, + int charcode, + grColor color ); + + + /********************************************************************** + * + * + * grWriteCellString + * + * + * The graphics sub-system contains an internal Latin1 8x8 font + * which can be used to display simple strings of text without + * using FreeType. + * + * This function writes a string with the internal font + * + * + * target :: handle to target bitmap + * x :: x pixel position of string's top left corner + * y :: y pixel position of string's top left corner + * string :: Latin-1 text string + * color :: color to be used to draw the character + * + **********************************************************************/ + + extern + void grWriteCellString( grBitmap* target, + int x, + int y, + const char* string, + grColor color ); + + /********************************************************************** + * + * + * grDoneBitmap + * + * + * destroys a bitmap + * + * + * bitmap :: handle to bitmap descriptor + * + * + * This function does NOT release the bitmap descriptor, only + * the pixel buffer. + * + **********************************************************************/ + + extern void grDoneBitmap( grBitmap* bit ); + + + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /******** ********/ + /******** DEVICE-SPECIFIC DEFINITIONS AND ROUTINES ********/ + /******** ********/ + /******** ********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* forward declaration - the definition of grDevice is not visible */ + /* to clients.. */ + typedef struct grDevice_ grDevice; + + + /********************************************************************** + * + * + * grDeviceChain + * + * + * a simple structure used to implement a linked list of + * graphics device descriptors. The list is called a + * "device chain" + * + * + * name :: ASCII name of the device, e.g. "x11", "os2pm", etc.. + * device :: handle to the device descriptor. + * next :: next element in chain + * + * + * the 'device' field is a blind pointer; it is thus unusable by + * client applications.. + * + **********************************************************************/ + + typedef struct grDeviceChain_ grDeviceChain; + + struct grDeviceChain_ + { + const char* name; + grDevice* device; + grDeviceChain* next; + }; + + + /********************************************************************** + * + * + * grInitDevices + * + * + * This function is in charge of initialising all system-specific + * devices. A device is responsible for creating and managing one + * or more "surfaces". A surface is either a window or a screen, + * depending on the system. + * + * + * a pointer to the first element of a device chain. The chain can + * be parsed to find the available devices on the current system + * + * + * If a device cannot be initialised correctly, it is not part of + * the device chain returned by this function. For example, if an + * X11 device was compiled in the library, it will be part of + * the returned device chain only if a connection to the display + * could be establisged + * + * If no driver could be initialised, this function returns NULL. + * + **********************************************************************/ + + extern + grDeviceChain* grInitDevices( void ); + + + + /********************************************************************** + * + * + * grGetDeviceModes + * + * + * queries the available pixel modes for a device. + * + * + * device_name :: name of device to be used. 0 for the default + * device. For a list of available devices, see + * grInitDevices. + * + * + * num_modes :: number of available modes. 0 in case of error, + * which really is an invalid device name. + * + * pixel_modes :: array of available pixel modes for this device + * this table is internal to the device and should + * not be freed by client applications. + * + * + * error code. 0 means success. invalid device name otherwise + * + * + * All drivers are _required_ to support at least the following + * pixel formats : + * + * - gr_pixel_mode_mono : i.e. monochrome bitmaps + * - gr_pixel_mode_gray : with any number of gray levels between + * 2 and 256. + * + * the pixel modes do not provide the number of grays in the case + * of "gray" devices. You should try to create a surface with the + * maximal number (256, that is) and see the value returned in + * the bitmap descriptor. + * + **********************************************************************/ + + extern void grGetDeviceModes( const char* device_name, + int *num_modes, + grPixelMode* *pixel_modes ); + + + + /********************************************************************** + * + * + * grNewSurface + * + * + * creates a new device-specific surface. A surface is either + * a window or a screen, depending on the device. + * + * + * device :: name of the device to use. A value of NULL means + * the default device (which depends on the system). + * for a list of available devices, see grInitDevices. + * + * + * bitmap :: handle to a bitmap descriptor containing the + * requested pixel mode, number of grays and dimensions + * for the surface. the bitmap's 'pitch' and 'buffer' + * fields are ignored on input. + * + * On output, the bitmap describes the surface's image + * completely. It is possible to write directly in it + * with grBlitGlyphToBitmap, even though the use of + * grBlitGlyphToSurface is recommended. + * + * + * handle to the corresponding surface object. 0 in case of error + * + * + * All drivers are _required_ to support at least the following + * pixel formats : + * + * - gr_pixel_mode_mono : i.e. monochrome bitmaps + * - gr_pixel_mode_gray : with any number of gray levels between + * 2 and 256. + * + * This function might change the bitmap descriptor's fields. For + * example, when displaying a full-screen surface, the bitmap's + * dimensions will be set to those of the screen (e.g. 640x480 + * or 800x600); also, the bitmap's 'buffer' field might point to + * the Video Ram depending on the mode requested.. + * + * The surface contains a copy of the returned bitmap descriptor, + * you can thus discard the 'bitmap' parameter after the call. + * + **********************************************************************/ + + extern grSurface* grNewSurface( const char* device, + grBitmap* bitmap ); + + + + /********************************************************************** + * + * + * grRefreshRectangle + * + * + * this function is used to indicate that a given surface rectangle + * was modified and thus needs re-painting. It really is useful for + * windowed or gray surfaces. + * + * + * surface :: handle to target surface + * x :: x coordinate of the top-left corner of the rectangle + * y :: y coordinate of the top-left corner of the rectangle + * width :: rectangle width in pixels + * height :: rectangle height in pixels + * + **********************************************************************/ + + extern void grRefreshRectangle( grSurface* surface, + grPos x, + grPos y, + grPos width, + grPos height ); + + + /********************************************************************** + * + * + * grRefreshSurface + * + * + * a variation of grRefreshRectangle which repaints the whole surface + * to the screen. + * + * + * surface :: handle to target surface + * + **********************************************************************/ + + extern void grRefreshSurface( grSurface* surface ); + + + + /********************************************************************** + * + * + * grWriteSurfaceChar + * + * + * This function is equivalent to calling grWriteCellChar on the + * surface's bitmap, then invoking grRefreshRectangle. + * + * The graphics sub-system contains an internal Latin1 8x8 font + * which can be used to display simple strings of text without + * using FreeType. + * + * This function writes a single 8x8 character on the target bitmap. + * + * + * target :: handle to target surface + * x :: x pixel position of character cell's top left corner + * y :: y pixel position of character cell's top left corner + * charcode :: Latin-1 character code + * color :: color to be used to draw the character + * + **********************************************************************/ + + extern + void grWriteSurfaceChar( grSurface* target, + int x, + int y, + int charcode, + grColor color ); + + + /********************************************************************** + * + * + * grWriteSurfaceString + * + * + * This function is equivalent to calling grWriteCellString on the + * surface's bitmap, then invoking grRefreshRectangle. + * + * The graphics sub-system contains an internal Latin1 8x8 font + * which can be used to display simple strings of text without + * using FreeType. + * + * This function writes a string with the internal font + * + * + * target :: handle to target bitmap + * x :: x pixel position of string's top left corner + * y :: y pixel position of string's top left corner + * string :: Latin-1 text string + * color :: color to be used to draw the character + * + **********************************************************************/ + + extern + void grWriteSurfaceString( grSurface* target, + int x, + int y, + const char* string, + grColor color ); + + + /********************************************************************** + * + * + * grSetTitle + * + * + * set the window title of a given windowed surface. + * + * + * surface :: handle to target surface + * title_string :: the new title + * + **********************************************************************/ + + extern void grSetTitle( grSurface* surface, + const char* title_string ); + + + + + /********************************************************************** + * + * + * grListenSurface + * + * + * listen the events for a given surface + * + * + * surface :: handle to target surface + * event_mask :: the event mask (mode) + * + * + * event :: the returned event + * + * + * XXX : For now, only keypresses are supported. + * + **********************************************************************/ + + extern + int grListenSurface( grSurface* surface, + int event_mask, + grEvent *event ); + + /********************************************************************** + * + * + * grSetGlyphGamma + * + * + * set the gamma-correction coefficient. This is only used to + * blit glyphs + * + * + * gamma :: gamma value. <= 0 to select sRGB transfer function + * + **********************************************************************/ + + extern + void grSetGlyphGamma( double gamma_value ); + +/* */ + +#endif /* GRAPH_H */ diff --git a/kernel/kls_ttf/ftview/grblit.cpp b/kernel/kls_ttf/ftview/grblit.cpp new file mode 100644 index 0000000..18046ab --- /dev/null +++ b/kernel/kls_ttf/ftview/grblit.cpp @@ -0,0 +1,2068 @@ +/****************************************************************************/ +/* */ +/* The FreeType project -- a free and portable quality TrueType renderer. */ +/* */ +/* Copyright 1996-1999, 2000, 2001, 2002 by */ +/* D. Turner, R.Wilhelm, and W. Lemberg */ +/* */ +/* grblit.c: Support for blitting of bitmaps with various depth. */ +/* */ +/****************************************************************************/ + +#include "grblit.h" +#include "grobjs.h" + +#include + +#define GRAY8 + + static + int compute_clips( grBlitter* blit, + int x_offset, + int y_offset ) + { + int xmin, ymin, xmax, ymax, width, height, target_width; + + /* perform clipping and setup variables */ + width = blit->source.width; + height = blit->source.rows; + + switch ( blit->source.mode ) + { + case gr_pixel_mode_mono: + width = (width + 7) & -8; + break; + + case gr_pixel_mode_pal4: + width = (width + 1) & -2; + break; + + case gr_pixel_mode_lcd: + case gr_pixel_mode_lcd2: + width /= 3; + break; + + case gr_pixel_mode_lcdv: + case gr_pixel_mode_lcdv2: + height /= 3; + break; + + default: + ; + } + + xmin = x_offset; + ymin = y_offset; + xmax = xmin + width-1; + ymax = ymin + height-1; + + /* clip if necessary */ + if ( width == 0 || height == 0 || + xmax < 0 || xmin >= blit->target.width || + ymax < 0 || ymin >= blit->target.rows ) + return 1; + + /* set up clipping and cursors */ + blit->yread = 0; + if ( ymin < 0 ) + { + blit->yread -= ymin; + height += ymin; + blit->ywrite = 0; + } + else + blit->ywrite = ymin; + + if ( ymax >= blit->target.rows ) + height -= ymax - blit->target.rows + 1; + + blit->xread = 0; + if ( xmin < 0 ) + { + blit->xread -= xmin; + width += xmin; + blit->xwrite = 0; + } + else + blit->xwrite = xmin; + + target_width = blit->target.width; + + switch ( blit->target.mode ) + { + case gr_pixel_mode_mono: + target_width = (target_width + 7) & -8; + break; + case gr_pixel_mode_pal4: + target_width = (target_width + 1) & -2; + break; + + default: + ; + } + + blit->right_clip = xmax - target_width + 1; + if ( blit->right_clip > 0 ) + width -= blit->right_clip; + else + blit->right_clip = 0; + + blit->width = width; + blit->height = height; + + /* set read and write to the top-left corner of the read */ + /* and write areas before clipping. */ + + blit->read = blit->source.buffer; + blit->write = blit->target.buffer; + + blit->read_line = blit->source.pitch; + blit->write_line = blit->target.pitch; + + if ( blit->read_line < 0 ) + blit->read -= (blit->source.rows-1) * blit->read_line; + + if ( blit->write_line < 0 ) + blit->write -= (blit->target.rows-1) * blit->write_line; + + /* now go to the start line. Note that we do not move the */ + /* x position yet, as this is dependent on the pixel format */ + blit->read += blit->yread * blit->read_line; + blit->write += blit->ywrite * blit->write_line; + + return 0; + } + + +/**************************************************************************/ +/* */ +/* blit_mono_to_mono */ +/* */ +/**************************************************************************/ + + static + void blit_mono_to_mono( grBlitter* blit, + grColor color ) + { + int shift, left_clip, x, y; + byte* read; + byte* write; + + (void)color; /* unused argument */ + + left_clip = ( blit->xread > 0 ); + shift = ( blit->xwrite - blit->xread ) & 7; + + read = blit->read + (blit->xread >> 3); + write = blit->write + (blit->xwrite >> 3); + + if ( shift == 0 ) + { + y = blit->height; + do + { + byte* _read = read; + byte* _write = write; + + x = blit->width; + + do + { + *_write++ |= *_read++; + x -= 8; + } while ( x > 0 ); + + read += blit->read_line; + write += blit->write_line; + y--; + } while ( y > 0 ); + } + else + { + int first, last, count; + + + first = blit->xwrite >> 3; + last = (blit->xwrite + blit->width-1) >> 3; + + count = last - first; + + if ( blit->right_clip ) + count++; + + y = blit->height; + + do + { + unsigned char* _read = read; + unsigned char* _write = write; + unsigned int old; + int shift2 = (8-shift); + + if ( left_clip ) + old = (*_read++) << shift2; + else + old = 0; + + x = count; + while ( x > 0 ) + { + unsigned char val; + + val = *_read++; + *_write++ |= (unsigned char)( (val >> shift) | old ); + old = val << shift2; + x--; + } + + if ( !blit->right_clip ) + *_write |= (unsigned char)old; + + read += blit->read_line; + write += blit->write_line; + y--; + + } while ( y > 0 ); + } + } + + +/**************************************************************************/ +/* */ +/* blit_mono_to_pal8 */ +/* */ +/**************************************************************************/ + + static + void blit_mono_to_pal8( grBlitter* blit, + grColor color ) + { + int x, y, shift; + unsigned char* read; + unsigned char* write; + + read = blit->read + (blit->xread >> 3); + write = blit->write + blit->xwrite; + shift = blit->xread & 7; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + unsigned long val = (*_read++ | 0x100) << shift; + + x = blit->width; + do + { + if (val & 0x10000) + val = *_read++ | 0x100; + + if ( val & 0x80 ) + *_write = (unsigned char)color.value; + + val <<= 1; + _write++; + + } while ( --x > 0 ); + + read += blit->read_line; + write += blit->write_line; + y--; + } while ( y > 0 ); + } + + +/**************************************************************************/ +/* */ +/* blit_mono_to_pal4 */ +/* */ +/**************************************************************************/ + + static + void blit_mono_to_pal4( grBlitter* blit, + grColor color ) + { + int x, y, phase,shift; + unsigned char* read; + unsigned char* write; + unsigned int col; + + + col = color.value & 15; + read = blit->read + (blit->xread >> 3); + write = blit->write + (blit->xwrite >> 1); + + /* now begin blit */ + shift = blit->xread & 7; + phase = blit->xwrite & 1; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int _phase = phase; + unsigned long val = (*_read++ | 0x100) << shift; + + x = blit->width; + do + { + if (val & 0x10000) + val = *_read++ | 0x100; + + if ( val & 0x80 ) + { + if ( _phase ) + *_write = (unsigned char)((*_write & 0xF0) | col); + else + *_write = (unsigned char)((*_write & 0x0F) | (col << 4)); + } + + val <<= 1; + + _write += _phase; + _phase ^= 1; + x--; + } while ( x > 0 ); + + read += blit->read_line; + write += blit->write_line; + y--; + } while ( y > 0 ); + } + + +/**************************************************************************/ +/* */ +/* blit_mono_to_rgb16 */ +/* */ +/**************************************************************************/ + + static + void blit_mono_to_rgb16( grBlitter* blit, + grColor color ) + { + int x, y,shift; + unsigned char* read; + unsigned char* write; + + read = blit->read + (blit->xread >> 3); + write = blit->write + blit->xwrite*2; + shift = blit->xread & 7; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + unsigned long val = (*_read++ | 0x100) << shift; + + x = blit->width; + do + { + if (val & 0x10000) + val = *_read++ | 0x100; + + if ( val & 0x80 ) + *(short*)_write = (short)color.value; + + val <<= 1; + _write +=2; + x--; + } while ( x > 0 ); + + read += blit->read_line; + write += blit->write_line; + y--; + } while ( y > 0 ); + } + + +/**************************************************************************/ +/* */ +/* blit_mono_to_rgb24 */ +/* */ +/**************************************************************************/ + + static + void blit_mono_to_rgb24( grBlitter* blit, + grColor color ) + { + int x, y, shift; + unsigned char* read; + unsigned char* write; + + read = blit->read + (blit->xread >> 3); + write = blit->write + blit->xwrite*3; + shift = blit->xread & 7; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + unsigned long val = (*_read++ | 0x100) << shift; + + x = blit->width; + do + { + if (val & 0x10000) + val = *_read++ | 0x100; + + if ( val & 0x80 ) + { + _write[0] = color.chroma[0]; + _write[1] = color.chroma[1]; + _write[2] = color.chroma[2]; + } + + val <<= 1; + _write += 3; + x--; + } while ( x > 0 ); + + read += blit->read_line; + write += blit->write_line; + y--; + } while ( y > 0 ); + } + + +/**************************************************************************/ +/* */ +/* blit_mono_to_rgb32 */ +/* */ +/**************************************************************************/ + + static + void blit_mono_to_rgb32( grBlitter* blit, + grColor color ) + { + int x, y,shift; + unsigned char* read; + unsigned char* write; + + read = blit->read + ( blit->xread >> 3 ); + write = blit->write + blit->xwrite*4; + shift = blit->xread & 7; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + unsigned long val = ( *_read++ | 0x100L ) << shift; + + x = blit->width; + do + { + if ( val & 0x10000 ) + val = *_read++ | 0x100L; + + if ( val & 0x80 ) + { + /* this could be greatly optimized as */ + /* */ + /* *(long*)_write = color.value */ + /* */ + /* but it wouldn't work on 64-bits systems... stupid C types! */ + _write[0] = color.chroma[0]; + _write[1] = color.chroma[1]; + _write[2] = color.chroma[2]; + _write[3] = color.chroma[3]; + } + + val <<= 1; + _write += 4; + x--; + + } while ( x > 0 ); + + read += blit->read_line; + write += blit->write_line; + y--; + + } while ( y > 0 ); + } + + + static + const grBlitterFunc gr_mono_blitters[gr_pixel_mode_max] = + { + 0, + blit_mono_to_mono, + blit_mono_to_pal4, + blit_mono_to_pal8, + blit_mono_to_pal8, + blit_mono_to_rgb16, + blit_mono_to_rgb16, + blit_mono_to_rgb24, + blit_mono_to_rgb32 + }; + + + /*******************************************************************/ + /* */ + /* Saturation tables */ + /* */ + /*******************************************************************/ + + typedef struct grSaturation_ + { + int count; + const byte* table; + + } grSaturation; + + + static + const byte gr_saturation_5[8] = { 0, 1, 2, 3, 4, 4, 4, 4 }; + + + static + const byte gr_saturation_17[32] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }; + + + static + grSaturation gr_saturations[ GR_MAX_SATURATIONS ] = + { + { 5, gr_saturation_5 }, + { 17, gr_saturation_17 } + }; + + static + int gr_num_saturations = 2; + + static + grSaturation* gr_last_saturation = gr_saturations; + + + extern + const byte* grGetSaturation( int num_grays ) + { + /* first of all, scan the current saturations table */ + grSaturation* sat = gr_saturations; + grSaturation* limit = sat + gr_num_saturations; + + if ( num_grays < 2 ) + { + grError = gr_err_bad_argument; + return 0; + } + + for ( ; sat < limit; sat++ ) + { + if ( sat->count == num_grays ) + { + gr_last_saturation = sat; + return sat->table; + } + } + + /* not found, simply create a new entry if there is room */ + if (gr_num_saturations < GR_MAX_SATURATIONS) + { + int i; + const byte* table; + + table = (const byte*)grAlloc( (3*num_grays-1)*sizeof(byte) ); + if (!table) return 0; + + sat->count = num_grays; + sat->table = table; + + for ( i = 0; i < num_grays; i++, table++ ) + *(unsigned char*)table = (unsigned char)i; + + for ( i = 2*num_grays-1; i > 0; i--, table++ ) + *(unsigned char*)table = (unsigned char)(num_grays-1); + + gr_num_saturations++; + gr_last_saturation = sat; + return sat->table; + } + grError = gr_err_saturation_overflow; + return 0; + } + + + + /*******************************************************************/ + /* */ + /* conversion tables */ + /* */ + /*******************************************************************/ + + typedef struct grConversion_ + { + int target_grays; + int source_grays; + const byte* table; + + } grConversion; + + + + static + const byte gr_gray5_to_gray17[5] = { 0, 4, 8, 12, 16 }; + + + static + const byte gr_gray5_to_gray128[5] = { 0, 32, 64, 96, 127 }; + + + static + const unsigned char gr_gray17_to_gray128[17] = + { + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 127 + }; + + static + grConversion gr_conversions[ GR_MAX_CONVERSIONS ] = + { + { 17, 5, gr_gray5_to_gray17 }, + { 128, 5, gr_gray5_to_gray128 }, + { 128, 17, gr_gray17_to_gray128 } + }; + + static + int gr_num_conversions = 3; + + static + grConversion* gr_last_conversion = gr_conversions; + + + extern + const byte* grGetConversion( int target_grays, + int source_grays ) + { + grConversion* conv = gr_conversions; + grConversion* limit = conv + gr_num_conversions; + + if ( target_grays < 2 || source_grays < 2 ) + { + grError = gr_err_bad_argument; + return 0; + } + + /* otherwise, scan table */ + for ( ; conv < limit; conv++ ) + { + if ( conv->target_grays == target_grays && + conv->source_grays == source_grays ) + { + gr_last_conversion = conv; + return conv->table; + } + } + + /* not found, add a new conversion to the table */ + if (gr_num_conversions < GR_MAX_CONVERSIONS) + { + const byte* table; + int n; + + table = (const byte*)grAlloc( source_grays*sizeof(byte) ); + if (!table) + return 0; + + conv->target_grays = target_grays; + conv->source_grays = source_grays; + conv->table = table; + + for ( n = 0; n < source_grays; n++ ) + ((unsigned char*)table)[n] = (unsigned char)(n*(target_grays-1) / + (source_grays-1)); + + gr_num_conversions++; + gr_last_conversion = conv; + return table; + } + grError = gr_err_conversion_overflow; + return 0; + } + + + + +/**************************************************************************/ +/* */ +/* blit_gray_to_gray */ +/* */ +/**************************************************************************/ + + static + void blit_gray_to_gray( grBlitter* blit, + const byte* saturation, + const byte* conversion ) + { + int y; + unsigned char* read; + unsigned char* write; + unsigned char max1; + unsigned char max2; + + max1 = (unsigned char)(blit->source.grays-1); + max2 = (unsigned char)(blit->target.grays-1); + + read = blit->read + blit->xread; + write = blit->write + blit->xwrite; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { +#ifdef GR_CONFIG_GRAY_SKIP_WHITE + unsigned char val = *_read; + + if (val) + { + if (val == max) + *_write = max2; + else + *_write = saturation[ (int)*_write + conversion[ *_read ] ]; + } +#else + *_write = saturation[ (int)*_write + conversion[ *_read ] ]; +#endif + _write++; + _read++; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + +/**************************************************************************/ +/* */ +/* blit_gray_to_gray_simple */ +/* */ +/**************************************************************************/ + + static + void blit_gray_to_gray_simple( grBlitter* blit, + const byte* saturation ) + { + int y; + unsigned char* read; + unsigned char* write; + unsigned char max; + + max = (unsigned char)(blit->source.grays-1); + + read = blit->read + blit->xread; + write = blit->write + blit->xwrite; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { +#ifdef GR_CONFIG_GRAY_SKIP_WHITE + unsigned char val = *_read; + + if (val) + { + if (val == max) + *_write = val; + else + *_write = saturation[ (int)*_write + *_read ]; + } +#else + *_write = saturation[ (int)*_write + *_read ]; +#endif + _write++; + _read++; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + + +#define compose_pixel_full( a, b, n0, n1, n2, max ) \ + { \ + int d, half = max >> 1; \ + \ + \ + d = (int)b.chroma[0] - a.chroma[0]; \ + a.chroma[0] += (unsigned char)((n0*d + half)/max); \ + \ + d = (int)b.chroma[1] - a.chroma[1]; \ + a.chroma[1] += (unsigned char)((n1*d + half)/max); \ + \ + d = (int)b.chroma[2] - a.chroma[2]; \ + a.chroma[2] += (unsigned char)((n2*d + half)/max); \ + } + +#define compose_pixel( a, b, n, max ) \ + compose_pixel_full( a, b, n, n, n, max ) + + +#define extract555( pixel, color ) \ + color.chroma[0] = (unsigned char)((pixel >> 10) & 0x1F); \ + color.chroma[1] = (unsigned char)((pixel >> 5) & 0x1F); \ + color.chroma[2] = (unsigned char)((pixel ) & 0x1F); + + +#define extract565( pixel, color ) \ + color.chroma[0] = (unsigned char)((pixel >> 11) & 0x1F); \ + color.chroma[1] = (unsigned char)((pixel >> 5) & 0x3F); \ + color.chroma[2] = (unsigned char)((pixel ) & 0x1F); + + +#define inject555( color ) \ + ( ( (unsigned short)color.chroma[0] << 10 ) | \ + ( (unsigned short)color.chroma[1] << 5 ) | \ + color.chroma[2] ) + + +#define inject565( color ) \ + ( ( (unsigned short)color.chroma[0] << 11 ) | \ + ( (unsigned short)color.chroma[1] << 5 ) | \ + color.chroma[2] ) + + +/**************************************************************************/ +/* */ +/* blit_gray_to_555 */ +/* */ +/**************************************************************************/ + +#ifdef GRAY8 + static + void blit_gray8_to_555( grBlitter* blit, + grColor color ) + { + int y; + int sr = (color.chroma[0] << 8) & 0x7C00; + int sg = (color.chroma[1] << 2) & 0x03E0; + int sb = (color.chroma[2] ) & 0x001F; + unsigned char* read; + unsigned char* write; + long color2; + + read = blit->read + blit->xread; + write = blit->write + 2*blit->xwrite; + + color2 = color.value; + extract565( color2, color ); + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + unsigned char val; + + val = *_read; + if (val) + { + unsigned short* pixel = (unsigned short*)_write; + + if (val >= 254 ) + { + pixel[0] = (short)color2; + } + else if ( val >= 2 ) + { + /* compose gray value */ + int pix = (int)*pixel; + int dr = pix & 0x7C00; + int dg = pix & 0x03E0; + int db = pix & 0x001F; + + dr = pix & 0x7C00; + dr += ((sr-dr)*val) >> 8; + dr &= 0xF800; + + dg = pix & 0x03E0; + dg += ((sg-dg)*val) >> 8; + dg &= 0x7E0; + + db = pix & 0x001F; + db += ((sb-db)*val) >> 8; + db += 0x001F; + + *pixel = (short)( dr | dg | db ); + } + } + _write +=2; + _read ++; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + + } +#endif /* GRAY8 */ + + static + void blit_gray_to_555( grBlitter* blit, + grColor color, + int max ) + { + int y; + unsigned char* read; + unsigned char* write; + long color2; + + read = blit->read + blit->xread; + write = blit->write + 2*blit->xwrite; + + /* convert color to R:G:B triplet */ + color2 = color.value; + extract555( color2, color ); + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + unsigned char val; + + val = *_read; + if (val) + { + unsigned short* pixel = (unsigned short*)_write; + + if (val == max) + { + pixel[0] = (short)color2; + } + else + { + /* compose gray value */ + unsigned short pix16 = *pixel; + grColor pix; + + extract555( pix16, pix ); + + compose_pixel( pix, color, val, max ); + *pixel = (unsigned short)(inject555(pix)); + } + } + _write += 2; + _read ++; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + +/**************************************************************************/ +/* */ +/* blit_gray_to_565 */ +/* */ +/**************************************************************************/ + +#ifdef GRAY8 + static + void blit_gray8_to_565( grBlitter* blit, + grColor color ) + { + int y; + int sr = (color.chroma[0] << 8) & 0xF800; + int sg = (color.chroma[1] << 2) & 0x07E0; + int sb = (color.chroma[2] ) & 0x001F; + unsigned char* read; + unsigned char* write; + long color2; + + read = blit->read + blit->xread; + write = blit->write + 2*blit->xwrite; + + color2 = color.value; + extract565( color2, color ); + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + unsigned char val; + + val = *_read; + if (val) + { + unsigned short* pixel = (unsigned short*)_write; + + if (val >= 254 ) + { + pixel[0] = (short)color2; + } + else if ( val >= 2 ) + { + /* compose gray value */ + int pix = (int)*pixel; + int dr = pix & 0xF800; + int dg = pix & 0x07E0; + int db = pix & 0x001F; + + dr = pix & 0xF800; + dr += ((sr-dr)*val) >> 8; + dr &= 0xF800; + + dg = pix & 0x07E0; + dg += ((sg-dg)*val) >> 8; + dg &= 0x7E0; + + db = pix & 0x001F; + db += ((sb-db)*val) >> 8; + db += 0x001F; + + *pixel = (short)( dr | dg | db ); + } + } + _write +=2; + _read ++; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } +#endif + + static + void blit_gray_to_565( grBlitter* blit, + grColor color, + int max ) + { + int y; + unsigned char* read; + unsigned char* write; + long color2; + + read = blit->read + blit->xread; + write = blit->write + 2*blit->xwrite; + + color2 = color.value; + extract565( color2, color ); + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + unsigned char val; + + val = *_read; + if (val) + { + unsigned short* pixel = (unsigned short*)_write; + + if (val == max) + { + pixel[0] = (short)color2; + } + else + { + /* compose gray value */ + unsigned short pix16 = *pixel; + grColor pix; + + extract565( pix16, pix ); + + compose_pixel( pix, color, val, max ); + *pixel = (short)inject565( pix ); + } + } + _write +=2; + _read ++; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + +/**************************************************************************/ +/* */ +/* blit_gray_to_24 */ +/* */ +/**************************************************************************/ + +#ifdef GRAY8 + static void + blit_gray8_to_24( grBlitter* blit, + grColor color ) + { + int y; + int sr = color.chroma[0]; + int sg = color.chroma[1]; + int sb = color.chroma[2]; + unsigned char* read; + unsigned char* write; + + read = blit->read + blit->xread; + write = blit->write + 3*blit->xwrite; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + unsigned char val; + + val = *_read; + if (val) + { + if (val >= 254) + { + _write[0] = (unsigned char)sr; + _write[1] = (unsigned char)sg; + _write[2] = (unsigned char)sb; + } + else if ( val >= 2 ) + { + int dr = _write[0]; + int dg = _write[1]; + int db = _write[2]; + + dr += ((sr-dr)*val) >> 8; + dg += ((sg-dg)*val) >> 8; + db += ((sb-db)*val) >> 8; + + _write[0] = (unsigned char)dr; + _write[1] = (unsigned char)dg, + _write[2] = (unsigned char)db; + } + } + _write += 3; + _read ++; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } +#endif /* GRAY8 */ + + + static + void blit_gray_to_24( grBlitter* blit, + grColor color, + int max ) + { + int y; + unsigned char* read; + unsigned char* write; + + read = blit->read + blit->xread; + write = blit->write + 3*blit->xwrite; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + unsigned char val; + + val = *_read; + if (val) + { + if (val == max) + { + _write[0] = color.chroma[0]; + _write[1] = color.chroma[1]; + _write[2] = color.chroma[2]; + } + else + { + /* compose gray value */ + grColor pix; + + pix.chroma[0] = _write[0]; + pix.chroma[1] = _write[1]; + pix.chroma[2] = _write[2]; + + compose_pixel( pix, color, val, max ); + + _write[0] = pix.chroma[0]; + _write[1] = pix.chroma[1]; + _write[2] = pix.chroma[2]; + } + } + _write += 3; + _read ++; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + +/**************************************************************************/ +/* */ +/* blit_gray_to_32 */ +/* */ +/**************************************************************************/ + + static + void blit_gray_to_32( grBlitter* blit, + grColor color, + int max ) + { + int y; + unsigned char* read; + unsigned char* write; + + read = blit->read + blit->xread; + write = blit->write + 4*blit->xwrite; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + unsigned char val; + + val = *_read; + if (val) + { + if (val == max) + { + _write[0] = color.chroma[0]; + _write[1] = color.chroma[1]; + _write[2] = color.chroma[2]; + _write[3] = color.chroma[3]; + } + else + { + /* compose gray value */ + grColor pix; + + pix.chroma[0] = _write[0]; + pix.chroma[1] = _write[1]; + pix.chroma[2] = _write[2]; + + compose_pixel( pix, color, val, max ); + + _write[0] = pix.chroma[0]; + _write[1] = pix.chroma[1]; + _write[2] = pix.chroma[2]; + } + } + _write += 4; + _read ++; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + + static + void blit_gray8_to_32( grBlitter* blit, + grColor color ) + { + blit_gray_to_32( blit, color, 255 ); + } + + +/**************************************************************************/ +/* */ +/* blit_lcd_to_24 */ +/* */ +/**************************************************************************/ + +#ifdef GRAY8 + static void + blit_lcd8_to_24( grBlitter* blit, + grColor color ) + { + int y; + int sr = color.chroma[0]; + int sg = color.chroma[1]; + int sb = color.chroma[2]; + unsigned char* read; + unsigned char* write; + + read = blit->read + 3*blit->xread; + write = blit->write + 3*blit->xwrite; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + int val0, val1, val2; + + val0 = _read[0]; + val1 = _read[1]; + val2 = _read[2]; + + if ( val0 | val1 | val2 ) + { + if ( val0 == val1 && + val0 == val2 && + val0 == 255 ) + { + _write[0] = (unsigned char)sr; + _write[1] = (unsigned char)sg; + _write[2] = (unsigned char)sb; + } + else + { + /* compose gray value */ + int dr, dg, db; + + dr = _write[0]; + dr += (sr-dr)*val0 >> 8; + + dg = _write[1]; + dg += (sg-dg)*val1 >> 8; + + db = _write[1]; + db += (sb-db)*val2 >> 8; + + _write[0] = dr; + _write[1] = dg; + _write[2] = db; + } + } + _write += 3; + _read += 3; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } +#endif /* GRAY8 */ + + static void + blit_lcd_to_24( grBlitter* blit, + grColor color, + int max ) + { + int y; + unsigned char* read; + unsigned char* write; + + read = blit->read + 3*blit->xread; + write = blit->write + 3*blit->xwrite; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + int val0, val1, val2; + + val0 = _read[0]; + val1 = _read[1]; + val2 = _read[2]; + + if ( val0 | val1 | val2 ) + { + if ( val0 == val1 && + val0 == val2 && + val0 == max ) + { + _write[0] = color.chroma[0]; + _write[1] = color.chroma[1]; + _write[2] = color.chroma[2]; + } + else + { + /* compose gray value */ + grColor pix; + + pix.chroma[0] = _write[0]; + pix.chroma[1] = _write[1]; + pix.chroma[2] = _write[2]; + + compose_pixel_full( pix, color, val0, val1, val2, max ); + + _write[0] = pix.chroma[0]; + _write[1] = pix.chroma[1]; + _write[2] = pix.chroma[2]; + } + } + _write += 3; + _read += 3; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + +#ifdef GRAY8 + static void + blit_lcd28_to_24( grBlitter* blit, + grColor color ) + { + int y; + int sr = color.chroma[0]; + int sg = color.chroma[1]; + int sb = color.chroma[2]; + unsigned char* read; + unsigned char* write; + + read = blit->read + 3*blit->xread; + write = blit->write + 3*blit->xwrite; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + int val0, val1, val2; + + val0 = _read[2]; + val1 = _read[1]; + val2 = _read[0]; + + if ( val0 | val1 | val2 ) + { + if ( val0 == val1 && + val0 == val2 && + val0 == 255 ) + { + _write[0] = (unsigned char)sr; + _write[1] = (unsigned char)sg; + _write[2] = (unsigned char)sb; + } + else + { + /* compose gray value */ + int dr, dg, db; + + dr = _write[0]; + dr += (sr-dr)*val0 >> 8; + + dg = _write[1]; + dg += (sg-dg)*val1 >> 8; + + db = _write[1]; + db += (sb-db)*val2 >> 8; + + _write[0] = dr; + _write[1] = dg; + _write[2] = db; + } + } + _write += 3; + _read += 3; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } +#endif /* GRAY8 */ + + static void + blit_lcd2_to_24( grBlitter* blit, + grColor color, + int max ) + { + int y; + unsigned char* read; + unsigned char* write; + + read = blit->read + 3*blit->xread; + write = blit->write + 3*blit->xwrite; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + int val0, val1, val2; + + val0 = _read[2]; + val1 = _read[1]; + val2 = _read[0]; + + if ( val0 | val1 | val2 ) + { + if ( val0 == val1 && + val0 == val2 && + val0 == max ) + { + _write[0] = color.chroma[0]; + _write[1] = color.chroma[1]; + _write[2] = color.chroma[2]; + } + else + { + /* compose gray value */ + grColor pix; + + pix.chroma[0] = _write[0]; + pix.chroma[1] = _write[1]; + pix.chroma[2] = _write[2]; + + compose_pixel_full( pix, color, val0, val1, val2, max ); + + _write[0] = pix.chroma[0]; + _write[1] = pix.chroma[1]; + _write[2] = pix.chroma[2]; + } + } + _write += 3; + _read += 3; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + +/**************************************************************************/ +/* */ +/* blit_lcdv_to_24 */ +/* */ +/**************************************************************************/ + + static void + blit_lcdv_to_24( grBlitter* blit, + grColor color, + int max ) + { + int y; + unsigned char* read; + unsigned char* write; + long line; + + read = blit->read + blit->xread; + write = blit->write + 3*blit->xwrite; + line = blit->read_line; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + unsigned char val0, val1, val2; + + val0 = _read[0*line]; + val1 = _read[1*line]; + val2 = _read[2*line]; + + if ( val0 | val1 | val2 ) + { + if ( val0 == val1 && + val0 == val2 && + val0 == max ) + { + _write[0] = color.chroma[0]; + _write[1] = color.chroma[1]; + _write[2] = color.chroma[2]; + } + else + { + /* compose gray value */ + grColor pix; + + pix.chroma[0] = _write[0]; + pix.chroma[1] = _write[1]; + pix.chroma[2] = _write[2]; + + compose_pixel_full( pix, color, val0, val1, val2, max ); + + _write[0] = pix.chroma[0]; + _write[1] = pix.chroma[1]; + _write[2] = pix.chroma[2]; + } + } + _write += 3; + _read += 1; + x--; + } + + read += 3*line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + + static void + blit_lcdv2_to_24( grBlitter* blit, + grColor color, + int max ) + { + int y; + unsigned char* read; + unsigned char* write; + long line; + + read = blit->read + blit->xread; + write = blit->write + 3*blit->xwrite; + line = blit->read_line; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + unsigned char val0, val1, val2; + + val0 = _read[2*line]; + val1 = _read[1*line]; + val2 = _read[0*line]; + + if ( val0 | val1 | val2 ) + { + if ( val0 == val1 && + val0 == val2 && + val0 == max ) + { + _write[0] = color.chroma[0]; + _write[1] = color.chroma[1]; + _write[2] = color.chroma[2]; + } + else + { + /* compose gray value */ + grColor pix; + + pix.chroma[0] = _write[0]; + pix.chroma[1] = _write[1]; + pix.chroma[2] = _write[2]; + + compose_pixel_full( pix, color, val0, val1, val2, max ); + + _write[0] = pix.chroma[0]; + _write[1] = pix.chroma[1]; + _write[2] = pix.chroma[2]; + } + } + _write += 3; + _read += 1; + x--; + } + + read += 3*line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + + /********************************************************************** + * + * + * grBlitGlyphBitmap + * + * + * writes a given glyph bitmap to a target surface. + * + * + * surface :: handle to target surface + * x :: position of left-most pixel of glyph image in surface + * y :: position of top-most pixel of glyph image in surface + * bitmap :: source glyph image + * + * + * Error code. 0 means success + * + **********************************************************************/ + + typedef void (*grColorGlyphBlitter)( grBlitter* blit, + grColor color, + int max_gray ); + + static + const grColorGlyphBlitter gr_color_blitters[gr_pixel_mode_max] = + { + 0, + 0, + 0, + 0, + 0, + blit_gray_to_555, + blit_gray_to_565, + blit_gray_to_24, + blit_gray_to_32 + }; + +#ifdef GRAY8 + typedef void (*grGray8GlyphBlitter)( grBlitter* blit, + grColor color ); + + static + const grGray8GlyphBlitter gr_gray8_blitters[gr_pixel_mode_max] = + { + 0, + 0, + 0, + 0, + 0, + blit_gray8_to_555, + blit_gray8_to_565, + blit_gray8_to_24, + blit_gray8_to_32 + }; +#endif + + +#include "gblblit.h" + + static double gr_glyph_gamma = 1.0; + + void grSetGlyphGamma( double gamma ) + { + gr_glyph_gamma = gamma; + } + + + int + grBlitGlyphToBitmap( grBitmap* target, + grBitmap* glyph, + grPos x, + grPos y, + grColor color ) + { + grBlitter blit; + grPixelMode mode; + + + /* check arguments */ + if ( !target || !glyph ) + { + grError = gr_err_bad_argument; + return -1; + } + + /* short cut to alpha blender for certain glyph types + */ + { + GBlenderSourceFormat src_format; + GBlenderTargetFormat dst_format; + int width, height; + GBlenderBlitRec gblit[1]; + GBlenderPixel gcolor; + static GBlenderRec gblender[1]; + static double gblender_gamma = -100.0; + + if ( glyph->grays != 256 ) + goto DefaultBlit; + + switch ( glyph->mode ) + { + case gr_pixel_mode_gray: src_format = GBLENDER_SOURCE_GRAY8; break; + case gr_pixel_mode_lcd: src_format = GBLENDER_SOURCE_HRGB; break; + case gr_pixel_mode_lcdv: src_format = GBLENDER_SOURCE_VRGB; break; + case gr_pixel_mode_lcd2: src_format = GBLENDER_SOURCE_HBGR; break; + case gr_pixel_mode_lcdv2: src_format = GBLENDER_SOURCE_VBGR; break; + + default: + goto DefaultBlit; + } + + width = glyph->width; + height = glyph->rows; + + if ( glyph->mode == gr_pixel_mode_lcd || + glyph->mode == gr_pixel_mode_lcd2 ) + width /= 3; + + if ( glyph->mode == gr_pixel_mode_lcdv || + glyph->mode == gr_pixel_mode_lcdv2 ) + height /= 3; + + switch ( target->mode ) + { + case gr_pixel_mode_rgb32: dst_format = GBLENDER_TARGET_RGB32; break; + case gr_pixel_mode_rgb24: dst_format = GBLENDER_TARGET_RGB24; break; + case gr_pixel_mode_rgb565: dst_format = GBLENDER_TARGET_RGB565; break; + default: + goto DefaultBlit; + } + + /* initialize blender when needed, i.e. when gamma changes + */ + if ( gblender_gamma != gr_glyph_gamma ) + { + gblender_gamma = gr_glyph_gamma; + gblender_init( gblender, gblender_gamma ); + } + + if ( gblender_blit_init( gblit, gblender, + x, y, + src_format, + glyph->buffer, + glyph->pitch, + width, + height, + dst_format, + target->buffer, + target->pitch, + target->width, + target->rows ) < 0 ) + { + /* nothing to do */ + return 0; + } + + gcolor = ((GBlenderPixel)color.chroma[0] << 16) | + ((GBlenderPixel)color.chroma[1] << 8 ) | + ((GBlenderPixel)color.chroma[2] ) ; + + gblender_blit_run( gblit, gcolor ); + return 1; + } + + DefaultBlit: + + /* set up blitter and compute clipping. Return immediately if needed */ + blit.source = *glyph; + blit.target = *target; + mode = target->mode; + + if ( compute_clips( &blit, x, y ) ) + return 0; + + switch ( glyph->mode ) + { + case gr_pixel_mode_mono: /* handle monochrome bitmap blitting */ + if ( mode <= gr_pixel_mode_none || mode >= gr_pixel_mode_max ) + { + grError = gr_err_bad_source_depth; + return -1; + } + + gr_mono_blitters[mode]( &blit, color ); + break; + + case gr_pixel_mode_gray: + if ( glyph->grays > 1 ) + { + int target_grays = target->grays; + int source_grays = glyph->grays; + const byte* saturation; + + + if ( mode == gr_pixel_mode_gray && target_grays > 1 ) + { + /* rendering into a gray target - use special composition */ + /* routines.. */ + if ( gr_last_saturation->count == target_grays ) + saturation = gr_last_saturation->table; + else + { + saturation = grGetSaturation( target_grays ); + if ( !saturation ) + return -3; + } + + if ( target_grays == source_grays ) + blit_gray_to_gray_simple( &blit, saturation ); + else + { + const byte* conversion; + + + if ( gr_last_conversion->target_grays == target_grays && + gr_last_conversion->source_grays == source_grays ) + conversion = gr_last_conversion->table; + else + { + conversion = grGetConversion( target_grays, source_grays ); + if ( !conversion ) + return -3; + } + + blit_gray_to_gray( &blit, saturation, conversion ); + } + } + else + { + /* rendering into a color target */ + if ( mode <= gr_pixel_mode_gray || + mode >= gr_pixel_mode_max ) + { + grError = gr_err_bad_target_depth; + return -1; + } + +#ifdef GRAY8 + if ( source_grays == 256 ) + gr_gray8_blitters[mode]( &blit, color ); + else +#endif /* GRAY8 */ + gr_color_blitters[mode]( &blit, color, source_grays - 1 ); + } + } + break; + + case gr_pixel_mode_lcd: + if ( mode == gr_pixel_mode_rgb24 ) + { +#ifdef GRAY8 + if ( glyph->grays == 256 ) + blit_lcd8_to_24( &blit, color ); + else +#endif + if ( glyph->grays > 1 ) + blit_lcd_to_24( &blit, color, glyph->grays-1 ); + } + break; + + + case gr_pixel_mode_lcdv: + if ( glyph->grays > 1 && mode == gr_pixel_mode_rgb24 ) + { + blit_lcdv_to_24( &blit, color, glyph->grays-1 ); + break; + } + + case gr_pixel_mode_lcd2: + if ( mode == gr_pixel_mode_rgb24 ) + { +#ifdef GRAY8 + if ( glyph->grays == 256 ) + blit_lcd28_to_24( &blit, color ); + else +#endif + if ( glyph->grays > 1 ) + blit_lcd2_to_24( &blit, color, glyph->grays-1 ); + } + break; + + case gr_pixel_mode_lcdv2: + if ( mode == gr_pixel_mode_rgb24 ) + { + if ( glyph->grays > 1 ) + blit_lcdv2_to_24( &blit, color, glyph->grays-1 ); + } + break; + + default: + /* we don't support the blitting of bitmaps of the following */ + /* types : pal4, pal8, rgb555, rgb565, rgb24, rgb32 */ + /* */ + grError = gr_err_bad_source_depth; + return -2; + } + + return 0; + } + + +/* End */ diff --git a/kernel/kls_ttf/ftview/grblit.h b/kernel/kls_ttf/ftview/grblit.h new file mode 100644 index 0000000..4d0b6e5 --- /dev/null +++ b/kernel/kls_ttf/ftview/grblit.h @@ -0,0 +1,25 @@ +/****************************************************************************/ +/* */ +/* The FreeType project -- a free and portable quality TrueType renderer. */ +/* */ +/* Copyright 1996-1999 by */ +/* D. Turner, R.Wilhelm, and W. Lemberg */ +/* */ +/* blitter.h: Support for blitting of bitmaps with various depth. */ +/* */ +/****************************************************************************/ + +#ifndef GRBLIT_H +#define GRBLIT_H + +#include "grobjs.h" + + int grBlitMono( grBitmap* target, + grBitmap* source, + int x_offset, + int y_offset, + grColor color ); + + +#endif /* GRBLIT_H */ +/* End */ diff --git a/kernel/kls_ttf/ftview/grconfig.h b/kernel/kls_ttf/ftview/grconfig.h new file mode 100644 index 0000000..02d8f4d --- /dev/null +++ b/kernel/kls_ttf/ftview/grconfig.h @@ -0,0 +1,9 @@ +#ifndef GRCONFIG_H +#define GRCONFIG_H + +#define GR_MAX_SATURATIONS 8 +#define GR_MAX_CONVERSIONS 16 + +#define GR_MAX_DEVICES 8 + +#endif /* GRCONFIG_H */ diff --git a/kernel/kls_ttf/ftview/grevents.h b/kernel/kls_ttf/ftview/grevents.h new file mode 100644 index 0000000..36dd52d --- /dev/null +++ b/kernel/kls_ttf/ftview/grevents.h @@ -0,0 +1,117 @@ +#ifndef GREVENTS_H +#define GREVENTS_H + + +#define gr_event_none 0 +#define gr_event_wait 1 +#define gr_event_poll 2 +#define gr_event_flush 3 + +#define gr_mouse_down 0x04 +#define gr_mouse_move 0x08 +#define gr_mouse_up 0x10 +#define gr_mouse_drag 0x20 + +#define gr_key_down 0x40 +#define gr_key_up 0x80 + + +#define gr_event_mouse 0x3C +#define gr_event_key 0xC0 + +#define gr_event_type (gr_event_mouse | gr_event_key) + + + typedef enum grKey_ + { + grKeyNone = 0, + + grKeyF1, + grKeyF2, + grKeyF3, + grKeyF4, + grKeyF5, + grKeyF6, + grKeyF7, + grKeyF8, + grKeyF9, + grKeyF10, + grKeyF11, + grKeyF12, + + grKeyLeft, + grKeyRight, + grKeyUp, + grKeyDown, + + grKeyIns, + grKeyDel, + grKeyHome, + grKeyEnd, + grKeyPageUp, + grKeyPageDown, + + grKeyEsc, + grKeyTab, + grKeyBackSpace, + grKeyReturn, + + grKeyMax, + grKeyForceShort = 0x7FFF /* this forces the grKey to be stored */ + /* on at least one short ! */ + + } grKey; + +#define grKEY(c) ((grKey)(c)) + +#define grKeyAlt ((grKey)0x8000) +#define grKeyCtrl ((grKey)0x4000) +#define grKeyShift ((grKey)0x2000) + +#define grKeyModifiers ((grKey)0xE000) + +#define grKey0 grKEY('0') +#define grKey1 grKEY('1') +#define grKey2 grKEY('2') +#define grKey3 grKEY('3') +#define grKey4 grKEY('4') +#define grKey5 grKEY('5') +#define grKey6 grKEY('6') +#define grKey7 grKEY('7') +#define grKey8 grKEY('8') +#define grKey9 grKEY('9') + + +#define grKeyPlus grKEY('+') +#define grKeyLess grKEY('-') +#define grKeyEqual grKEY('=') +#define grKeyMult grKEY('*') +#define grKeyDollar grKEY('$') +#define grKeySmaller grKEY('<') +#define grKeyGreater grKEY('>') +#define grKeyQuestion grKEY('?') +#define grKeyComma grKEY(',') +#define grKeyDot grKEY('.') +#define grKeySemiColumn grKEY(';') +#define grKeyColumn grKEY(':') +#define grKeyDiv grKEY('/') +#define grKeyExclam grKEY('!') +#define grKeyPercent grKEY('%') +#define grKeyLeftParen grKEY('(') +#define grKeyRightParen grKEY('(') +#define grKeyAt grKEY('@') +#define grKeyUnder grKEY('_') + + + typedef struct grEvent_ + { + int type; + grKey key; + int x, y; + + } grEvent; + + + +#endif /* GREVENTS_H */ + diff --git a/kernel/kls_ttf/ftview/grfont.cpp b/kernel/kls_ttf/ftview/grfont.cpp new file mode 100644 index 0000000..b6dfa3b --- /dev/null +++ b/kernel/kls_ttf/ftview/grfont.cpp @@ -0,0 +1,373 @@ + +#include "grfont.h" +#include + + /* font characters */ + + const unsigned char font_8x8[2048] = + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E, + 0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E, + 0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, + 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, + 0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x92, 0x10, 0x7C, + 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C, + 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, + 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, + 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, + 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, + 0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78, + 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, + 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x70, 0xF0, 0xE0, + 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0, + 0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99, + 0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00, + 0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00, + 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, + 0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00, + 0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0x86, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00, + 0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF, + 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, + 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, + 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, + 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, + 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00, + 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, + 0x18, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x18, 0x00, + 0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00, + 0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00, + 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, + 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, + 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, + 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, + 0x7C, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0x7C, 0x00, + 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xFC, 0x00, + 0x78, 0xCC, 0x0C, 0x38, 0x60, 0xCC, 0xFC, 0x00, + 0x78, 0xCC, 0x0C, 0x38, 0x0C, 0xCC, 0x78, 0x00, + 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00, + 0xFC, 0xC0, 0xF8, 0x0C, 0x0C, 0xCC, 0x78, 0x00, + 0x38, 0x60, 0xC0, 0xF8, 0xCC, 0xCC, 0x78, 0x00, + 0xFC, 0xCC, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00, + 0x78, 0xCC, 0xCC, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x78, 0xCC, 0xCC, 0x7C, 0x0C, 0x18, 0x70, 0x00, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, + 0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00, + 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00, + 0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00, + 0x7C, 0xC6, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00, + 0x30, 0x78, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00, + 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, + 0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00, + 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, + 0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00, + 0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00, + 0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3A, 0x00, + 0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00, + 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x1E, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00, + 0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00, + 0xF0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, + 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00, + 0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00, + 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, + 0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, + 0x7C, 0xC6, 0xC6, 0xC6, 0xD6, 0x7C, 0x0E, 0x00, + 0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00, + 0x7C, 0xC6, 0xE0, 0x78, 0x0E, 0xC6, 0x7C, 0x00, + 0xFC, 0xB4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFC, 0x00, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00, + 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00, + 0xC6, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0xC6, 0x00, + 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x78, 0x00, + 0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00, + 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, + 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00, + 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, + 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xDC, 0x00, + 0x00, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00, + 0x1C, 0x0C, 0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0x38, 0x6C, 0x64, 0xF0, 0x60, 0x60, 0xF0, 0x00, + 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, + 0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00, + 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x0C, 0x00, 0x1C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, + 0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00, + 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x00, 0xCC, 0xFE, 0xFE, 0xD6, 0xD6, 0x00, + 0x00, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, + 0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0, + 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E, + 0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0xF0, 0x00, + 0x00, 0x00, 0x7C, 0xC0, 0x70, 0x1C, 0xF8, 0x00, + 0x10, 0x30, 0xFC, 0x30, 0x30, 0x34, 0x18, 0x00, + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00, + 0x00, 0x00, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00, + 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00, + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, + 0x00, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00, + 0x1C, 0x30, 0x30, 0xE0, 0x30, 0x30, 0x1C, 0x00, + 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, + 0xE0, 0x30, 0x30, 0x1C, 0x30, 0x30, 0xE0, 0x00, + 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00, + 0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x0C, 0x06, 0x7C, + 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x1C, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0x7E, 0x81, 0x3C, 0x06, 0x3E, 0x66, 0x3B, 0x00, + 0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0xE0, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0x30, 0x30, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0x78, 0x0C, 0x38, + 0x7E, 0x81, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00, + 0xCC, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0xE0, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0xCC, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x7C, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00, + 0xE0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xC6, 0x10, 0x7C, 0xC6, 0xFE, 0xC6, 0xC6, 0x00, + 0x30, 0x30, 0x00, 0x78, 0xCC, 0xFC, 0xCC, 0x00, + 0x1C, 0x00, 0xFC, 0x60, 0x78, 0x60, 0xFC, 0x00, + 0x00, 0x00, 0x7F, 0x0C, 0x7F, 0xCC, 0x7F, 0x00, + 0x3E, 0x6C, 0xCC, 0xFE, 0xCC, 0xCC, 0xCE, 0x00, + 0x78, 0x84, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0xCC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0xE0, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x78, 0x84, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0xE0, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, + 0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00, + 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, + 0x18, 0x18, 0x7E, 0xC0, 0xC0, 0x7E, 0x18, 0x18, + 0x38, 0x6C, 0x64, 0xF0, 0x60, 0xE6, 0xFC, 0x00, + 0xCC, 0xCC, 0x78, 0x30, 0xFC, 0x30, 0xFC, 0x30, + 0xF8, 0xCC, 0xCC, 0xFA, 0xC6, 0xCF, 0xC6, 0xC3, + 0x0E, 0x1B, 0x18, 0x3C, 0x18, 0x18, 0xD8, 0x70, + 0x1C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x1C, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0x1C, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0xF8, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0x00, + 0xFC, 0x00, 0xCC, 0xEC, 0xFC, 0xDC, 0xCC, 0x00, + 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00, + 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00, + 0x18, 0x00, 0x18, 0x18, 0x30, 0x66, 0x3C, 0x00, + 0x00, 0x00, 0x00, 0xFC, 0xC0, 0xC0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFC, 0x0C, 0x0C, 0x00, 0x00, + 0xC6, 0xCC, 0xD8, 0x36, 0x6B, 0xC2, 0x84, 0x0F, + 0xC3, 0xC6, 0xCC, 0xDB, 0x37, 0x6D, 0xCF, 0x03, + 0x18, 0x00, 0x18, 0x18, 0x3C, 0x3C, 0x18, 0x00, + 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00, + 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00, + 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, + 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, + 0xDB, 0xF6, 0xDB, 0x6F, 0xDB, 0x7E, 0xD7, 0xED, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00, + 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x36, 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xDC, 0xC8, 0xDC, 0x76, 0x00, + 0x00, 0x78, 0xCC, 0xF8, 0xCC, 0xF8, 0xC0, 0xC0, + 0x00, 0xFC, 0xCC, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, + 0x00, 0x00, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, + 0xFC, 0xCC, 0x60, 0x30, 0x60, 0xCC, 0xFC, 0x00, + 0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0x70, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0xC0, + 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x00, + 0xFC, 0x30, 0x78, 0xCC, 0xCC, 0x78, 0x30, 0xFC, + 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x6C, 0x38, 0x00, + 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x6C, 0xEE, 0x00, + 0x1C, 0x30, 0x18, 0x7C, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0x7E, 0x00, 0x00, + 0x06, 0x0C, 0x7E, 0xDB, 0xDB, 0x7E, 0x60, 0xC0, + 0x38, 0x60, 0xC0, 0xF8, 0xC0, 0x60, 0x38, 0x00, + 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, + 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, + 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x7E, 0x00, + 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xFC, 0x00, + 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xFC, 0x00, + 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0x70, + 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00, + 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x0F, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C, + 0x58, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, + 0x70, 0x98, 0x30, 0x60, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + + static + grBitmap gr_charcell = + { + 8, /* rows */ + 8, /* width */ + 1, /* pitch */ + gr_pixel_mode_mono, /* mode */ + 0, /* grays */ + 0 /* buffer */ + }; + + void grWriteCellChar( grBitmap* target, + int x, + int y, + int charcode, + grColor color ) + { + if (charcode < 0 || charcode > 255) + return; + + gr_charcell.buffer = (unsigned char*)font_8x8 + 8 * charcode; + grBlitGlyphToBitmap( target, &gr_charcell, x, y, color ); + } + + + void grWriteCellString( grBitmap* target, + int x, + int y, + const char* string, + grColor color ) + { + while (*string) + { + gr_charcell.buffer = (unsigned char *)font_8x8 + + 8 * (int)(unsigned char)*string++; + grBlitGlyphToBitmap( target, &gr_charcell, x, y, color ); + x += 8; + } + } + + static int gr_cursor_x = 0; + static int gr_cursor_y = 0; + static grBitmap* gr_text_bitmap = 0; + static int gr_margin_right = 0; + static int gr_margin_top = 0; + + + extern void grGotobitmap( grBitmap* bitmap ) + { + gr_text_bitmap = bitmap; + } + + + extern void grSetMargin( int right, int top ) + { + gr_margin_top = top << 3; + gr_margin_right = right << 3; + } + + + extern void grSetPixelMargin( int right, int top ) + { + gr_margin_top = top; + gr_margin_right = right; + } + + + extern void grGotoxy ( int x, int y ) + { + gr_cursor_x = x; + gr_cursor_y = y; + } + + + extern void grWrite ( const char* string ) + { + if (string) + { + grColor color; + + color.value = 127; + grWriteCellString( gr_text_bitmap, + gr_margin_right + (gr_cursor_x << 3), + gr_margin_top + (gr_cursor_y << 3), + string, + color ); + + gr_cursor_x += strlen(string); + } + } + + + extern void grLn( void ) + { + gr_cursor_y ++; + gr_cursor_x = 0; + } + + + extern void grWriteln( const char* string ) + { + grWrite( string ); + grLn(); + } + + diff --git a/kernel/kls_ttf/ftview/grfont.h b/kernel/kls_ttf/ftview/grfont.h new file mode 100644 index 0000000..47f226a --- /dev/null +++ b/kernel/kls_ttf/ftview/grfont.h @@ -0,0 +1,17 @@ +#ifndef GRFONT_H +#define GRFONT_H + +#include "graph.h" + + extern const unsigned char font_8x8[]; + + extern void grGotobitmap( grBitmap* bitmap ); + extern void grSetMargin( int right, int top ); + extern void grSetPixelMargin( int right, int top ); + extern void grGotoxy ( int x, int y ); + + extern void grWrite ( const char* string ); + extern void grWriteln( const char* string ); + extern void grLn( void ); + +#endif /* GRFONT_H */ diff --git a/kernel/kls_ttf/ftview/grobjs.cpp b/kernel/kls_ttf/ftview/grobjs.cpp new file mode 100644 index 0000000..283c315 --- /dev/null +++ b/kernel/kls_ttf/ftview/grobjs.cpp @@ -0,0 +1,213 @@ +#include "grobjs.h" +#include +#include + + int grError = 0; + + + /******************************************************************** + * + * + * grRealloc + * + * + * Simple memory re-allocation. + * + * + * block :: original memory block address + * size :: new requested block size in bytes + * + * + * the memory block address. 0 in case of error + * + ********************************************************************/ + + unsigned char* grAlloc( long size ) + { + unsigned char* p; + + p = (unsigned char*)malloc(size); + if (!p && size > 0) + { + grError = gr_err_memory; + } + + if (p) + memset( p, 0, size ); + + return p; + } + + + /******************************************************************** + * + * + * grRealloc + * + * + * Simple memory re-allocation. + * + * + * block :: original memory block address + * size :: new requested block size in bytes + * + * + * the memory block address. 0 in case of error + * + ********************************************************************/ + + unsigned char* grRealloc( const unsigned char* block, long size ) + { + unsigned char* p; + + p = (unsigned char *)realloc( (void*)block, size ); + if (!p && size > 0) + { + grError = gr_err_memory; + } + return p; + } + + + /******************************************************************** + * + * + * grFree + * + * + * Simple memory release + * + * + * block :: target block + * + ********************************************************************/ + + void grFree( const void* block ) + { + if (block) + free( (void *)block ); + } + + + + static + int check_mode( grPixelMode pixel_mode, + int num_grays ) + { + if ( pixel_mode <= gr_pixel_mode_none || + pixel_mode >= gr_pixel_mode_max ) + goto Fail; + + if ( pixel_mode != gr_pixel_mode_gray || + ( num_grays >= 2 && num_grays <= 256 ) ) + return 0; + + Fail: + grError = gr_err_bad_argument; + return grError; + } + + + /********************************************************************** + * + * + * grNewBitmap + * + * + * creates a new bitmap + * + * + * pixel_mode :: the target surface's pixel_mode + * num_grays :: number of grays levels for PAL8 pixel mode + * width :: width in pixels + * height :: height in pixels + * + * + * bit :: descriptor of the new bitmap + * + * + * Error code. 0 means success. + * + **********************************************************************/ + + extern int grNewBitmap( grPixelMode pixel_mode, + int num_grays, + int width, + int height, + grBitmap *bit ) + { + int pitch; + + /* check mode */ + if (check_mode(pixel_mode,num_grays)) + goto Fail; + + /* check dimensions */ + if (width < 0 || height < 0) + { + grError = gr_err_bad_argument; + goto Fail; + } + + bit->width = width; + bit->rows = height; + bit->mode = pixel_mode; + bit->grays = num_grays; + + pitch = width; + + switch (pixel_mode) + { + case gr_pixel_mode_mono : pitch = (width+7) >> 3; break; + case gr_pixel_mode_pal4 : pitch = (width+3) >> 2; break; + + case gr_pixel_mode_pal8 : + case gr_pixel_mode_gray : pitch = width; break; + + case gr_pixel_mode_rgb555: + case gr_pixel_mode_rgb565: pitch = width*2; break; + + case gr_pixel_mode_rgb24 : pitch = width*3; break; + + case gr_pixel_mode_rgb32 : pitch = width*4; break; + + default: + grError = gr_err_bad_target_depth; + return 0; + } + + bit->pitch = pitch; + bit->buffer = grAlloc( (long)bit->pitch * bit->rows ); + if (!bit->buffer) goto Fail; + + return 0; + + Fail: + return grError; + } + + /********************************************************************** + * + * + * grDoneBitmap + * + * + * destroys a bitmap + * + * + * bitmap :: handle to bitmap descriptor + * + * + * This function does NOT release the bitmap descriptor, only + * the pixel buffer. + * + **********************************************************************/ + + extern void grDoneBitmap( grBitmap* bit ) + { + grFree( bit->buffer ); + bit->buffer = 0; + } + + + diff --git a/kernel/kls_ttf/ftview/grobjs.h b/kernel/kls_ttf/ftview/grobjs.h new file mode 100644 index 0000000..038ec54 --- /dev/null +++ b/kernel/kls_ttf/ftview/grobjs.h @@ -0,0 +1,182 @@ +/*************************************************************************** + * + * grobjs.h + * + * basic object classes defintions + * + * Copyright 1999 - The FreeType Development Team - www.freetype.org + * + * + * + * + ***************************************************************************/ + +#ifndef GROBJS_H +#define GROBJS_H + +#include "graph.h" +#include "grconfig.h" +#include "grtypes.h" + + + typedef struct grBiColor_ + { + grColor foreground; + grColor background; + + int num_levels; + int max_levels; + grColor* levels; + + } grBiColor; + + + + /********************************************************************** + * + * Technical note : explaining how the blitter works. + * + * The blitter is used to "draw" a given source bitmap into + * a given target bitmap. + * + * The function called 'compute_clips' is used to compute clipping + * constraints. These lead us to compute two areas : + * + * - the read area : is the rectangle, within the source bitmap, + * which will be effectively "drawn" in the + * target bitmap. + * + * - the write area : is the rectangle, within the target bitmap, + * which will effectively "receive" the pixels + * from the read area + * + * Note that both areas have the same dimensions, but are + * located in distinct surfaces. + * + * These areas are computed by 'compute_clips' which is called + * by each blitting function. + * + * Note that we use the Y-downwards convention within the blitter + * + **********************************************************************/ + + typedef struct grBlitter_ + { + int width; /* width in pixels of the areas */ + int height; /* height in pixels of the areas */ + + int xread; /* x position of start point in read area */ + int yread; /* y position of start point in read area */ + + int xwrite; /* x position of start point in write area */ + int ywrite; /* y position of start point in write area */ + + int right_clip; /* amount of right clip */ + + unsigned char* read; /* top left corner of read area in source map */ + unsigned char* write; /* top left corner of write area in target map */ + + int read_line; /* byte increment to go down one row in read area */ + int write_line; /* byte increment to go down one row in write area */ + + grBitmap source; /* source bitmap descriptor */ + grBitmap target; /* target bitmap descriptor */ + + } grBlitter; + + + + typedef void (*grBlitterFunc)( grBlitter* blitter, + grColor color ); + + typedef void (*grSetTitleFunc)( grSurface* surface, + const char* title_string ); + + typedef void (*grRefreshRectFunc)( grSurface* surface, + int x, + int y, + int width, + int height ); + + typedef void (*grDoneSurfaceFunc)( grSurface* surface ); + + typedef int (*grListenEventFunc)( grSurface* surface, + int event_mode, + grEvent *event ); + + + + struct grSurface_ + { + grDevice* device; + grBitmap bitmap; + grBool refresh; + grBool owner; + + const byte* saturation; /* used for gray surfaces only */ + grBlitterFunc blit_mono; /* 0 by default, set by grBlit.. */ + + grRefreshRectFunc refresh_rect; + grSetTitleFunc set_title; + grListenEventFunc listen_event; + grDoneSurfaceFunc done; + }; + + + + /******************************************************************** + * + * + * grAlloc + * + * + * Simple memory allocation. The returned block is always zero-ed + * + * + * size :: size in bytes of the requested block + * + * + * the memory block address. 0 in case of error + * + ********************************************************************/ + + extern unsigned char* grAlloc( long size ); + + + /******************************************************************** + * + * + * grRealloc + * + * + * Simple memory re-allocation. + * + * + * block :: original memory block address + * size :: new requested block size in bytes + * + * + * the memory block address. 0 in case of error + * + ********************************************************************/ + + extern unsigned char* grRealloc( const unsigned char* block, long size ); + + + /******************************************************************** + * + * + * grFree + * + * + * Simple memory release + * + * + * block :: target block + * + ********************************************************************/ + + extern void grFree( const void* block ); + + +#endif /* GROBJS_H */ diff --git a/kernel/kls_ttf/ftview/grtypes.h b/kernel/kls_ttf/ftview/grtypes.h new file mode 100644 index 0000000..7c39e2a --- /dev/null +++ b/kernel/kls_ttf/ftview/grtypes.h @@ -0,0 +1,52 @@ +/*************************************************************************** + * + * grtypes.h + * + * basic type defintions + * + * Copyright 1999 - The FreeType Development Team - www.freetype.org + * + * + * + * + ***************************************************************************/ + +#ifndef GRTYPES_H +#define GRTYPES_H + + typedef unsigned char byte; + +#if 0 + typedef signed char uchar; + + typedef unsigned long ulong; + typedef unsigned short ushort; + typedef unsigned int uint; +#endif + + typedef struct grDimension_ + { + int x; + int y; + + } grDimension; + +#define gr_err_ok 0 +#define gr_err_memory -1 +#define gr_err_bad_argument -2 +#define gr_err_bad_target_depth -3 +#define gr_err_bad_source_depth -4 +#define gr_err_saturation_overflow -5 +#define gr_err_conversion_overflow -6 +#define gr_err_invalid_device -7 + + +#ifdef GR_MAKE_OPTION_SINGLE_OBJECT +#define GR_LOCAL_DECL static +#define GR_LOCAL_FUNC static +#else +#define GR_LOCAL_DECL extern +#define GR_LOCAL_FUNC /* void */ +#endif + +#endif /* GRTYPES_H */ diff --git a/kernel/kls_ttf/ttf2pnm.cpp b/kernel/kls_ttf/ttf2pnm.cpp new file mode 100644 index 0000000..4571731 --- /dev/null +++ b/kernel/kls_ttf/ttf2pnm.cpp @@ -0,0 +1,187 @@ +/****************************************************************************/ +/* */ +/* The FreeType project -- a free and portable quality TrueType renderer. */ +/* */ +/* Copyright 1996-2000, 2003, 2004, 2005, 2006 by */ +/* D. Turner, R.Wilhelm, and W. Lemberg */ +/* */ +/* */ +/* FTView - a simple font viewer. */ +/* */ +/* This is a new version using the MiGS graphics subsystem for */ +/* blitting and display. */ +/* */ +/* Press F1 when running this program to have a list of key-bindings */ +/* */ +/****************************************************************************/ + +#include + +#include +#include +#include + +#include "ftcommon.h" +#include + + /* the following header shouldn't be used in normal programs */ +#include FT_SYNTHESIS_H + +#define MAXPTSIZE 500 /* dtp */ + +#ifdef CEIL +#undef CEIL +#endif +#define CEIL( x ) ( ( (x) + 63 ) >> 6 ) + +#define INIT_SIZE( size, start_x, start_y, step_x, step_y, x, y ) \ + do { \ + start_x = 4; \ + start_y = CEIL( size->metrics.height ); \ + step_x = CEIL( size->metrics.max_advance ); \ + step_y = CEIL( size->metrics.height ) + 4; \ + \ + x = start_x; \ + y = start_y; \ + } while ( 0 ) + +#define X_TOO_LONG( x, size, bitmap) \ + ( ( x ) + ( ( size )->metrics.max_advance >> 6 ) > bitmap->width ) + +#define Y_TOO_LONG( y, size, bitmap) \ + ( ( y ) >= bitmap->rows ) + +grBitmap *bit; + + static struct status_ + { + FT_Encoding encoding; + int res; + int ptsize; /* current point size */ + + int font_index; + int Num; /* current first index */ + int Fail; + + } status = { FT_ENCODING_NONE, 72, 24, 0, 0, 0 }; + + static FTDemo_Handle* handle; + + static FT_Error + Render_All( int num_indices, + int first_index ) + { + int start_x, start_y, step_x, step_y, x, y; + int i; + FT_Size size; + + error = FTDemo_Get_Size(handle, &size); + + if ( error ) + { + /* probably a non-existent bitmap font size */ + return error; + } + + INIT_SIZE( size, start_x, start_y, step_x, step_y, x, y ); + + i = first_index; + + while ( i < num_indices ) + { + int gindex; + + if ( handle->encoding == FT_ENCODING_NONE ) + gindex = i; + else + gindex = FTDemo_Get_Index( handle, i ); + + error = FTDemo_Draw_Index( handle, bit, gindex, &x, &y ); + + if ( error ) + status.Fail++; + else if ( X_TOO_LONG( x, size, bit ) ) + { + x = start_x; + y += step_y; + + if ( Y_TOO_LONG( y, size, bit ) ) + break; + } + + i++; + } + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** REST OF THE APPLICATION/PROGRAM *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + static void + event_font_change() + { + int num_indices; + + status.font_index = 0; + status.Num = 0; + + FTDemo_Set_Current_Font(handle, handle->fonts[status.font_index]); + FTDemo_Set_Current_Pointsize(handle, status.ptsize, status.res); + FTDemo_Update_Current_Flags(handle); + + num_indices = handle->current_font->num_indices; + + if(status.Num >= num_indices) + status.Num = num_indices - 1; + } + + + int + main( int argc, + char* argv[] ) + { + if(argc != 3) + exit(1); + + /* Initialize engine */ + handle = FTDemo_New(status.encoding); + + FTDemo_Install_Font(handle, argv[1]); + + if(handle->num_fonts == 0) + PanicZ( "could not find/open any font file" ); + + bit = FTDemo_Display_New(); + + if(!bit) + PanicZ( "could not allocate display surface" ); + + status.Fail = 0; + + event_font_change(); + + FTDemo_Update_Current_Flags(handle); + + FTDemo_Display_Clear(bit); + + Render_All(handle->current_font->num_indices, status.Num); + + FILE *f = fopen(argv[2], "wb"); + + fprintf(f, "P6\n%d %d\n255\n", bit->width, bit->rows); + fwrite(bit->buffer, bit->width * bit->rows * 3, 1, f); + + fclose(f); + + FTDemo_Display_Done(bit); + FTDemo_Done(handle); + + return 0; + } diff --git a/kernel/kls_utah/Makefile.am b/kernel/kls_utah/Makefile.am new file mode 100644 index 0000000..965b4cb --- /dev/null +++ b/kernel/kls_utah/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I../include + +bin_SCRIPTS = ksquirrel-libs-utah2ppm + +pkglib_LTLIBRARIES = libkls_utah.la + +libkls_utah_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_utah_la_LDFLAGS = ${SQ_RELEASE} + +libkls_utah_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DCODEC_NETPBM -DCODEC_UTAH -DNETPBM_S=\"${bindir}/ksquirrel-libs-utah2ppm\" + +EXTRA_DIST = ksquirrel-libs-utah2ppm.in \ No newline at end of file diff --git a/kernel/kls_utah/fmt_codec_pnm.cpp b/kernel/kls_utah/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_utah/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_utah/fmt_codec_pnm_defs.h b/kernel/kls_utah/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_utah/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_utah/ksquirrel-libs-utah2ppm.in b/kernel/kls_utah/ksquirrel-libs-utah2ppm.in new file mode 100644 index 0000000..1d77d7a --- /dev/null +++ b/kernel/kls_utah/ksquirrel-libs-utah2ppm.in @@ -0,0 +1,3 @@ +#!/bin/sh + +@UTAHTOPNM@ "$1" > "$2" \ No newline at end of file diff --git a/kernel/kls_wal/Makefile.am b/kernel/kls_wal/Makefile.am new file mode 100644 index 0000000..388c52b --- /dev/null +++ b/kernel/kls_wal/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_wal.la + +libkls_wal_la_SOURCES = fmt_codec_wal.cpp fmt_codec_wal_defs.h q2pal.h + +libkls_wal_la_LDFLAGS = ${SQ_RELEASE} + +libkls_wal_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_wal/fmt_codec_wal.cpp b/kernel/kls_wal/fmt_codec_wal.cpp new file mode 100644 index 0000000..a5b46d5 --- /dev/null +++ b/kernel/kls_wal/fmt_codec_wal.cpp @@ -0,0 +1,172 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_wal_defs.h" +#include "fmt_codec_wal.h" + +#include "ksquirrel-libs/error.h" + +#include "q2pal.h" + +#include "../xpm/codec_wal.xpm" + +/* + * + * Quake2 WAL texture + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.2.0"; + o->name = "Quake2 texture"; + o->filter = "*.wal "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-wal"; + o->pixmap = codec_wal; + o->readable = true; + o->canbemultiple = true; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + read_error = false; + + finfo.animated = false; + + bits = NULL; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage == 4) + return SQE_NOTOK; + + if(!currentImage) + { + if(!frs.readK(&wal, sizeof(wal_header))) + return SQE_R_BADFILE; + + neww = wal.width; + newh = wal.height; + + fmt_metaentry mt; + + mt.group = "Quake2 texture name"; + mt.data = wal.name; + addmeta(mt); + + mt.group = "Quake2 next texture name"; + mt.data = wal.next_name; + addmeta(mt); + } + else + { + neww /= 2; + newh /= 2; + } + + bits = (u8 *)realloc(bits, neww * newh); + + if(!bits) + return SQE_R_NOMEMORY; + + fmt_image image; + + frs.seekg(wal.offset[currentImage], ios::beg); + + if(!frs.good()) + return SQE_R_BADFILE; + + image.w = neww; + image.h = newh; + image.bpp = 8; + image.compression = "-"; + image.colorspace = fmt_utils::colorSpaceByBpp(8); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + if(!frs.readK(bits, im->w)) + return SQE_R_BADFILE; + + for(s32 i = 0;i < im->w;i++) + { + scan[i].r = q2pal[bits[i] * 3]; + scan[i].g = q2pal[bits[i] * 3 + 1]; + scan[i].b = q2pal[bits[i] * 3 + 2]; + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); + + if(bits) free(bits); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_wal/fmt_codec_wal_defs.h b/kernel/kls_wal/fmt_codec_wal_defs.h new file mode 100644 index 0000000..1e8210f --- /dev/null +++ b/kernel/kls_wal/fmt_codec_wal_defs.h @@ -0,0 +1,42 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_CODEC_DEFS_wal +#define KSQUIRREL_CODEC_DEFS_wal + +typedef struct +{ + s8 name[32]; /* name of the texture */ + + u32 width; /* width (in pixels) of the largest mipmap level */ + u32 height; /* height (in pixels) of the largest mipmap level */ + + s32 offset[4]; /* byte offset of the start of each of the 4 mipmap levels */ + + s8 next_name[32]; /* name of the next texture in the animation */ + + u32 flags; + u32 contents; + u32 value; + +}wal_header; + +#endif diff --git a/kernel/kls_wal/q2pal.h b/kernel/kls_wal/q2pal.h new file mode 100644 index 0000000..39530e5 --- /dev/null +++ b/kernel/kls_wal/q2pal.h @@ -0,0 +1,266 @@ +#ifndef Q2PAL_H +#define Q2PAL_H + +/* Quake2 pallette taken from DevIL library (http://imagelib.org) */ + +static const s8 q2pal[768] = +{ + 0, 0, 0, + 15, 15, 15, + 31, 31, 31, + 47, 47, 47, + 63, 63, 63, + 75, 75, 75, + 91, 91, 91, + 107, 107, 107, + 123, 123, 123, + 139, 139, 139, + 155, 155, 155, + 171, 171, 171, + 187, 187, 187, + 203, 203, 203, + 219, 219, 219, + 235, 235, 235, + 99, 75, 35, + 91, 67, 31, + 83, 63, 31, + 79, 59, 27, + 71, 55, 27, + 63, 47, 23, + 59, 43, 23, + 51, 39, 19, + 47, 35, 19, + 43, 31, 19, + 39, 27, 15, + 35, 23, 15, + 27, 19, 11, + 23, 15, 11, + 19, 15, 7, + 15, 11, 7, + 95, 95, 111, + 91, 91, 103, + 91, 83, 95, + 87, 79, 91, + 83, 75, 83, + 79, 71, 75, + 71, 63, 67, + 63, 59, 59, + 59, 55, 55, + 51, 47, 47, + 47, 43, 43, + 39, 39, 39, + 35, 35, 35, + 27, 27, 27, + 23, 23, 23, + 19, 19, 19, + 143, 119, 83, + 123, 99, 67, + 115, 91, 59, + 103, 79, 47, + 207, 151, 75, + 167, 123, 59, + 139, 103, 47, + 111, 83, 39, + 235, 159, 39, + 203, 139, 35, + 175, 119, 31, + 147, 99, 27, + 119, 79, 23, + 91, 59, 15, + 63, 39, 11, + 35, 23, 7, + 167, 59, 43, + 159, 47, 35, + 151, 43, 27, + 139, 39, 19, + 127, 31, 15, + 115, 23, 11, + 103, 23, 7, + 87, 19, 0, + 75, 15, 0, + 67, 15, 0, + 59, 15, 0, + 51, 11, 0, + 43, 11, 0, + 35, 11, 0, + 27, 7, 0, + 19, 7, 0, + 123, 95, 75, + 115, 87, 67, + 107, 83, 63, + 103, 79, 59, + 95, 71, 55, + 87, 67, 51, + 83, 63, 47, + 75, 55, 43, + 67, 51, 39, + 63, 47, 35, + 55, 39, 27, + 47, 35, 23, + 39, 27, 19, + 31, 23, 15, + 23, 15, 11, + 15, 11, 7, + 111, 59, 23, + 95, 55, 23, + 83, 47, 23, + 67, 43, 23, + 55, 35, 19, + 39, 27, 15, + 27, 19, 11, + 15, 11, 7, + 179, 91, 79, + 191, 123, 111, + 203, 155, 147, + 215, 187, 183, + 203, 215, 223, + 179, 199, 211, + 159, 183, 195, + 135, 167, 183, + 115, 151, 167, + 91, 135, 155, + 71, 119, 139, + 47, 103, 127, + 23, 83, 111, + 19, 75, 103, + 15, 67, 91, + 11, 63, 83, + 7, 55, 75, + 7, 47, 63, + 7, 39, 51, + 0, 31, 43, + 0, 23, 31, + 0, 15, 19, + 0, 7, 11, + 0, 0, 0, + 139, 87, 87, + 131, 79, 79, + 123, 71, 71, + 115, 67, 67, + 107, 59, 59, + 99, 51, 51, + 91, 47, 47, + 87, 43, 43, + 75, 35, 35, + 63, 31, 31, + 51, 27, 27, + 43, 19, 19, + 31, 15, 15, + 19, 11, 11, + 11, 7, 7, + 0, 0, 0, + 151, 159, 123, + 143, 151, 115, + 135, 139, 107, + 127, 131, 99, + 119, 123, 95, + 115, 115, 87, + 107, 107, 79, + 99, 99, 71, + 91, 91, 67, + 79, 79, 59, + 67, 67, 51, + 55, 55, 43, + 47, 47, 35, + 35, 35, 27, + 23, 23, 19, + 15, 15, 11, + 159, 75, 63, + 147, 67, 55, + 139, 59, 47, + 127, 55, 39, + 119, 47, 35, + 107, 43, 27, + 99, 35, 23, + 87, 31, 19, + 79, 27, 15, + 67, 23, 11, + 55, 19, 11, + 43, 15, 7, + 31, 11, 7, + 23, 7, 0, + 11, 0, 0, + 0, 0, 0, + 119, 123, 207, + 111, 115, 195, + 103, 107, 183, + 99, 99, 167, + 91, 91, 155, + 83, 87, 143, + 75, 79, 127, + 71, 71, 115, + 63, 63, 103, + 55, 55, 87, + 47, 47, 75, + 39, 39, 63, + 35, 31, 47, + 27, 23, 35, + 19, 15, 23, + 11, 7, 7, + 155, 171, 123, + 143, 159, 111, + 135, 151, 99, + 123, 139, 87, + 115, 131, 75, + 103, 119, 67, + 95, 111, 59, + 87, 103, 51, + 75, 91, 39, + 63, 79, 27, + 55, 67, 19, + 47, 59, 11, + 35, 47, 7, + 27, 35, 0, + 19, 23, 0, + 11, 15, 0, + 0, 255, 0, + 35, 231, 15, + 63, 211, 27, + 83, 187, 39, + 95, 167, 47, + 95, 143, 51, + 95, 123, 51, + 255, 255, 255, + 255, 255, 211, + 255, 255, 167, + 255, 255, 127, + 255, 255, 83, + 255, 255, 39, + 255, 235, 31, + 255, 215, 23, + 255, 191, 15, + 255, 171, 7, + 255, 147, 0, + 239, 127, 0, + 227, 107, 0, + 211, 87, 0, + 199, 71, 0, + 183, 59, 0, + 171, 43, 0, + 155, 31, 0, + 143, 23, 0, + 127, 15, 0, + 115, 7, 0, + 95, 0, 0, + 71, 0, 0, + 47, 0, 0, + 27, 0, 0, + 239, 0, 0, + 55, 55, 255, + 255, 0, 0, + 0, 0, 255, + 43, 43, 35, + 27, 27, 23, + 19, 19, 15, + 235, 151, 127, + 195, 115, 83, + 159, 87, 51, + 123, 63, 27, + 235, 211, 199, + 199, 171, 155, + 167, 139, 119, + 135, 107, 87, + 159, 91, 83 +}; + +#endif diff --git a/kernel/kls_wbmp/Makefile.am b/kernel/kls_wbmp/Makefile.am new file mode 100644 index 0000000..9c2d093 --- /dev/null +++ b/kernel/kls_wbmp/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_wbmp.la + +libkls_wbmp_la_SOURCES = fmt_codec_wbmp.cpp fmt_codec_wbmp_defs.h + +libkls_wbmp_la_LDFLAGS = ${SQ_RELEASE} + +libkls_wbmp_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_wbmp/fmt_codec_wbmp.cpp b/kernel/kls_wbmp/fmt_codec_wbmp.cpp new file mode 100644 index 0000000..f69dab6 --- /dev/null +++ b/kernel/kls_wbmp/fmt_codec_wbmp.cpp @@ -0,0 +1,278 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +/* + * The Wireless Application Protocol Bitmap Format (WBMP) is designed for use + * with applications that operate over wireless communication networks. + * The WBMP format is commonly used in mobile phones (WAP phones) and enables + * graphical information to be sent to the handset. + * This format is very simple and allows to store image only in 1-bit + * format (black and white). + */ + + +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fmt_utils.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" + +#include "fmt_codec_wbmp_defs.h" +#include "fmt_codec_wbmp.h" + +#include "../xpm/codec_wbmp.xpm" + +/* + * + * WBMP: Wireless Bitmap Type 0: B/W, Uncompressed Bitmap + * Specification of the WBMP format can be found in the + * SPEC-WAESpec-19990524.pdf + * + * You can download the WAP specification on: http://www.wapforum.com/ + * + */ + +static const RGB mono[2] = { RGB(255,255,255), RGB(0,0,0) }; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.9.0"; + o->name = "Wireless Application Protocol Bitmap"; + o->filter = "*.wbmp "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-wbmp"; + o->pixmap = codec_wbmp; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + wbmp.bitmap = NULL; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + u8 type; + + frs.readK(&type, sizeof(u8)); + + wbmp.type = type; + + if(wbmp.type != 0) + return SQE_R_BADFILE; + + if(skipheader(frs)) + return SQE_R_BADFILE; + + wbmp.width = getmbi(frs); + + if(wbmp.width == -1) + return SQE_R_BADFILE; + + wbmp.height = getmbi(frs); + + if(wbmp.height == -1) + return SQE_R_BADFILE; + + image.w = wbmp.width; + image.h = wbmp.height; + image.bpp = 1; + + wbmp.bitmap = new s32 [wbmp.width * wbmp.height]; + + if(!wbmp.bitmap) + return SQE_R_NOMEMORY; + + s32 row, col, byte, pel, pos; + u8 b; + + pos = 0; + + for(row = 0;row < wbmp.height;row++) + { + for(col = 0;col < wbmp.width;) + { + if(!frs.readK(&b, sizeof(u8))) + return SQE_R_BADFILE; + + byte = b; + + for(pel = 7;pel >= 0;pel--) + { + if(col++ < wbmp.width) + { + if(byte & 1 << pel) + wbmp.bitmap[pos] = WBMP_WHITE; + else + wbmp.bitmap[pos] = WBMP_BLACK; + + pos++; + } + } + } + } + + image.compression = "-"; + image.colorspace = fmt_utils::colorSpaceByBpp(1); + + finfo.image.push_back(image); + + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + line++; + + for(s32 i = 0;i < im->w;i++) + memcpy(scan+i, mono + (wbmp.bitmap[line * im->w + i]), sizeof(RGB)); + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + delete [] wbmp.bitmap; + wbmp.bitmap = NULL; + + finfo.meta.clear(); + finfo.image.clear(); +} + +/* + * + * These functions were taken from Wbmp program by Johan Van den Brande + * + * (c) 2000 Johan Van den Brande + * + */ + +s32 fmt_codec::getmbi(ifstreamK &f) +{ + s32 mbi = 0; + s8 i; + + do + { + f.readK(&i, sizeof(s8)); + + if(i < 0) + return -1; + + mbi = (mbi << 7) | (i & 0x7f); + + }while(i & 0x80); + + return mbi; +} + +s32 fmt_codec::putmbi(s32 i, ofstreamK &f) +{ + s32 cnt, l, accu; + u8 s; + + /* Get number of septets */ + cnt = 0; + accu = 0; + + while(accu != i) + accu += i & 0x7f << 7*cnt++; + + /* Produce the multibyte output */ + for(l = cnt-1;l > 0;l--) + { + s = 0x80 | (i & 0x7f << 7*l ) >> 7*l; + f.writeK(&s, sizeof(s8)); + } + + s = i & 0x7f; + + f.writeK(&s, sizeof(u8)); + + return 0; +} + +s32 fmt_codec::skipheader(ifstreamK &f) +{ + s8 i; + bool b; + + do + { + b = f.readK(&i, sizeof(s8)); + + if(!b) + return -1; + + if(i < 0) + return -1; + + }while(i & 0x80); + + return 0; +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_wbmp/fmt_codec_wbmp_defs.h b/kernel/kls_wbmp/fmt_codec_wbmp_defs.h new file mode 100644 index 0000000..b774933 --- /dev/null +++ b/kernel/kls_wbmp/fmt_codec_wbmp_defs.h @@ -0,0 +1,37 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_wbmp +#define KSQUIRREL_READ_IMAGE_wbmp + +struct Wbmp +{ + s32 type; /* type of the wbmp */ + s32 width; /* width of the image */ + s32 height; /* height of the image */ + s32 *bitmap; /* pointer to data: 0 = WHITE , 1 = BLACK */ + +}PACKED; + +#define WBMP_WHITE 0 +#define WBMP_BLACK 1 + +#endif diff --git a/kernel/kls_wmf/Makefile.am b/kernel/kls_wmf/Makefile.am new file mode 100644 index 0000000..be71d57 --- /dev/null +++ b/kernel/kls_wmf/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include @SQ_WMF_CFLAGS@ + +pkglib_LTLIBRARIES = libkls_wmf.la + +libkls_wmf_la_SOURCES = fmt_codec_wmf.cpp wmf2mem.cpp fmt_codec_wmf_defs.h + +libkls_wmf_la_LDFLAGS = ${SQ_RELEASE} + +libkls_wmf_la_LIBADD = @SQ_WMF_LDFLAGS@ ${SQ_LOCAL_RPATH} \ No newline at end of file diff --git a/kernel/kls_wmf/fmt_codec_wmf.cpp b/kernel/kls_wmf/fmt_codec_wmf.cpp new file mode 100644 index 0000000..ec5045d --- /dev/null +++ b/kernel/kls_wmf/fmt_codec_wmf.cpp @@ -0,0 +1,150 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_wmf_defs.h" +#include "fmt_codec_wmf.h" + +#include "../xpm/codec_wmf.xpm" + +/* + * + * Microsoft Windows Metafile Format (WMF) files are used to store both + * vector and bitmap-format graphical data in memory or in disk files. + * The vector data stored in WMF files is described as Microsoft Windows + * Graphics Device Interface (GDI) commands. In the Window environment + * these commands are interpreted and played back on an output device + * using the Windows API PlayMetaFile() function. Bitmap data stored in + * a WMF file may be stored in the form of a Microsoft Device Dependent + * Bitmap (DDB), or Device Independent Bitmap (DIB). + * + */ + +extern int call(int, char **, unsigned char **, int *, int *); + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.9.0"; + o->name = "Windows Metafile"; + o->filter = "*.wmf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-wmf"; + o->pixmap = codec_wmf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + frs.close(); + + currentImage = -1; + + finfo.animated = false; + + const char * argv[] = + { + "wmf2gd", + file.c_str() + }; + + buf = NULL; + + call(2, (char **)argv, &buf, &w, &h); + + if(!buf) + return SQE_R_NOMEMORY; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + image.bpp = 32; + image.w = w; + image.h = h; + image.compression = "-"; + image.colorspace = "Vectorized RGB"; + + finfo.image.push_back(image); + + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + line++; + + memcpy(scan, buf + line * im->w * sizeof(RGBA), im->w * sizeof(RGBA)); + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + finfo.meta.clear(); + finfo.image.clear(); + + delete [] buf; + buf = NULL; +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_wmf/fmt_codec_wmf_defs.h b/kernel/kls_wmf/fmt_codec_wmf_defs.h new file mode 100644 index 0000000..5167e0a --- /dev/null +++ b/kernel/kls_wmf/fmt_codec_wmf_defs.h @@ -0,0 +1,25 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_wmf +#define KSQUIRREL_READ_IMAGE_wmf + +#endif diff --git a/kernel/kls_wmf/wmf2mem.cpp b/kernel/kls_wmf/wmf2mem.cpp new file mode 100644 index 0000000..ed644e1 --- /dev/null +++ b/kernel/kls_wmf/wmf2mem.cpp @@ -0,0 +1,361 @@ +/* libwmf (convert/wmf2gd.c): library for wmf conversion + Copyright (C) 2000 - various; see CREDITS, ChangeLog, and sources + + The libwmf Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The libwmf Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the libwmf Library; see the file COPYING. If not, + write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fmt_defs.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +typedef struct +{ int argc; + char** argv; + + char* wmf_filename; + char* gd_filename; + + wmf_gd_t options; + + unsigned int max_width; + unsigned int max_height; + + unsigned long max_flags; + +} PlotData; + +#define WMF2GD_MAXPECT (1 << 0) +#define WMF2GD_MAXSIZE (1 << 1) + +int wmf2gd_draw (PlotData*, unsigned char **buf, int *w, int *h); + +void wmf2gd_init (PlotData*,int,char**); +int wmf2gd_args (PlotData*); +int wmf2gd_file (PlotData*, unsigned char **buf, int *w, int *h); + +int call(int argc,char** argv, unsigned char **buf, int *w, int *h); + +int explicit_wmf_error(wmf_error_t); + +int wmf2gd_draw (PlotData* pdata, unsigned char **buf, int *www, int *hhh) +{ + int status = 0; + + float wmf_width; + float wmf_height; + + float ratio_wmf; + float ratio_bounds; + + unsigned int disp_width = 0; + unsigned int disp_height = 0; + + unsigned long flags; + unsigned long max_flags; + + wmf_error_t err; + + wmf_gd_t* ddata = 0; + + wmfAPI* API = 0; + + wmfAPI_Options api_options; + + flags = 0; + + flags |= WMF_OPT_FUNCTION; + api_options.function = wmf_gd_function; + + flags |= WMF_OPT_ARGS; + api_options.argc = pdata->argc; + api_options.argv = pdata->argv; +#ifndef DEBUG + flags |= WMF_OPT_IGNORE_NONFATAL; +#endif + err = wmf_api_create (&API,flags,&api_options); + status = explicit_wmf_error (err); + + if (status) + { if (API) wmf_api_destroy (API); + return (status); + } + + ddata = WMF_GD_GetData (API); + + err = wmf_file_open(API, pdata->wmf_filename); + status = explicit_wmf_error (err); + + if (status) + { + wmf_api_destroy (API); + return (status); + } + + err = wmf_scan (API, 0, &(pdata->options.bbox)); + status = explicit_wmf_error (err); + + if (status) + { + wmf_api_destroy (API); + return (status); + } + +/* Okay, got this far, everything seems cool. + */ + ddata->type = pdata->options.type; + + ddata->flags |= WMF_GD_OUTPUT_MEMORY; + ddata->file = pdata->options.file; + + ddata->bbox = pdata->options.bbox; + + wmf_display_size (API, &disp_width, &disp_height, 72, 72); + + wmf_width = (float) disp_width; + wmf_height = (float) disp_height; + + if ((wmf_width <= 0) || (wmf_height <= 0)) + { + status = 1; + wmf_api_destroy (API); + return (status); + } + + max_flags = pdata->max_flags; + + if ((wmf_width > (float) pdata->max_width ) || (wmf_height > (float) pdata->max_height)) + if (max_flags == 0) + max_flags = WMF2GD_MAXPECT; + + if (max_flags == WMF2GD_MAXPECT) /* scale the image */ + { ratio_wmf = wmf_height / wmf_width; + ratio_bounds = (float) pdata->max_height / (float) pdata->max_width; + + if (ratio_wmf > ratio_bounds) + { ddata->height = pdata->max_height; + ddata->width = (unsigned int) ((float) ddata->height / ratio_wmf); + } + else + { ddata->width = pdata->max_width; + ddata->height = (unsigned int) ((float) ddata->width * ratio_wmf); + } + } + else if (max_flags == WMF2GD_MAXSIZE) /* bizarre option, really */ + { ddata->width = pdata->max_width; + ddata->height = pdata->max_height; + } + else + { ddata->width = (unsigned int) ceil ((double) wmf_width ); + ddata->height = (unsigned int) ceil ((double) wmf_height); + } + + if (status == 0) + { + err = wmf_play(API, 0, &(pdata->options.bbox)); + status = explicit_wmf_error (err); + } + + wmf_api_destroy(API); + + int *p = wmf_gd_image_pixels(ddata->gd_image); + unsigned int w, h; + + unsigned int pixel; + unsigned char r, g, b, a; + + *buf = new u8 [ddata->height * ddata->width * sizeof(RGBA)]; + + if(!*buf) + return 1; + + unsigned char *pss = *buf; + + for (h = 0; h < ddata->height; h++) + for (w = 0; w < ddata->width; w++) + { + pixel = (unsigned int) (*p++); + + b = (unsigned char) (pixel & 0xff); + pixel >>= 8; + g = (unsigned char) (pixel & 0xff); + pixel >>= 8; + r = (unsigned char) (pixel & 0xff); + pixel >>= 7; + a = (unsigned char) (pixel & 0xfe); + a ^= 0xff; + + *pss++ = r; + *pss++ = g; + *pss++ = b; + *pss++ = a; + } + + *www = ddata->width; + *hhh = ddata->height; + + free(ddata->gd_image); + + if(ddata->memory) + free(ddata->memory); + + return status; +} + +void wmf2gd_init(PlotData *pdata, int argc, char **argv) +{ + pdata->argc = argc; + pdata->argv = argv; + + pdata->wmf_filename = 0; + pdata->gd_filename = 0; + + pdata->options.type = wmf_gd_png; + + pdata->options.file = 0; + + pdata->options.width = 0; + pdata->options.height = 0; + + pdata->options.flags = 0; + + pdata->max_width = 768; + pdata->max_height = 512; + + pdata->max_flags = 0; +} + +int wmf2gd_args (PlotData* pdata) +{ + int status = 0; + int arg = 0; + + int argc = pdata->argc; + char** argv = pdata->argv; + + while ((++arg) < argc) + { + if (strcmp (argv[arg],"-o") == 0) + { if ((++arg) < argc) + { pdata->gd_filename = argv[arg]; + continue; + } + fprintf (stderr,"usage: `wmf2gd -o '.\n"); + fprintf (stderr,"Try `%s --help' for more information.\n",argv[0]); + status = arg; + break; + } + + if (argv[arg][0] != '-') + { pdata->wmf_filename = argv[arg]; + continue; + } + + fprintf (stderr,"option `%s' not recognized.\n",argv[arg]); + fprintf (stderr,"Try `%s --help' for more information.\n",argv[0]); + status = arg; + + break; + } + + if (status == 0) + { if(pdata->wmf_filename == 0) + { + fprintf (stderr,"No input file specified!\n"); + fprintf (stderr,"Try `%s --help' for more information.\n",argv[0]); + status = argc; + } + } + + pdata->options.type = wmf_gd_image; + + return (status); +} + +int wmf2gd_file(PlotData* pdata, unsigned char **buf, int *w, int *h) +{ + int status = 0; + + pdata->options.file = stdout; + + status = wmf2gd_draw(pdata, buf, w, h); + + if(pdata->options.file != stdout) + fclose(pdata->options.file); + + return status; +} + +int call(int argc, char **argv, unsigned char **buf, int *w, int *h) +{ + int status = 0; + + PlotData PData; + + wmf2gd_init(&PData, argc, argv); + + status = wmf2gd_args(&PData); + + if(status) + return status; + + status = wmf2gd_file(&PData, buf, w, h); + + return status; +} + +int explicit_wmf_error (wmf_error_t err) +{ + int status = 0; + + switch (err) + { + case wmf_E_None: + status = 0; + break; + + case wmf_E_InsMem: + case wmf_E_BadFile: + case wmf_E_BadFormat: + case wmf_E_EOF: + case wmf_E_DeviceError: + case wmf_E_Glitch: + case wmf_E_Assert: + status = 1; + break; + + default: + status = 1; + } + + return status; +} diff --git a/kernel/kls_xbm/Makefile.am b/kernel/kls_xbm/Makefile.am new file mode 100644 index 0000000..07bd070 --- /dev/null +++ b/kernel/kls_xbm/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_xbm.la + +libkls_xbm_la_SOURCES = fmt_codec_xbm.cpp fmt_codec_xbm_defs.h + +libkls_xbm_la_LDFLAGS = ${SQ_RELEASE} + +libkls_xbm_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_xbm/fmt_codec_xbm.cpp b/kernel/kls_xbm/fmt_codec_xbm.cpp new file mode 100644 index 0000000..71409ae --- /dev/null +++ b/kernel/kls_xbm/fmt_codec_xbm.cpp @@ -0,0 +1,219 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fmt_utils.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" + +#include "fmt_codec_xbm_defs.h" +#include "fmt_codec_xbm.h" + +#include "../xpm/codec_xbm.xpm" + +/* + * + * XBM is a native file format of the X Window System and is used for + * storing cursor and icon bitmaps that are used in the X GUI. + * XBMfiles are quite different in that they are actually C language source + * files that are created to be read by a C compiler rather than a + * graphical display program. + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.7.0"; + o->name = "X BitMap"; + o->filter = "*.xbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xbm"; + o->pixmap = codec_xbm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = fopen(file.c_str(), "rb"); + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + long _tmp; + s8 str[256], *ptr; + + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + if(!skip_comments(fptr)) + return SQE_R_BADFILE; + + if(!sq_fgets(str, sizeof(str)-1, fptr)) + return SQE_R_BADFILE; + + if(strncmp(str, "#define ", 8) != 0) + return SQE_R_BADFILE; + + if((ptr = strstr(str, "_width ")) == NULL) + return SQE_R_BADFILE; + + image.w = (long)atoi(ptr+6); + + if(!sq_fgets(str, sizeof(str)-1, fptr)) + return SQE_R_BADFILE; + + if(strncmp(str, "#define ", 8) != 0) + return SQE_R_BADFILE; + + if((ptr = strstr(str, "_height ")) == NULL) + return SQE_R_BADFILE; + + image.h = (long)atoi(ptr+7); + + while(sq_fgets(str, sizeof(str)-1, fptr)) + { + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if(strncmp(str, "#define ", 8) != 0) + break; + } + + if(str[0] == '\n') if(!sq_fgets(str, sizeof(str)-1, fptr)) return SQE_R_BADFILE; + + if(strstr(str, "_bits[") == NULL || (ptr = strrchr(str, '{')) == NULL) + return SQE_R_BADFILE; + + if((strstr(str, "unsigned") && (strstr(str, "char"))) || strstr(str, "char")) + version = 11; + else if(strstr(str, "short")) + version = 10; + else + return SQE_R_NOTSUPPORTED; + + _tmp = lscan = image.w; + + image.bpp = 1; + + lscan /= 8; + lscan = lscan + ((_tmp%8)?1:0); + + memset(pal, 255, sizeof(RGB)); + memset(pal+1, 0, sizeof(RGB)); + + image.compression = "-"; + image.colorspace = fmt_utils::colorSpaceByBpp(1); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + s8 index, c; + s32 counter = 0, remain = (im->w <= 8) ? im->w : (im->w % 8), j; + u32 bt; + + for(j = 0;j < lscan;j++) + { + fscanf(fptr, "%x%c", &bt, &c); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + // @todo make faster + if(j==lscan-1 && (remain-0)<=0 && remain)break; index = (bt & 1); memcpy(scan+counter, pal+(s32)index, 3); counter++; + if(j==lscan-1 && (remain-1)<=0 && remain)break; index = (bt & 2) ? 1 : 0; memcpy(scan+counter, pal+(s32)index, 3); counter++; + if(j==lscan-1 && (remain-2)<=0 && remain)break; index = (bt & 4) ? 1 : 0; memcpy(scan+counter, pal+(s32)index, 3); counter++; + if(j==lscan-1 && (remain-3)<=0 && remain)break; index = (bt & 8) ? 1 : 0; memcpy(scan+counter, pal+(s32)index, 3); counter++; + if(j==lscan-1 && (remain-4)<=0 && remain)break; index = (bt & 16) ? 1 : 0; memcpy(scan+counter, pal+(s32)index, 3); counter++; + if(j==lscan-1 && (remain-5)<=0 && remain)break; index = (bt & 32) ? 1 : 0; memcpy(scan+counter, pal+(s32)index, 3); counter++; + if(j==lscan-1 && (remain-6)<=0 && remain)break; index = (bt & 64) ? 1 : 0; memcpy(scan+counter, pal+(s32)index, 3); counter++; + if(j==lscan-1 && (remain-7)<=0 && remain)break; index = (bt & 128) ? 1 : 0; memcpy(scan+counter, pal+(s32)index, 3); counter++; + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +/* skip a single line C-like comment */ +bool skip_comments(FILE *fp) +{ + s8 str[513]; + s32 pos; + + do + { + pos = ftell(fp); + if(!sq_fgets(str, 512, fp)) return false; + + if(!strstr(str, "/*")) + break; + }while(true); + + fsetpos(fp, (fpos_t*)&pos); + + return true; +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_xbm/fmt_codec_xbm_defs.h b/kernel/kls_xbm/fmt_codec_xbm_defs.h new file mode 100644 index 0000000..6204269 --- /dev/null +++ b/kernel/kls_xbm/fmt_codec_xbm_defs.h @@ -0,0 +1,48 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_xbm +#define KSQUIRREL_READ_IMAGE_xbm + +struct XBM_HEADER +{ + u8 ID[3]; + +}PACKED; + +bool skip_comments(FILE *); + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = fgets(s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +#endif diff --git a/kernel/kls_xcf/Makefile.am b/kernel/kls_xcf/Makefile.am new file mode 100644 index 0000000..6b9a50d --- /dev/null +++ b/kernel/kls_xcf/Makefile.am @@ -0,0 +1,18 @@ +SUBDIRS = xcf2pnm + +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_xcf.la + +libkls_xcf_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_xcf_la_LDFLAGS = ${SQ_RELEASE} +libkls_xcf_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DXCF_UI=\"${pkgdatadir}/libkls_xcf.so.ui\" -DCODEC_XCF -DCODEC_ANOTHER -DKLXCF2PNM=\"${bindir}/ksquirrel-libs-xcf2pnm\" + +EXTRA_DIST = libkls_xcf.so.ui + +install-data-am: + $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) + $(INSTALL) --mode=0644 libkls_xcf.so.ui $(DESTDIR)$(pkgdatadir)/libkls_xcf.so.ui diff --git a/kernel/kls_xcf/fmt_codec_pnm.cpp b/kernel/kls_xcf/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_xcf/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_xcf/fmt_codec_pnm_defs.h b/kernel/kls_xcf/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_xcf/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_xcf/libkls_xcf.so.ui b/kernel/kls_xcf/libkls_xcf.so.ui new file mode 100644 index 0000000..e0f9073 --- /dev/null +++ b/kernel/kls_xcf/libkls_xcf.so.ui @@ -0,0 +1,78 @@ + +Form1 + + + Form1 + + + + 0 + 0 + 351 + 59 + + + + Form1 + + + + unnamed + + + 0 + + + + line5 + + + HLine + + + Sunken + + + Horizontal + + + + + autocrop + + + Autocrop to visible layer boundaries + + + + + background + + + + + + + + textLabel1 + + + Background color for transparent images: + + + AlignVCenter + + + + + + + + background + autocrop + + + + kcolorbutton.h + + diff --git a/kernel/kls_xcf/xcf2pnm/Makefile.am b/kernel/kls_xcf/xcf2pnm/Makefile.am new file mode 100644 index 0000000..c81ca26 --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/Makefile.am @@ -0,0 +1,5 @@ +bin_PROGRAMS = ksquirrel-libs-xcf2pnm + +ksquirrel_libs_xcf2pnm_SOURCES = enums.c flatspec.c flatten.c io-unix.c pixels.c scaletab.c table.c utils.c xcf2pnm.c xcf-general.c + +EXTRA_DIST = xcf2pnm.oi \ No newline at end of file diff --git a/kernel/kls_xcf/xcf2pnm/enums.c b/kernel/kls_xcf/xcf2pnm/enums.c new file mode 100644 index 0000000..88f68e7 --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/enums.c @@ -0,0 +1,116 @@ +/* Autogenerated from enums.h */ +#include "enums.h" +#define N_ +#include +const char* +showGimpLayerModeEffects(GimpLayerModeEffects x) +{ + static char buf[35]; + switch(x) { + case GIMP_NORMAL_MODE: return N_("Normal"); + case GIMP_DISSOLVE_MODE: return N_("Dissolve"); + case GIMP_BEHIND_MODE: return N_("Behind"); + case GIMP_MULTIPLY_MODE: return N_("Multiply"); + case GIMP_SCREEN_MODE: return N_("Screen"); + case GIMP_OVERLAY_MODE: return N_("Overlay"); + case GIMP_DIFFERENCE_MODE: return N_("Difference"); + case GIMP_ADDITION_MODE: return N_("Addition"); + case GIMP_SUBTRACT_MODE: return N_("Subtract"); + case GIMP_DARKEN_ONLY_MODE: return N_("DarkenOnly"); + case GIMP_LIGHTEN_ONLY_MODE: return N_("LightenOnly"); + case GIMP_HUE_MODE: return N_("Hue"); + case GIMP_SATURATION_MODE: return N_("Saturation"); + case GIMP_COLOR_MODE: return N_("Color"); + case GIMP_VALUE_MODE: return N_("Value"); + case GIMP_DIVIDE_MODE: return N_("Divide"); + case GIMP_DODGE_MODE: return N_("Dodge"); + case GIMP_BURN_MODE: return N_("Burn"); + case GIMP_HARDLIGHT_MODE: return N_("Hardlight"); + case GIMP_SOFTLIGHT_MODE: return N_("Softlight"); + case GIMP_GRAIN_EXTRACT_MODE: return N_("GrainExtract"); + case GIMP_GRAIN_MERGE_MODE: return N_("GrainMerge"); + case GIMP_COLOR_ERASE_MODE: return N_("ColorErase"); + case GIMP_ERASE_MODE: return N_("Erase"); + case GIMP_REPLACE_MODE: return N_("Replace"); + case GIMP_ANTI_ERASE_MODE: return N_("AntiErase"); + case GIMP_NORMAL_NOPARTIAL_MODE: return N_("NormalNopartial"); + default: sprintf(buf,"(GimpLayerModeEffects:%d)",(int)x); + return buf; + } +} +const char* +showGimpImageBaseType(GimpImageBaseType x) +{ + static char buf[32]; + switch(x) { + case GIMP_RGB: return N_("RGB color"); + case GIMP_GRAY: return N_("Grayscale"); + case GIMP_INDEXED: return N_("Indexed color"); + default: sprintf(buf,"(GimpImageBaseType:%d)",(int)x); + return buf; + } +} +const char* +showGimpImageType(GimpImageType x) +{ + static char buf[28]; + switch(x) { + case GIMP_RGB_IMAGE: return N_("RGB"); + case GIMP_RGBA_IMAGE: return N_("RGB-alpha"); + case GIMP_GRAY_IMAGE: return N_("Grayscale"); + case GIMP_GRAYA_IMAGE: return N_("Grayscale-alpha"); + case GIMP_INDEXED_IMAGE: return N_("Indexed"); + case GIMP_INDEXEDA_IMAGE: return N_("Indexed-alpha"); + default: sprintf(buf,"(GimpImageType:%d)",(int)x); + return buf; + } +} +const char* +showPropType(PropType x) +{ + static char buf[23]; + switch(x) { + case PROP_END: return ("End"); + case PROP_COLORMAP: return ("Colormap"); + case PROP_ACTIVE_LAYER: return ("ActiveLayer"); + case PROP_ACTIVE_CHANNEL: return ("ActiveChannel"); + case PROP_SELECTION: return ("Selection"); + case PROP_FLOATING_SELECTION: return ("FloatingSelection"); + case PROP_OPACITY: return ("Opacity"); + case PROP_MODE: return ("Mode"); + case PROP_VISIBLE: return ("Visible"); + case PROP_LINKED: return ("Linked"); + case PROP_PRESERVE_TRANSPARENCY: return ("PreserveTransparency"); + case PROP_APPLY_MASK: return ("ApplyMask"); + case PROP_EDIT_MASK: return ("EditMask"); + case PROP_SHOW_MASK: return ("ShowMask"); + case PROP_SHOW_MASKED: return ("ShowMasked"); + case PROP_OFFSETS: return ("Offsets"); + case PROP_COLOR: return ("Color"); + case PROP_COMPRESSION: return ("Compression"); + case PROP_GUIDES: return ("Guides"); + case PROP_RESOLUTION: return ("Resolution"); + case PROP_TATTOO: return ("Tattoo"); + case PROP_PARASITES: return ("Parasites"); + case PROP_UNIT: return ("Unit"); + case PROP_PATHS: return ("Paths"); + case PROP_USER_UNIT: return ("UserUnit"); + case PROP_VECTORS: return ("Vectors"); + case PROP_TEXT_LAYER_FLAGS: return ("TextLayerFlags"); + default: sprintf(buf,"(PropType:%d)",(int)x); + return buf; + } +} +const char* +showXcfCompressionType(XcfCompressionType x) +{ + static char buf[33]; + switch(x) { + case COMPRESS_NONE: return N_("None"); + case COMPRESS_RLE: return N_("RLE"); + case COMPRESS_ZLIB: return N_("Zlib"); + case COMPRESS_FRACTAL: return N_("Fractal"); + default: sprintf(buf,"(XcfCompressionType:%d)",(int)x); + return buf; + } +} diff --git a/kernel/kls_xcf/xcf2pnm/enums.h b/kernel/kls_xcf/xcf2pnm/enums.h new file mode 100644 index 0000000..81746ef --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/enums.h @@ -0,0 +1,98 @@ +/* Extracted from + * gimp/base-enums.h + * gimp/gimpbaseenums.h + * gimp/xcf-private.h + * by mkenumsh.pl + */ +typedef enum +{ + GIMP_NORMAL_MODE, + GIMP_DISSOLVE_MODE, + GIMP_BEHIND_MODE, + GIMP_MULTIPLY_MODE, + GIMP_SCREEN_MODE, + GIMP_OVERLAY_MODE, + GIMP_DIFFERENCE_MODE, + GIMP_ADDITION_MODE, + GIMP_SUBTRACT_MODE, + GIMP_DARKEN_ONLY_MODE, + GIMP_LIGHTEN_ONLY_MODE, + GIMP_HUE_MODE, + GIMP_SATURATION_MODE, + GIMP_COLOR_MODE, + GIMP_VALUE_MODE, + GIMP_DIVIDE_MODE, + GIMP_DODGE_MODE, + GIMP_BURN_MODE, + GIMP_HARDLIGHT_MODE, + GIMP_SOFTLIGHT_MODE, + GIMP_GRAIN_EXTRACT_MODE, + GIMP_GRAIN_MERGE_MODE, + GIMP_COLOR_ERASE_MODE, + GIMP_ERASE_MODE, /*< pdb-skip, skip >*/ + GIMP_REPLACE_MODE, /*< pdb-skip, skip >*/ + GIMP_ANTI_ERASE_MODE /*< pdb-skip, skip >*/ + ,GIMP_NORMAL_NOPARTIAL_MODE=-1 +} GimpLayerModeEffects; +const char *showGimpLayerModeEffects(GimpLayerModeEffects); +#define GimpLayerModeEffects_LAST GIMP_ANTI_ERASE_MODE +typedef enum +{ + GIMP_RGB, /*< desc="RGB color" >*/ + GIMP_GRAY, /*< desc="Grayscale" >*/ + GIMP_INDEXED /*< desc="Indexed color" >*/ +} GimpImageBaseType; +const char *showGimpImageBaseType(GimpImageBaseType); +#define GimpImageBaseType_LAST GIMP_INDEXED +typedef enum +{ + GIMP_RGB_IMAGE, /*< desc="RGB" >*/ + GIMP_RGBA_IMAGE, /*< desc="RGB-alpha" >*/ + GIMP_GRAY_IMAGE, /*< desc="Grayscale" >*/ + GIMP_GRAYA_IMAGE, /*< desc="Grayscale-alpha" >*/ + GIMP_INDEXED_IMAGE, /*< desc="Indexed" >*/ + GIMP_INDEXEDA_IMAGE /*< desc="Indexed-alpha" >*/ +} GimpImageType; +const char *showGimpImageType(GimpImageType); +#define GimpImageType_LAST GIMP_INDEXEDA_IMAGE +typedef enum +{ + PROP_END = 0, + PROP_COLORMAP = 1, + PROP_ACTIVE_LAYER = 2, + PROP_ACTIVE_CHANNEL = 3, + PROP_SELECTION = 4, + PROP_FLOATING_SELECTION = 5, + PROP_OPACITY = 6, + PROP_MODE = 7, + PROP_VISIBLE = 8, + PROP_LINKED = 9, + PROP_PRESERVE_TRANSPARENCY = 10, + PROP_APPLY_MASK = 11, + PROP_EDIT_MASK = 12, + PROP_SHOW_MASK = 13, + PROP_SHOW_MASKED = 14, + PROP_OFFSETS = 15, + PROP_COLOR = 16, + PROP_COMPRESSION = 17, + PROP_GUIDES = 18, + PROP_RESOLUTION = 19, + PROP_TATTOO = 20, + PROP_PARASITES = 21, + PROP_UNIT = 22, + PROP_PATHS = 23, + PROP_USER_UNIT = 24, + PROP_VECTORS = 25, + PROP_TEXT_LAYER_FLAGS = 26 +} PropType; +const char *showPropType(PropType); +#define PropType_LAST PROP_TEXT_LAYER_FLAGS +typedef enum +{ + COMPRESS_NONE = 0, + COMPRESS_RLE = 1, + COMPRESS_ZLIB = 2, /* unused */ + COMPRESS_FRACTAL = 3 /* unused */ +} XcfCompressionType; +const char *showXcfCompressionType(XcfCompressionType); +#define XcfCompressionType_LAST COMPRESS_FRACTAL diff --git a/kernel/kls_xcf/xcf2pnm/flatspec.c b/kernel/kls_xcf/xcf2pnm/flatspec.c new file mode 100644 index 0000000..75827ff --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/flatspec.c @@ -0,0 +1,370 @@ +/* Flattening selections function for xcftools + * + * Copyright (C) 2006 Henning Makholm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "xcftools.h" +#include "flatten.h" +#include +#include + +void +init_flatspec(struct FlattenSpec *spec) +{ + spec->window_mode = USE_CANVAS ; + spec->default_pixel = PERHAPS_ALPHA_CHANNEL ; + spec->numLayers = 0 ; + spec->layers = NULL ; + spec->transmap_filename = NULL ; + spec->output_filename = "-" ; + spec->out_color_mode = COLOR_BY_CONTENTS ; + spec->partial_transparency_mode = ALLOW_PARTIAL_TRANSPARENCY ; + spec->process_in_memory = 0 ; + spec->gimpish_indexed = 1 ; +} + +void +add_layer_request(struct FlattenSpec *spec, const char *layer) +{ + spec->layers = realloc(spec->layers, + sizeof(struct xcfLayer) * (1+spec->numLayers)); + if( spec->layers == NULL ) + FatalUnexpected(_("Out of memory")); + spec->layers[spec->numLayers].name = layer ; + spec->layers[spec->numLayers].mode = (GimpLayerModeEffects)-1 ; + spec->layers[spec->numLayers].opacity = 9999 ; + spec->layers[spec->numLayers].hasMask = -1 ; + spec->numLayers++ ; +} + +struct xcfLayer * +lastlayerspec(struct FlattenSpec *spec,const char *option) +{ + if( spec->numLayers == 0 ) + FatalGeneric(20,_("The %s option must follow a layer name on the " + "command line"),option); + return spec->layers + (spec->numLayers-1) ; +} + +static int +typeHasTransparency(GimpImageType type) +{ + switch( type ) { + case GIMP_RGB_IMAGE: + case GIMP_GRAY_IMAGE: + case GIMP_INDEXED_IMAGE: + return 0 ; + case GIMP_RGBA_IMAGE: + case GIMP_GRAYA_IMAGE: + case GIMP_INDEXEDA_IMAGE: + return 1 ; + } + return 1 ; +} + +static enum out_color_mode +color_by_layers(struct FlattenSpec *spec) +{ + int colormap_is_colored = 0 ; + enum out_color_mode grayish = COLOR_MONO ; + int i ; + + if( spec->default_pixel == CHECKERED_BACKGROUND ) + grayish = COLOR_GRAY ; + else if( degrayPixel(spec->default_pixel) < 0 ) + return COLOR_RGB ; + for( i=0; inumLayers; i++ ) + switch( spec->layers[i].type ) { + case GIMP_RGB_IMAGE: + case GIMP_RGBA_IMAGE: + return COLOR_RGB ; + case GIMP_GRAY_IMAGE: + case GIMP_GRAYA_IMAGE: + grayish = COLOR_GRAY ; + break ; + case GIMP_INDEXED_IMAGE: + case GIMP_INDEXEDA_IMAGE: + if( colormap_is_colored ) return COLOR_RGB ; + break ; + } + return grayish ; +} + +void +complete_flatspec(struct FlattenSpec *spec, guesser guess_callback) +{ + unsigned i ; + int anyPartial ; + + /* Find the layers to convert. + */ + if( spec->numLayers == 0 ) { + spec->layers = XCF.layers ; + spec->numLayers = XCF.numLayers ; + } else { + for( i=0; inumLayers; i++ ) { + GimpLayerModeEffects mode ; + int opacity, hasMask ; + unsigned j ; + + for( j=0; ; j++ ) { + if( j == XCF.numLayers ) + FatalGeneric(22,_("The image has no layer called '%s'"), + spec->layers[i].name); + if( strcmp(spec->layers[i].name,XCF.layers[j].name) == 0 ) + break ; + } + mode = spec->layers[i].mode == (GimpLayerModeEffects)-1 ? + XCF.layers[j].mode : spec->layers[i].mode ; + opacity = spec->layers[i].opacity == 9999 ? + XCF.layers[j].opacity : spec->layers[i].opacity ; + hasMask = spec->layers[i].hasMask == -1 ? + XCF.layers[j].hasMask : spec->layers[i].hasMask ; + if( hasMask && !XCF.layers[j].hasMask && + XCF.layers[j].mask.hierarchy == 0 ) + FatalGeneric(22,_("Layer '%s' has no layer mask to enable"), + spec->layers[i].name); + spec->layers[i] = XCF.layers[j] ; + spec->layers[i].mode = mode ; + spec->layers[i].opacity = opacity ; + spec->layers[i].hasMask = hasMask ; + spec->layers[i].isVisible = 1 ; + } + } + + /* Force the mode of the lowest visible layer to be Normal or Dissolve. + * That may not be logical, but the Gimp does it + */ + for( i=0; i < spec->numLayers; i++ ) { + if( spec->layers[i].isVisible ) { + if( spec->layers[i].mode != GIMP_DISSOLVE_MODE ) + spec->layers[i].mode = GIMP_NORMAL_MODE ; + break ; + } + } + + /* Mimic the Gimp's behavior on indexed layers */ + if( XCF.type == GIMP_INDEXED && spec->gimpish_indexed ) { + for( i=0; inumLayers; i++ ) + if( spec->layers[i].mode != GIMP_DISSOLVE_MODE ) + spec->layers[i].mode = GIMP_NORMAL_NOPARTIAL_MODE ; + } else + spec->gimpish_indexed = 0 ; + + /* compute dimensions of the window */ + if( spec->window_mode == AUTOCROP ) { + int first = 1 ; + for( i=0; inumLayers; i++ ) + if( spec->layers[i].isVisible ) { + computeDimensions(&spec->layers[i].dim) ; + if( first ) { + spec->dim = spec->layers[i].dim ; + first = 0 ; + } else { + if( spec->dim.c.l < spec->layers[i].dim.c.l ) + spec->dim.c.l = spec->layers[i].dim.c.l ; + if( spec->dim.c.r > spec->layers[i].dim.c.r ) + spec->dim.c.r = spec->layers[i].dim.c.r ; + if( spec->dim.c.t < spec->layers[i].dim.c.t ) + spec->dim.c.t = spec->layers[i].dim.c.t ; + if( spec->dim.c.b > spec->layers[i].dim.c.b ) + spec->dim.c.b = spec->layers[i].dim.c.b ; + } + } + if( first ) { + spec->window_mode = USE_CANVAS ; + } else { + spec->dim.width = spec->dim.c.r - spec->dim.c.l ; + spec->dim.height = spec->dim.c.b - spec->dim.c.t ; + } + } + if( spec->window_mode != AUTOCROP ) { + if( (spec->window_mode & MANUAL_OFFSET) == 0 ) + spec->dim.c.t = spec->dim.c.l = 0 ; + if( (spec->window_mode & MANUAL_CROP) == 0 ) { + spec->dim.height = XCF.height ; + spec->dim.width = XCF.width ; + } + } + computeDimensions(&spec->dim); + + /* Turn off layers that we don't hit at all */ + for( i=0; inumLayers; i++ ) + if( spec->layers[i].isVisible && + disjointRects(spec->dim.c,spec->layers[i].dim.c) ) + spec->layers[i].isVisible = 0 ; + + /* See if there is a completely covering layer somewhere in the stack */ + /* Also check if partial transparency is possible */ + anyPartial = 0 ; + for( i=spec->numLayers; i-- ; ) { + if( !spec->layers[i].isVisible ) + continue ; + if( typeHasTransparency(spec->layers[i].type) ) { + if( spec->layers[i].mode == GIMP_NORMAL_MODE ) + anyPartial = 1; + } else if( isSubrect(spec->dim.c,spec->layers[i].dim.c) && + (spec->layers[i].mode == GIMP_NORMAL_MODE || + spec->layers[i].mode == GIMP_NORMAL_NOPARTIAL_MODE || + spec->layers[i].mode == GIMP_DISSOLVE_MODE) ) { + /* This layer fills out the entire image. + * Turn off anly lower layers, and note that we cannot have + * transparency at all. + */ + while(i) spec->layers[--i].isVisible = 0 ; + if( spec->default_pixel != FORCE_ALPHA_CHANNEL ) + spec->default_pixel = NEWALPHA(colormap[0],255); + anyPartial = 0 ; + break ; + } + } + if( spec->partial_transparency_mode == ALLOW_PARTIAL_TRANSPARENCY && + (!anyPartial || ALPHA(spec->default_pixel) >= 128) ) + spec->partial_transparency_mode = PARTIAL_TRANSPARENCY_IMPOSSIBLE ; + + /* Initialize layers and print overview if we're verbose */ + for( i=spec->numLayers; i--; ) + if( spec->layers[i].isVisible ) { + initLayer(&spec->layers[i]) ; + if( verboseFlag ) { + fprintf(stderr,"%dx%d%+d%+d %s %s", + spec->layers[i].dim.width, spec->layers[i].dim.height, + spec->layers[i].dim.c.l - spec->dim.c.l, + spec->layers[i].dim.c.t - spec->dim.c.t, + _(showGimpImageType(spec->layers[i].type)), + _(showGimpLayerModeEffects(spec->layers[i].mode))); + if( spec->layers[i].opacity < 255 ) + fprintf(stderr,"/%02d%%",spec->layers[i].opacity * 100 / 255); + if( XCF.layers[i].hasMask ) + fprintf(stderr,_("/mask")); + fprintf(stderr," %s\n",spec->layers[i].name); + } + } + + /* Resolve color mode unless we wait until we have the entire image */ + if( spec->out_color_mode == COLOR_BY_CONTENTS && + !spec->process_in_memory ) { + if( guess_callback ) + spec->out_color_mode = guess_callback(spec,NULL); + if( spec->out_color_mode == COLOR_BY_CONTENTS ) + spec->out_color_mode = color_by_layers(spec) ; + } +} + +void +analyse_colormode(struct FlattenSpec *spec,rgba **allPixels, + guesser guess_callback) +{ + unsigned x,y ; + int status ; + /* 8 - looking for any transparency + * 4 - looking for partially transparent pixels + * 2 - looking for pixels other than black and white + * 1 - looking for colored pixels + */ + int known_absent = 0 ; + int assume_present = 0 ; + + if( spec->out_color_mode == COLOR_BY_CONTENTS && guess_callback ) + spec->out_color_mode = guess_callback(spec,allPixels) ; + + if( spec->out_color_mode == COLOR_RGB ) assume_present |= 3 ; + if( spec->out_color_mode == COLOR_INDEXED ) assume_present |= 3 ; + if( spec->out_color_mode == COLOR_GRAY ) assume_present |= 2 ; + switch( color_by_layers(spec) ) { + case COLOR_GRAY: known_absent |= 1 ; break ; + case COLOR_MONO: known_absent |= 3 ; break ; + default: break ; + } + if( spec->partial_transparency_mode == DISSOLVE_PARTIAL_TRANSPARENCY || + spec->partial_transparency_mode == PARTIAL_TRANSPARENCY_IMPOSSIBLE ) + known_absent |= 4 ; + if( ALPHA(spec->default_pixel) >= 128 ) known_absent |= 12 ; + else if( spec->default_pixel == FORCE_ALPHA_CHANNEL ) assume_present |= 8 ; + + status = 15 - (known_absent | assume_present) ; + + for( y=0; status && ydim.height; y++ ) { + rgba *row = allPixels[y] ; + if( (status & 3) != 0 ) { + /* We're still interested in color */ + for( x=0; status && xdim.width; x++ ) { + if( NULLALPHA(row[x]) ) + status &= ~8 ; + else { + rgba full = row[x] | (255 << ALPHA_SHIFT) ; + if( !FULLALPHA(row[x]) ) status &= ~12 ; + if( full == NEWALPHA(0,255) || full == NEWALPHA(-1,255) ) + /* Black or white */ ; + else if( degrayPixel(row[x]) != -1 ) + status &= ~2 ; /* gray */ + else + status &= ~3 ; /* color */ + } + } + } else { + /* Not interested in color */ + for( x=0; status && xdim.width; x++ ) { + if( NULLALPHA(row[x]) ) + status &= ~8 ; + else if( !FULLALPHA(row[x]) ) + status &= ~12 ; + } + } + } + + status |= known_absent ; + + switch( spec->out_color_mode ) { + case COLOR_INDEXED: /* The caller takes responsibility */ + case COLOR_RGB: /* Everything is fine. */ + break ; + case COLOR_GRAY: + if( (status & 1) == 0 ) + FatalGeneric(103, + _("Grayscale output selected, but colored pixel(s) found")); + break ; + case COLOR_MONO: + if( (status & 2) == 0 ) + FatalGeneric(103,_("Monochrome output selected, but not all pixels " + "are black or white")); + break ; + case COLOR_BY_FILENAME: /* Should not happen ... */ + case COLOR_BY_CONTENTS: + if( (status & 1) == 0 ) + spec->out_color_mode = COLOR_RGB ; + else if( (status & 2) == 0 ) + spec->out_color_mode = COLOR_GRAY ; + else + spec->out_color_mode = COLOR_MONO ; + break ; + } + + if( (status & 12) == 12 ) /* No transparency found */ + spec->default_pixel = NEWALPHA(colormap[0],255); + else if( (status & 12) == 4 ) + spec->partial_transparency_mode = PARTIAL_TRANSPARENCY_IMPOSSIBLE ; +} diff --git a/kernel/kls_xcf/xcf2pnm/flatten.c b/kernel/kls_xcf/xcf2pnm/flatten.c new file mode 100644 index 0000000..c564ddd --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/flatten.c @@ -0,0 +1,689 @@ +/* Flattning functions for xcftools + * + * Copyright (C) 2006 Henning Makholm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "xcftools.h" +#include "flatten.h" +#include "pixels.h" +#include +#include +#include + +static rgba __ATTRIBUTE__((noinline,const)) +composite_one(rgba bot,rgba top) +{ + unsigned tfrac, alpha ; + + tfrac = ALPHA(top) ; + alpha = 255 ; + if( !FULLALPHA(bot) ) { + alpha = 255 ^ scaletable[255-ALPHA(bot)][255-ALPHA(top)] ; + /* This peculiar combination of ^ and - makes the GCC code + * generator for i386 particularly happy. + */ + tfrac = (256*ALPHA(top) - 1) / alpha ; + /* Tfrac is the fraction of the coposited pixel's covered area + * that comes from the top pixel. + * For mathematical accuracy we ought to scale by 255 and + * subtract alpha/2, but this is faster, and never misses the + * true value by more than one 1/255. This effect is completely + * overshadowed by the linear interpolation in the first place. + * (I.e. gamma is ignored when combining intensities). + * [In any case, complete fairness is not possible: if the + * bottom pixel had alpha=170 and the top has alpha=102, + * each should contribute equally to the color of the + * resulting alpha=204 pixel, which is not possible in general] + * Subtracting one helps the topfrac never be 256, which would + * be bad. + * On the other hand it means that we would get tfrac=-1 if the + * top pixel is completely transparent, and we get a division + * by zero if _both_ pixels are fully transparent. These cases + * must be handled by all callers. + * More snooping in the Gimp sources reveal that it uses + * floating-point for its equivalent of tfrac when the + * bottom layer has an alpha channel. (alphify() macro + * in paint-funcs.c). What gives? + */ + } + return (alpha << ALPHA_SHIFT) + + ((uint32_t)scaletable[ tfrac ][255&(top>>RED_SHIFT )] << RED_SHIFT ) + + ((uint32_t)scaletable[ tfrac ][255&(top>>GREEN_SHIFT)] << GREEN_SHIFT ) + + ((uint32_t)scaletable[ tfrac ][255&(top>>BLUE_SHIFT )] << BLUE_SHIFT ) + + ((uint32_t)scaletable[255^tfrac][255&(bot>>RED_SHIFT )] << RED_SHIFT ) + + ((uint32_t)scaletable[255^tfrac][255&(bot>>GREEN_SHIFT)] << GREEN_SHIFT ) + + ((uint32_t)scaletable[255^tfrac][255&(bot>>BLUE_SHIFT )] << BLUE_SHIFT ) + ; +} + +/* merge_normal() takes ownership of bot. + * merge_normal() will share ownership of top. + * Return: may be shared. + */ +static struct Tile * __ATTRIBUTE__((noinline)) +merge_normal(struct Tile *bot, struct Tile *top) +{ + unsigned i ; + assertTileCompatibility(bot,top); + + /* See if there is an easy winner */ + if( (bot->summary & TILESUMMARY_ALLNULL) || + (top->summary & TILESUMMARY_ALLFULL) ) { + freeTile(bot); + return top ; + } + if( top->summary & TILESUMMARY_ALLNULL ) { + freeTile(top); + return bot ; + } + + /* Try hard to make top win */ + for( i=0; ; i++ ) { + if( i == top->count ) { + freeTile(bot); + return top ; + } + if( !(NULLALPHA(bot->pixels[i]) || FULLALPHA(top->pixels[i])) ) + break ; + } + + INIT_SCALETABLE_IF( !(top->summary & TILESUMMARY_CRISP) ); + + /* Otherwise bot wins, but is forever changed ... */ + if( (top->summary & TILESUMMARY_ALLNULL) == 0 ) { + unsigned i ; + invalidateSummary(bot,0); + for( i=0 ; i < top->count ; i++ ) { + if( !NULLALPHA(top->pixels[i]) ) { + if( FULLALPHA(top->pixels[i]) || NULLALPHA(bot->pixels[i]) ) + bot->pixels[i] = top->pixels[i] ; + else + bot->pixels[i] = composite_one(bot->pixels[i],top->pixels[i]); + } + } + } + freeTile(top); + return bot ; +} + +#define exotic_combinator static inline unsigned __ATTRIBUTE__((const)) + + + +exotic_combinator +ucombine_ADDITION(uint8_t bot,uint8_t top) +{ + return bot+top > 255 ? 255 : bot+top ; +} + +exotic_combinator +ucombine_SUBTRACT(uint8_t bot,uint8_t top) +{ + return top>bot ? 0 : bot-top ; +} + +exotic_combinator +ucombine_LIGHTEN_ONLY(uint8_t bot,uint8_t top) +{ + return top > bot ? top : bot ; +} + +exotic_combinator +ucombine_DARKEN_ONLY(uint8_t bot,uint8_t top) +{ + return top < bot ? top : bot ; +} + +exotic_combinator +ucombine_DIFFERENCE(uint8_t bot,uint8_t top) +{ + return top > bot ? top-bot : bot-top ; +} + +exotic_combinator +ucombine_MULTIPLY(uint8_t bot,uint8_t top) +{ + return scaletable[bot][top] ; +} + +exotic_combinator +ucombine_DIVIDE(uint8_t bot,uint8_t top) +{ + int result = (int)bot*256 / (1+top) ; + return result >= 256 ? 255 : result ; +} + +exotic_combinator +ucombine_SCREEN(uint8_t bot,uint8_t top) +{ + /* An inverted version of "multiply" */ + return 255 ^ scaletable[255-bot][255-top] ; +} + +exotic_combinator +ucombine_OVERLAY(uint8_t bot,uint8_t top) +{ + return scaletable[bot][bot] + + 2*scaletable[top][scaletable[bot][255-bot]] ; + /* This strange formula is equivalent to + * (1-top)*(bot^2) + top*(1-(1-top)^2) + * that is, the top value is used to interpolate between + * the self-multiply and the self-screen of the bottom. + */ + /* Note: This is exactly what the "Soft light" effect also + * does, though with different code in the Gimp. + */ +} + +exotic_combinator +ucombine_DODGE(uint8_t bot,uint8_t top) +{ + return ucombine_DIVIDE(bot,255-top); +} + +exotic_combinator +ucombine_BURN(uint8_t bot,uint8_t top) +{ + return 255 - ucombine_DIVIDE(255-bot,top); +} + +exotic_combinator +ucombine_HARDLIGHT(uint8_t bot,uint8_t top) +{ + if( top >= 128 ) + return 255 ^ scaletable[255-bot][2*(255-top)] ; + else + return scaletable[bot][2*top]; + /* The code that implements "hardlight" in Gimp 2.2.10 has some + * rounding errors, but this is undoubtedly what is meant. + */ +} + +exotic_combinator +ucombine_GRAIN_EXTRACT(uint8_t bot,uint8_t top) +{ + int temp = (int)bot - (int)top + 128 ; + return temp < 0 ? 0 : temp >= 256 ? 255 : temp ; +} + +exotic_combinator +ucombine_GRAIN_MERGE(uint8_t bot,uint8_t top) +{ + int temp = (int)bot + (int)top - 128 ; + return temp < 0 ? 0 : temp >= 256 ? 255 : temp ; +} + +struct HSV { + enum { HUE_RED_GREEN_BLUE,HUE_RED_BLUE_GREEN,HUE_BLUE_RED_GREEN, + HUE_BLUE_GREEN_RED,HUE_GREEN_BLUE_RED,HUE_GREEN_RED_BLUE } hue; + unsigned ch1, ch2, ch3 ; +}; + +static void +RGBtoHSV(rgba rgb,struct HSV *hsv) +{ + unsigned RED = (uint8_t)(rgb >> RED_SHIFT); + unsigned GREEN = (uint8_t)(rgb >> GREEN_SHIFT); + unsigned BLUE = (uint8_t)(rgb >> BLUE_SHIFT) ; + #define HEXTANT(b,m,t) hsv->ch1 = b, hsv->ch2 = m, hsv->ch3 = t, \ + hsv->hue = HUE_ ## b ## _ ## m ## _ ## t + if( GREEN <= RED ) + if( BLUE <= RED ) + if( GREEN <= BLUE ) + HEXTANT(GREEN,BLUE,RED); + else + HEXTANT(BLUE,GREEN,RED); + else + HEXTANT(GREEN,RED,BLUE); + else if( BLUE <= RED ) + HEXTANT(BLUE,RED,GREEN); + else if( BLUE <= GREEN ) + HEXTANT(RED,BLUE,GREEN); + else + HEXTANT(RED,GREEN,BLUE); + #undef HEXTANT +} + +/* merge_exotic() destructively updates bot. + * merge_exotic() reads but does not free top. + */ +static void __ATTRIBUTE__((noinline)) +merge_exotic(struct Tile *bot, const struct Tile *top, + GimpLayerModeEffects mode) +{ + unsigned i ; + assertTileCompatibility(bot,top); + if( (bot->summary & TILESUMMARY_ALLNULL) != 0 ) return ; + if( (top->summary & TILESUMMARY_ALLNULL) != 0 ) return ; + assert( bot->refcount == 1 ); + /* The transparency status of bot never changes */ + + INIT_SCALETABLE_IF(1); + + for( i=0; i < top->count ; i++ ) { + uint32_t RED, GREEN, BLUE ; + if( NULLALPHA(bot->pixels[i]) || NULLALPHA(top->pixels[i]) ) + continue ; +#define UNIFORM(mode) case GIMP_ ## mode ## _MODE: \ + RED = ucombine_ ## mode (bot->pixels[i]>>RED_SHIFT , \ + top->pixels[i]>>RED_SHIFT ); \ + GREEN = ucombine_ ## mode (bot->pixels[i]>>GREEN_SHIFT, \ + top->pixels[i]>>GREEN_SHIFT); \ + BLUE = ucombine_ ## mode (bot->pixels[i]>>BLUE_SHIFT , \ + top->pixels[i]>>BLUE_SHIFT ); \ + break ; + switch( mode ) { + case GIMP_NORMAL_MODE: + case GIMP_DISSOLVE_MODE: + FatalUnexpected("Normal and Dissolve mode can't happen here!"); + UNIFORM(ADDITION); + UNIFORM(SUBTRACT); + UNIFORM(LIGHTEN_ONLY); + UNIFORM(DARKEN_ONLY); + UNIFORM(DIFFERENCE); + UNIFORM(MULTIPLY); + UNIFORM(DIVIDE); + UNIFORM(SCREEN); + case GIMP_SOFTLIGHT_MODE: /* A synonym for "overlay"! */ + UNIFORM(OVERLAY); + UNIFORM(DODGE); + UNIFORM(BURN); + UNIFORM(HARDLIGHT); + UNIFORM(GRAIN_EXTRACT); + UNIFORM(GRAIN_MERGE); + case GIMP_HUE_MODE: + case GIMP_SATURATION_MODE: + case GIMP_VALUE_MODE: + case GIMP_COLOR_MODE: + { + static struct HSV hsvTop, hsvBot ; + RGBtoHSV(top->pixels[i],&hsvTop); + if( mode == GIMP_HUE_MODE && hsvTop.ch1 == hsvTop.ch3 ) + continue ; + RGBtoHSV(bot->pixels[i],&hsvBot); + if( mode == GIMP_VALUE_MODE ) { + if( hsvBot.ch3 ) { + hsvBot.ch1 = (hsvBot.ch1*hsvTop.ch3 + hsvBot.ch3/2) / hsvBot.ch3; + hsvBot.ch2 = (hsvBot.ch2*hsvTop.ch3 + hsvBot.ch3/2) / hsvBot.ch3; + hsvBot.ch3 = hsvTop.ch3 ; + } else { + hsvBot.ch1 = hsvBot.ch2 = hsvBot.ch3 = hsvTop.ch3 ; + } + } else { + unsigned mfNum, mfDenom ; + if( mode == GIMP_HUE_MODE || mode == GIMP_COLOR_MODE ) { + mfNum = hsvTop.ch2-hsvTop.ch1 ; + mfDenom = hsvTop.ch3-hsvTop.ch1 ; + hsvBot.hue = hsvTop.hue ; + } else { + mfNum = hsvBot.ch2-hsvBot.ch1 ; + mfDenom = hsvBot.ch3-hsvBot.ch1 ; + } + if( mode == GIMP_SATURATION_MODE ) { + if( hsvTop.ch3 == 0 ) + hsvBot.ch1 = hsvBot.ch3 ; /* Black has no saturation */ + else + hsvBot.ch1 = (hsvTop.ch1*hsvBot.ch3 + hsvTop.ch3/2) / hsvTop.ch3; + } else if( mode == GIMP_COLOR_MODE ) { + /* GIMP_COLOR_MODE works in HSL space instead of HSV. We must + * transfer H and S, keeping the L = ch1+ch3 of the bottom pixel, + * but the S we transfer works differently from the S in HSV. + */ + unsigned L = hsvTop.ch1 + hsvTop.ch3 ; + unsigned sNum = hsvTop.ch3 - hsvTop.ch1 ; + unsigned sDenom = L < 256 ? L : 510-L ; + if( sDenom == 0 ) sDenom = 1 ; /* sNum will be 0 */ + L = hsvBot.ch1 + hsvBot.ch3 ; + if( L < 256 ) { + /* Ideally we want to compute L/2 * (1-sNum/sDenom) + * But shuffle this a bit so we can use integer arithmetic. + * The "-1" in the rounding prevents us from ending up with + * ch1 > ch3. + */ + hsvBot.ch1 = (L*(sDenom-sNum)+sDenom-1)/(2*sDenom); + hsvBot.ch3 = L - hsvBot.ch1 ; + } else { + /* Here our goal is 255 - (510-L)/2 * (1-sNum/sDenom) */ + hsvBot.ch3 = 255 - ((510-L)*(sDenom-sNum)+sDenom-1)/(2*sDenom); + hsvBot.ch1 = L - hsvBot.ch3 ; + } + assert(hsvBot.ch3 <= 255); + assert(hsvBot.ch3 >= hsvBot.ch1); + } + if( mfDenom == 0 ) + hsvBot.ch2 = hsvBot.ch1 ; + else + hsvBot.ch2 = hsvBot.ch1 + + (mfNum*(hsvBot.ch3-hsvBot.ch1) + mfDenom/2) / mfDenom ; + } + switch( hsvBot.hue ) { + #define HEXTANT(b,m,t) case HUE_ ## b ## _ ## m ## _ ## t : \ + b = hsvBot.ch1; m = hsvBot.ch2; t = hsvBot.ch3; break; + HEXTANT(RED,GREEN,BLUE); + HEXTANT(RED,BLUE,GREEN); + HEXTANT(BLUE,RED,GREEN); + HEXTANT(BLUE,GREEN,RED); + HEXTANT(GREEN,BLUE,RED); + HEXTANT(GREEN,RED,BLUE); + #undef HEXTANT + } + break ; + } + default: + FatalUnsupportedXCF(_("'%s' layer mode"), + _(showGimpLayerModeEffects(mode))); + } + if( FULLALPHA(bot->pixels[i] & top->pixels[i]) ) + bot->pixels[i] = (bot->pixels[i] & (255 << ALPHA_SHIFT)) + + (RED << RED_SHIFT) + + (GREEN << GREEN_SHIFT) + + (BLUE << BLUE_SHIFT) ; + else { + rgba bp = bot->pixels[i] ; + /* In a sane world, the alpha of the top pixel would simply be + * used to interpolate linearly between the bottom pixel's base + * color and the effect-computed color. + * But no! What the Gimp actually does is empirically + * described by the following (which borrows code from + * composite_one() that makes no theoretical sense here): + */ + unsigned tfrac = ALPHA(top->pixels[i]) ; + if( !FULLALPHA(bp) ) { + unsigned pseudotop = (tfrac < ALPHA(bp) ? tfrac : ALPHA(bp)); + unsigned alpha = 255 ^ scaletable[255-ALPHA(bp)][255-pseudotop] ; + tfrac = (256*pseudotop - 1) / alpha ; + } + bot->pixels[i] = (bp & (255 << ALPHA_SHIFT)) + + ((rgba)scaletable[ tfrac ][ RED ] << RED_SHIFT ) + + ((rgba)scaletable[ tfrac ][ GREEN ] << GREEN_SHIFT) + + ((rgba)scaletable[ tfrac ][ BLUE ] << BLUE_SHIFT ) + + ((rgba)scaletable[255^tfrac][255&(bp>>RED_SHIFT )] << RED_SHIFT ) + + ((rgba)scaletable[255^tfrac][255&(bp>>GREEN_SHIFT)] << GREEN_SHIFT) + + ((rgba)scaletable[255^tfrac][255&(bp>>BLUE_SHIFT )] << BLUE_SHIFT ) ; + } + } + return ; +} + +static void +dissolveTile(struct Tile *tile) +{ + unsigned i ; + summary_t summary ; + assert( tile->refcount == 1 ); + if( (tile->summary & TILESUMMARY_CRISP) ) + return ; + summary = TILESUMMARY_UPTODATE + TILESUMMARY_ALLNULL + + TILESUMMARY_ALLFULL + TILESUMMARY_CRISP ; + for( i = 0 ; i < tile->count ; i++ ) { + if( FULLALPHA(tile->pixels[i]) ) + summary &= ~TILESUMMARY_ALLNULL ; + else if ( NULLALPHA(tile->pixels[i]) ) + summary &= ~TILESUMMARY_ALLFULL ; + else if( ALPHA(tile->pixels[i]) > rand() % 0xFF ) { + tile->pixels[i] |= 255 << ALPHA_SHIFT ; + summary &= ~TILESUMMARY_ALLNULL ; + } else { + tile->pixels[i] = 0 ; + summary &= ~TILESUMMARY_ALLFULL ; + } + } + tile->summary = summary ; +} + +static void +roundAlpha(struct Tile *tile) +{ + unsigned i ; + summary_t summary ; + assert( tile->refcount == 1 ); + if( (tile->summary & TILESUMMARY_CRISP) ) + return ; + summary = TILESUMMARY_UPTODATE + TILESUMMARY_ALLNULL + + TILESUMMARY_ALLFULL + TILESUMMARY_CRISP ; + for( i = 0 ; i < tile->count ; i++ ) { + if( ALPHA(tile->pixels[i]) >= 128 ) { + tile->pixels[i] |= 255 << ALPHA_SHIFT ; + summary &= ~TILESUMMARY_ALLNULL ; + } else { + tile->pixels[i] = 0 ; + summary &= ~TILESUMMARY_ALLFULL ; + } + } + tile->summary = summary ; +} + +/* flattenTopdown() shares ownership of top. + * The return value may be a shared tile. + */ +static struct Tile * +flattenTopdown(struct FlattenSpec *spec, struct Tile *top, + unsigned nlayers, const struct rect *where) +{ + struct Tile *tile; + + while( nlayers-- ) { + if( tileSummary(top) & TILESUMMARY_ALLFULL ) + return top ; + if( !spec->layers[nlayers].isVisible ) + continue ; + + tile = getLayerTile(&spec->layers[nlayers],where); + + if( tile->summary & TILESUMMARY_ALLNULL ) + continue ; /* Simulate a tail call */ + + switch( spec->layers[nlayers].mode ) { + case GIMP_NORMAL_NOPARTIAL_MODE: + roundAlpha(tile) ; + /* fall through */ + if(0) { + case GIMP_DISSOLVE_MODE: + dissolveTile(tile); + /* fall through */ + } + case GIMP_NORMAL_MODE: + top = merge_normal(tile,top); + break ; + default: + { + struct Tile *below, *above ; + unsigned i ; + if( !(top->summary & TILESUMMARY_ALLNULL) ) { + rgba tile_or = 0 ; + invalidateSummary(tile,0); + for( i=0; icount; i++ ) + if( FULLALPHA(top->pixels[i]) ) + tile->pixels[i] = 0 ; + else + tile_or |= tile->pixels[i] ; + /* If the tile only has pixels that will be covered by 'top' anyway, + * forget it anyway. + */ + if( ALPHA(tile_or) == 0 ) { + freeTile(tile); + break ; /* from the switch, which will continue the while */ + } + } + /* Create a dummy top for the layers below this */ + if( top->summary & TILESUMMARY_CRISP ) { + above = forkTile(top); + } else { + summary_t summary = TILESUMMARY_ALLNULL ; + above = newTile(*where); + for( i=0; icount; i++ ) + if( FULLALPHA(top->pixels[i]) ) { + above->pixels[i] = -1 ; + summary = 0 ; + } else + above->pixels[i] = 0 ; + above->summary = TILESUMMARY_UPTODATE + TILESUMMARY_CRISP + summary; + } + below = flattenTopdown(spec, above, nlayers, where); + if( below->refcount > 1 ) { + assert( below == top ); + /* This can only happen if 'below' is a copy of 'top' + * THROUGH 'above', which in turn means that none of all + * this is visible after all. So just free it and return 'top'. + */ + freeTile(below); + return top ; + } + merge_exotic(below,tile,spec->layers[nlayers].mode); + freeTile(tile); + top = merge_normal(below,top); + return top ; + } + } + } + return top ; +} + +static void +addBackground(struct FlattenSpec *spec, struct Tile *tile, unsigned ncols) +{ + unsigned i ; + + if( tileSummary(tile) & TILESUMMARY_ALLFULL ) + return ; + + switch( spec->partial_transparency_mode ) { + case FORBID_PARTIAL_TRANSPARENCY: + if( !(tileSummary(tile) & TILESUMMARY_CRISP) ) + FatalGeneric(102,_("Flattened image has partially transparent pixels")); + break ; + case DISSOLVE_PARTIAL_TRANSPARENCY: + dissolveTile(tile); + break ; + case ALLOW_PARTIAL_TRANSPARENCY: + case PARTIAL_TRANSPARENCY_IMPOSSIBLE: + break ; + } + + if( spec->default_pixel == CHECKERED_BACKGROUND ) { + INIT_SCALETABLE_IF( !(tile->summary & TILESUMMARY_CRISP ) ); + for( i=0; icount; i++ ) + if( !FULLALPHA(tile->pixels[i]) ) { + rgba fillwith = ((i/ncols)^(i%ncols))&8 ? 0x66 : 0x99 ; + fillwith = graytable[fillwith] + (255 << ALPHA_SHIFT) ; + if( NULLALPHA(tile->pixels[i]) ) + tile->pixels[i] = fillwith ; + else + tile->pixels[i] = composite_one(fillwith,tile->pixels[i]); + } + tile->summary = TILESUMMARY_UPTODATE + + TILESUMMARY_ALLFULL + TILESUMMARY_CRISP ; + return ; + } + if( !FULLALPHA(spec->default_pixel) ) return ; + if( tileSummary(tile) & TILESUMMARY_ALLNULL ) { + fillTile(tile,spec->default_pixel); + } else { + INIT_SCALETABLE_IF( !(tile->summary & TILESUMMARY_CRISP) ); + for( i=0; icount; i++ ) + if( NULLALPHA(tile->pixels[i]) ) + tile->pixels[i] = spec->default_pixel ; + else if( FULLALPHA(tile->pixels[i]) ) + ; + else + tile->pixels[i] = composite_one(spec->default_pixel,tile->pixels[i]); + + tile->summary = TILESUMMARY_UPTODATE + + TILESUMMARY_ALLFULL + TILESUMMARY_CRISP ; + } +} + +void +flattenIncrementally(struct FlattenSpec *spec,lineCallback callback) +{ + rgba *rows[TILE_HEIGHT] ; + unsigned i, y, nrows, ncols ; + struct rect where ; + struct Tile *tile ; + static struct Tile toptile ; + + toptile.count = TILE_HEIGHT * TILE_WIDTH ; + fillTile(&toptile,0); + + for( where.t = spec->dim.c.t; where.t < spec->dim.c.b; where.t=where.b ) { + where.b = (where.t+TILE_HEIGHT) - where.t % TILE_HEIGHT ; + if( where.b > spec->dim.c.b ) where.b = spec->dim.c.b ; + nrows = where.b - where.t ; + for( y = 0; y < nrows ; y++ ) + rows[y] = xcfmalloc(4*(spec->dim.c.r-spec->dim.c.l)); + + for( where.l = spec->dim.c.l; where.l < spec->dim.c.r; where.l=where.r ) { + where.r = (where.l+TILE_WIDTH) - where.l % TILE_WIDTH ; + if( where.r > spec->dim.c.r ) where.r = spec->dim.c.r ; + ncols = where.r - where.l ; + + toptile.count = ncols * nrows ; + toptile.refcount = 2 ; /* For bug checking */ + assert( toptile.summary == TILESUMMARY_UPTODATE + + TILESUMMARY_ALLNULL + TILESUMMARY_CRISP ); + tile = flattenTopdown(spec,&toptile,spec->numLayers,&where) ; + toptile.refcount-- ; /* addBackground may change destructively */ + addBackground(spec,tile,ncols); + + for( i = 0 ; i < tile->count ; i++ ) + if( NULLALPHA(tile->pixels[i]) ) + tile->pixels[i] = 0 ; + for( y = 0 ; y < nrows ; y++ ) + memcpy(rows[y] + (where.l - spec->dim.c.l), + tile->pixels + y * ncols, ncols*4); + + if( tile == &toptile ) { + fillTile(&toptile,0); + } else { + freeTile(tile); + } + } + for( y = 0 ; y < nrows ; y++ ) + callback(spec->dim.width,rows[y]); + } +} + +static rgba **collectPointer ; + +static void +collector(unsigned num,rgba *row) +{ + *collectPointer++ = row ; +} + +rgba ** +flattenAll(struct FlattenSpec *spec) +{ + rgba **rows = xcfmalloc(spec->dim.height * sizeof(rgba*)); + if( verboseFlag ) + fprintf(stderr,_("Flattening image ...")); + collectPointer = rows ; + flattenIncrementally(spec,collector); + if( verboseFlag ) + fprintf(stderr,"\n"); + return rows ; +} + +void +shipoutWithCallback(struct FlattenSpec *spec, rgba **pixels, + lineCallback callback) +{ + unsigned i ; + for( i = 0; i < spec->dim.height; i++ ) { + callback(spec->dim.width,pixels[i]); + } + xcffree(pixels); +} diff --git a/kernel/kls_xcf/xcf2pnm/flatten.h b/kernel/kls_xcf/xcf2pnm/flatten.h new file mode 100644 index 0000000..c252175 --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/flatten.h @@ -0,0 +1,77 @@ +/* Flattning functions for xcftools + * + * Copyright (C) 2006 Henning Makholm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FLATTEN_H +#define FLATTEN_H + +#include "xcftools.h" +#include "pixels.h" + +#define PERHAPS_ALPHA_CHANNEL (NEWALPHA(0,1)) +#define FORCE_ALPHA_CHANNEL (NEWALPHA(0,2)) +#define CHECKERED_BACKGROUND (NEWALPHA(0,200)) +struct FlattenSpec { + struct tileDimensions dim ; + rgba default_pixel ; + int numLayers ; + struct xcfLayer *layers ; + + const char * transmap_filename ; + const char * output_filename ; + enum out_color_mode { + COLOR_BY_FILENAME, + COLOR_BY_CONTENTS, + COLOR_INDEXED, + COLOR_RGB, + COLOR_GRAY, + COLOR_MONO + } out_color_mode ; + enum { ALLOW_PARTIAL_TRANSPARENCY, + DISSOLVE_PARTIAL_TRANSPARENCY, + FORBID_PARTIAL_TRANSPARENCY, + PARTIAL_TRANSPARENCY_IMPOSSIBLE + } partial_transparency_mode ; + enum { USE_CANVAS = 0, + MANUAL_OFFSET = 1, + MANUAL_CROP = 2, + AUTOCROP = 4 } window_mode ; + int process_in_memory ; + int gimpish_indexed ; +}; + +/* From flatspec.c */ + +void init_flatspec(struct FlattenSpec *); + +void add_layer_request(struct FlattenSpec *,const char *name); +struct xcfLayer *lastlayerspec(struct FlattenSpec *,const char *option); + +typedef enum out_color_mode (*guesser) (struct FlattenSpec *,rgba **); + +/* Call this after processing options, and after opening the XCF file */ +void complete_flatspec(struct FlattenSpec *,guesser); +void analyse_colormode(struct FlattenSpec *,rgba **allPixels,guesser); + +/* From flatten.c */ + +typedef void (*lineCallback)(unsigned num,rgba *pixels); +void flattenIncrementally(struct FlattenSpec *,lineCallback); +rgba **flattenAll(struct FlattenSpec*); +void shipoutWithCallback(struct FlattenSpec *,rgba **pixels,lineCallback); + +#endif /* FLATTEN_H */ diff --git a/kernel/kls_xcf/xcf2pnm/io-unix.c b/kernel/kls_xcf/xcf2pnm/io-unix.c new file mode 100644 index 0000000..38dc4e4 --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/io-unix.c @@ -0,0 +1,176 @@ +/* OS-specific IO functions for xcftools + * + * Copyright (C) 2006 Henning Makholm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "xcftools.h" +#include +#include +#include +#include +#include +#include +#include +#if HAVE_MMAP +#include +#endif + +static FILE *xcfstream = 0 ; + +void +free_or_close_xcf(void) +{ + if( xcf_file ) { + if( xcfstream ) { + munmap(xcf_file,xcf_length) ; + fclose(xcfstream); + xcf_file = 0 ; + xcfstream = 0 ; + } else { + free(xcf_file) ; + xcf_file = 0 ; + } + } +} + +void +read_or_mmap_xcf(const char *filename,const char *unzipper) +{ + struct stat statbuf ; + + free_or_close_xcf() ; + + if( strcmp(filename,"-") != 0 ) { + if( access(filename,R_OK) != 0 ) + FatalGeneric(21,"!%s",filename); + } + + if( !unzipper ) { + const char *pc ; + pc = filename + strlen(filename) ; + if( pc-filename > 2 && strcmp(pc-2,"gz") == 0 ) + unzipper = "zcat" ; + else if ( pc-filename > 3 && strcmp(pc-3,"bz2") == 0 ) + unzipper = "bzcat" ; + else + unzipper = "" ; + } else if( strcmp(unzipper,"cat") == 0 ) + unzipper = "" ; + + if( *unzipper ) { + int pid, status, outfd ; +#if HAVE_MMAP + xcfstream = tmpfile() ; + if( !xcfstream ) + FatalUnexpected(_("!Cannot create temporary unzipped file")); + outfd = fileno(xcfstream) ; +#else + int fh[2] ; + if( pipe(fh) < 0 ) + FatalUnexpected("!Cannot create pipe for %s",unzipper); + xcfstream = fdopen(fh[1],"rb") ; + if( !xcfstream ) + FatalUnexpected("!Cannot fdopen() unzipper pipe"); + outfd = fh[0] ; +#endif + if( (pid = fork()) == 0 ) { + /* We're the child */ + if( dup2(outfd,1) < 0 ) { + perror("Cannot dup2 in unzip process"); + exit(127) ; + } + fclose(xcfstream) ; + execlp(unzipper,unzipper,filename,NULL) ; + fprintf(stderr,_("Cannot execute ")); + perror(unzipper); + exit(126) ; + } +#if HAVE_MMAP + while( wait(&status) != pid ) + ; + if( WIFEXITED(status) ) { + status = WEXITSTATUS(status) ; + if( status > 0 ) { + fclose(xcfstream) ; + xcfstream = 0 ; + FatalGeneric(status,NULL); + } + } else { + fclose(xcfstream) ; + xcfstream = 0 ; + FatalGeneric(126,_("%s terminated abnormally"),unzipper); + } +#else + close(fh[0]) ; +#endif + } else if( strcmp(filename,"-") == 0 ) { + xcfstream = fdopen(dup(0),"rb") ; + if( !xcfstream ) + FatalUnexpected("!Cannot dup stdin for input") ; + } else { + xcfstream = fopen(filename,"rb") ; + if( !xcfstream ) + FatalGeneric(21,_("!Cannot open %s"),filename); + } + /* OK, now we have an open stream ... */ + if( fstat(fileno(xcfstream),&statbuf) == 0 && + (statbuf.st_mode & S_IFMT) == S_IFREG ) { + xcf_length = statbuf.st_size ; +#if HAVE_MMAP + xcf_file = mmap(0,xcf_length,PROT_READ,MAP_SHARED,fileno(xcfstream),0); + if( xcf_file != (void*)-1 ) + return ; + if( errno != ENODEV ) { + int saved = errno ; + fclose(xcfstream) ; + xcf_file = 0 ; + errno = saved ; + FatalUnexpected("!Could not mmap input"); + } +#endif + xcf_file = malloc(xcf_length); + if( xcf_file == 0 ) + FatalUnexpected(_("Out of memory for xcf data")); + if( fread(xcf_file,1,xcf_length,xcfstream) != xcf_length ) { + if( feof(xcfstream) ) + FatalUnexpected(_("XCF file shrunk while reading it")); + else + FatalUnexpected(_("!Could not read xcf data")); + } + fclose(xcfstream) ; + xcfstream = 0 ; + } else { + size_t blocksize = 0x80000 ; /* 512 KB */ + xcf_length = 0 ; + xcf_file = 0 ; + while(1) { + xcf_file = realloc(xcf_file,blocksize) ; + if( xcf_file == 0 ) + FatalUnexpected(_("Out of memory for xcf data")); + size_t actual = fread(xcf_file+xcf_length,1,blocksize-xcf_length, + xcfstream) ; + xcf_length += actual ; + if( feof(xcfstream) ) + break ; + if( xcf_length < blocksize ) { + FatalUnexpected(_("!Could not read xcf data")) ; + } + blocksize += (blocksize >> 1) & ~(size_t)0x3FFF ; /* 16 KB granularity */ + } + fclose(xcfstream) ; + xcfstream = 0 ; + } +} diff --git a/kernel/kls_xcf/xcf2pnm/options.i b/kernel/kls_xcf/xcf2pnm/options.i new file mode 100644 index 0000000..f891767 --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/options.i @@ -0,0 +1,410 @@ +/* Option processing for xcftools -*- C -*- + * + * Copyright (C) 2006 Henning Makholm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +OPTIONGROUP(1i,General options); + +OPTION('h',--help,show this message, + (Print an option summery to standard output and exit with a + return code of 0. + )); +exit(0); + +OPTION('V',--version,show version, + (Print the version numer of + .B xcftools + to standard output and exit with a return code of 0. + )); +printf(OPTI_TARGET " - " PACKAGE_STRING "\n"); +exit(0); + +OPTION('v',--verbose,show progress messages, + (Print progress messages about the conversion to standard error. + )); +verboseFlag = 1 ; +break ; + +OPTION('j',--bzip,input is bzip2 compressed, + (Equivalent to + .BR "\-Z bzcat" . + Default if the filename ends with + .BR bz2 . + )); +unzipper = "bzcat" ; +break ; + +OPTION('z',--gzip,input is gzip compressed, + (Equivalent to + .BR "\-Z zcat" . + Default if the filename ends with + .BR gz . + )); +unzipper = "zcat" ; +break ; + +OPTION('Z',--unpack,(command) use 'command' to decompress input, + (Specify a command that the input file is filtered through + before being interpreted as an XCF file. The command is invoked as + .I command filename + and must produce output to its standard output. + Note that it is not possible to specify arguments as part of + .IR command . + An uncompressor is selected automatically if the filename ends + with + .B gz + or + .BR bz2 ; + to suppress this, use + .B \-Z cat + (which is implemented without actually starting a + .BR cat (1) + process). + )); +unzipper = optarg ; +break ; + +#ifdef XCF2FOO + +OPTION('o',--output,(filename) name output file, + (Write the converted picture to + .I filename + instead of to standard output. + )); +flatspec.output_filename = optarg ; +break ; + +#ifdef XCF2PNM +OPTION('a',--alpha,(filename) write transparency map, + (Output a transparency mask for the flattened image to + .I filename + as a + .BR pgm (5) + file, in addition to the ordinary output. + If the flattened image is completely opaque, this will produce an + error message and exit status 101; + use + .B \-A + to suppress this. + )); +flatspec.transmap_filename = optarg ; +break ; +#endif + +OPTION('b',--background,(color) select background color, + (Use this color for transparent pixels in the image. + The color can be given as + .B #rrggbb + or + .B #rgb + hexadecimal values, + or as an X11 color name + (which will only work if a color name database can be found + in one of a number of standard locations). + )); +{ + unsigned r,g,b ; + unsigned long hex ; + int met = 0 ; + if( *optarg == '#' ) + sscanf(optarg+1,"%lx%n",&hex,&met); + if( met == 3 && strlen(optarg) == 4 ) { + r = ((hex >> 8) & 0xF) * 0x11 ; + g = ((hex >> 4) & 0xF) * 0x11 ; + b = ((hex >> 0) & 0xF) * 0x11 ; + } else if( met == 6 && strlen(optarg) == 7 ) { + r = ((hex >> 16) & 0xFF) ; + g = ((hex >> 8) & 0xFF) ; + b = ((hex >> 0) & 0xFF) ; + } else if( strcasecmp(optarg,"black") == 0 ) + r = g = b = 0 ; + else if( strcasecmp(optarg,"white") == 0 ) + r = g = b = 255 ; + else { + const char *filenames[] = { "/etc/X11/rgb.txt", + "/usr/lib/X11/rgb.txt", + "/usr/share/X11/rgb.txt", + NULL }; + const char **fnp ; + r = (unsigned)-1 ; + int any = 0 ; + for( fnp = filenames; r == (unsigned)-1 && fnp && *fnp; fnp++ ) { + FILE *colortable = fopen(*fnp,"rt"); + if( colortable ) { + any = 1 ; + int clen ; + char colorbuf[80] ; + do { + if( !fgets(colorbuf,sizeof colorbuf,colortable) ) { + r = (unsigned)-1 ; + break ; + } + clen = strlen(colorbuf); + while( clen && isspace(colorbuf[clen-1]) ) + clen-- ; + colorbuf[clen] = '\0' ; + clen = 0 ; + sscanf(colorbuf," %u %u %u %n",&r,&g,&b,&clen); + } while( clen == 0 || strcasecmp(colorbuf+clen,optarg) != 0 ); + fclose(colortable) ; + } + } + if( !any ) { + fprintf(stderr,_("Could not find X11 color database\n")); + } + } + if( r == (unsigned)-1 ) + FatalGeneric(20,_("Unknown background color '%s'"),optarg); + flatspec.default_pixel = ((rgba)255 << ALPHA_SHIFT) + + ((rgba)r << RED_SHIFT) + + ((rgba)g << GREEN_SHIFT) + + ((rgba)b << BLUE_SHIFT); + break ; +} + +OPTION('A',--force-alpha,force alpha channel in output, + (Invent a trivial alpha channel even if the flattened image is + completely opaque. + )); +flatspec.default_pixel = FORCE_ALPHA_CHANNEL ; +break ; + +OPTION('c',--color --colour,select color output, + (Force the output to use RGB color space even if it there are + more compact alternatives. +#ifdef XCF2PNM + This will be selected automatically if the output file''s name + ends with + .BR .ppm . +#endif + )); +flatspec.out_color_mode = COLOR_RGB ; +break ; + +OPTION('g',--gray --grey,select grayscale output, + (Force the output to be a grayscale image even if it may be monochrome. + If any colored pixels are encountered, exit with status 103. + This will be selected automatically if the output file''s name + ends with + .BR .pgm . + )); +flatspec.out_color_mode = COLOR_GRAY ; +break ; + +#ifdef XCF2PNM +OPTION('m',--mono,select monochrome output, + (Force the output to be a monochrome image. + If any colors except black and white are encountered, exit with + status 103. + This will be selected automatically if the output file''s name + ends with + .BR .pbm . + )); +flatspec.out_color_mode = COLOR_MONO ; +break ; +#endif + +#ifdef XCF2PNM +OPTION('n',--pnm,select -c/-g/-m by image contents, + (Suppress the automatic choice of + .BR \-c , + .BR \-g , + or + .BR \-m + based on output filename, and instead select the output format + based on image contents. + This is the default if the filename is not recognized, and + when writing to stdout. + )); +flatspec.out_color_mode = COLOR_BY_CONTENTS ; +break ; +#endif + +OPTION('T',--truecolor,treat indexed images as RGB for flattening, + (Use standard RGB compositing for flattening indexed layers. + Without this option, + .B \*p + will mimic the Gimp''s current strategy of rounding each + alpha value to either full transparency or full opacity, + and interpret all layer modes as + .BR Normal . + )); +flatspec.gimpish_indexed = 0 ; +break ; + +OPTION('G',--for-gif,disallow partial transparency, + (Assert that the flattened image will have no partial transparency + (allowing a more compact representation of the alpha output). + Exit with status 102 if the flattened image has any partial + transparency. + If + .B \-b + is also given, this tests whether there there is partial + transparency before applying the background color. + )); +flatspec.partial_transparency_mode = FORBID_PARTIAL_TRANSPARENCY ; +break ; + +OPTION('D',--dissolve,dissolve partial transparency, + (Do a "dissolve" step to eliminate partial transparency after + flattening. + If + .B \-b + is also given, this happens before the background color is applied. + )); +flatspec.partial_transparency_mode = DISSOLVE_PARTIAL_TRANSPARENCY ; +break ; + +OPTION('f',--full-image,flatten to memory; then analyse, + (First flatten the entire image to a memory buffer before writing + output. Then analyse the image to decide on the details of the + output format (e.g., whether a grayscale output is sufficient). + Without this option, the program flattens only a singe row of "tiles" + (height 64) at a time. + )); +flatspec.process_in_memory = 1 ; +break ; + +OPTION('S',--size,(w"x"h) crop image while converting, + (Crop the converted image to width \fIw\fP and height \fIh\fP. + )); +{ + unsigned w,h ; + int n = 0 ; + sscanf(optarg,"%ux%u%n",&w,&h,&n) ; + if( n && n == strlen(optarg) ) { + if( flatspec.window_mode == AUTOCROP ) flatspec.window_mode = USE_CANVAS ; + flatspec.window_mode |= MANUAL_CROP ; + flatspec.dim.width = w ; + flatspec.dim.height = h ; + } else + FatalGeneric(20,_("-S option must have an argument of the form wxh")); + break ; +} + +OPTION('O',--offset,(x","y) translate converted part of image, + (Offset the converted part of the image from the top-left corner + of the XCF canvas. Usually used with + .BR \-S . + )); +{ + int x,y ; + int n = 0 ; + sscanf(optarg,"%d,%d%n",&x,&y,&n) ; + if( n && n == strlen(optarg) ) { + if( flatspec.window_mode == AUTOCROP ) flatspec.window_mode = USE_CANVAS ; + flatspec.window_mode |= MANUAL_OFFSET ; + flatspec.dim.c.l = x ; + flatspec.dim.c.t = y ; + } else + FatalGeneric(20,_("-O option must have an argument of the form x,y")); + break ; +} + +OPTION('C',--autocrop,autocrop to visible layer boundaries, + (Crop and offset the converted part of the image to just include + the boundaries of the visible (or selected) layers. + (Note that the + .I contents + of the layers is not taken into account when autocropping). + .IP + In the absence of options that specify otherwise, the converted + image will cover the entire XCF canvas. + )); +flatspec.window_mode = AUTOCROP ; +break ; + +#ifndef XCFVIEW +OPTIONGROUP(1il,Layer-selection options); +#endif + +OPTION(300,--mode,(mode) set layer mode, + (Set the layer mode (e.g., + .B Normal + or + .BR Multiply ). + )); +{ + GimpLayerModeEffects m ; + #ifdef ENABLE_NLS + for( m = 0; m < GimpLayerModeEffects_LAST; m++ ) + if( strcmp(optarg,_(showGimpLayerModeEffects(m))) == 0 ) + goto found_localized ; + #endif + + for( m = 0; strcmp(optarg,showGimpLayerModeEffects(m)) != 0 ; m++ ) { + if( m > GimpLayerModeEffects_LAST ) + FatalGeneric(20,_("Layer mode '%s' is unknown"),optarg); + } + found_localized: + lastlayerspec(&flatspec,"--mode")->mode = m ; + break ; +} + +OPTION(301,--percent,(n) set opacity in percent, + (Set the opacity on a scale from 0 to 100 + (as in the Gimp user interface). + )); +{ + unsigned pct ; + int n ; + sscanf(optarg,"%u%n",&pct,&n) ; + if( n != strlen(optarg) || pct > 100 ) + FatalGeneric(20,_("The argument to --percent is not a percentage")); + lastlayerspec(&flatspec,"--percent")->opacity = pct * 255 / 100 ; + break ; +} + +OPTION(302,--opacity,(n) set opacity in 1/255 units, + (Set the opacity on a scale from 0 to 255 (as used internally) + )); +{ + unsigned alpha ; + int n ; + sscanf(optarg,"%u%n",&alpha,&n) ; + if( n != strlen(optarg) || alpha > 255 ) + FatalGeneric(20,_("The argument to --opacity is not a number " + "between 0 and 255")); + lastlayerspec(&flatspec,"--percent")->opacity = alpha ; + break ; +} + +OPTION(303,--mask,enable layer mask, + (Enable the layer mask. + )); +lastlayerspec(&flatspec,"--mask")->hasMask = 1 ; +break ; + +OPTION(304,--nomask,disable layer mask, + (Disable the layer mask. + )); +lastlayerspec(&flatspec,"--nomask")->hasMask = 0 ; +break ; + +#endif /* XCF2FOO */ + +OPTIONGROUP(1i,) + +#if HAVE_ICONV +OPTION('u',--utf8,use UTF-8 for layer names, + (Use the raw UTF-8 representation from the XCF file to compare + and display layer names. + Ordinarily, layer names will be converted to the character set + of the current locale. + )); +use_utf8 = 1 ; +break ; +#endif diff --git a/kernel/kls_xcf/xcf2pnm/pixels.c b/kernel/kls_xcf/xcf2pnm/pixels.c new file mode 100644 index 0000000..65891f9 --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/pixels.c @@ -0,0 +1,487 @@ +/* Pixel and tile functions for xcftools + * + * Copyright (C) 2006 Henning Makholm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define DEBUG +#include "xcftools.h" +#include "pixels.h" +#include +#include + +rgba colormap[256] ; +unsigned colormapLength=0 ; + +int +degrayPixel(rgba pixel) +{ + if( ((pixel >> RED_SHIFT) & 255) == ((pixel >> GREEN_SHIFT) & 255) && + ((pixel >> RED_SHIFT) & 255) == ((pixel >> BLUE_SHIFT) & 255) ) + return (pixel >> RED_SHIFT) & 255 ; + return -1 ; +} + +/* ****************************************************************** */ + +typedef const struct _convertParams { + int bpp ; + int shift[4] ; + uint32_t base_pixel ; + const rgba *lookup ; +} convertParams ; +#define RGB_SHIFT RED_SHIFT, GREEN_SHIFT, BLUE_SHIFT +#define OPAQUE (255 << ALPHA_SHIFT) +static convertParams convertRGB = { 3, {RGB_SHIFT}, OPAQUE, 0 }; +static convertParams convertRGBA = { 4, {RGB_SHIFT, ALPHA_SHIFT}, 0,0 }; +static convertParams convertGRAY = { 1, {-1}, OPAQUE, graytable }; +static convertParams convertGRAYA = { 2, {-1,ALPHA_SHIFT}, 0, graytable }; +static convertParams convertINDEXED = { 1, {-1}, OPAQUE, colormap }; +static convertParams convertINDEXEDA = { 2, {-1,ALPHA_SHIFT}, 0, colormap }; + +static convertParams convertColormap = { 3, {RGB_SHIFT}, 0, 0 }; +static convertParams convertChannel = { 1, {ALPHA_SHIFT}, 0, 0 }; + +/* ****************************************************************** */ + +static inline int +tileDirectoryOneLevel(struct tileDimensions *dim,uint32_t ptr) +{ + if( ptr == 0 ) + return 0 ; + if( xcfL(ptr ) != dim->c.r - dim->c.l || + xcfL(ptr+4) != dim->c.b - dim->c.t ) + FatalBadXCF("Drawable size mismatch at %" PRIX32, ptr); + return ptr += 8 ; +} + +static void +initTileDirectory(struct tileDimensions *dim,struct xcfTiles *tiles, + const char *type) +{ + uint32_t ptr ; + uint32_t data ; + + ptr = tiles->hierarchy ; + tiles->hierarchy = 0 ; + if( (ptr = tileDirectoryOneLevel(dim,ptr)) == 0 ) return ; + if( tiles->params == &convertChannel ) { + /* A layer mask is a channel. + * Skip a name and a property list. + */ + xcfString(ptr,&ptr); + while( xcfNextprop(&ptr,&data) != PROP_END ) + ; + ptr = xcfOffset(ptr,4*4); + if( (ptr = tileDirectoryOneLevel(dim,ptr)) == 0 ) return ; + } + /* The XCF format has a dummy "hierarchy" level which was + * once meant to mean something, but never happened. It contains + * the bpp value and a list of "level" pointers; but only the + * first level actually contains data. + */ + data = xcfL(ptr) ; + if( xcfL(ptr) != tiles->params->bpp ) + FatalBadXCF("%"PRIu32" bytes per pixel for %s drawable",xcfL(ptr),type); + ptr = xcfOffset(ptr+4,3*4) ; + if( (ptr = tileDirectoryOneLevel(dim,ptr)) == 0 ) return ; + + xcfCheckspace(ptr,dim->ntiles*4+4,"Tile directory at %" PRIX32,ptr); + if( xcfL(ptr + dim->ntiles*4) != 0 ) + FatalBadXCF("Wrong sized tile directory at %" PRIX32,ptr); +#define REUSE_RAW_DATA tiles->tileptrs = (uint32_t*)(xcf_file + ptr) +#if defined(WORDS_BIGENDIAN) && defined(CAN_DO_UNALIGNED_WORDS) + REUSE_RAW_DATA; +#else +# if defined(WORDS_BIGENDIAN) + if( (ptr&3) == 0 ) REUSE_RAW_DATA; else +# endif + { + unsigned i ; + tiles->tileptrs = xcfmalloc(dim->ntiles * sizeof(uint32_t)) ; + for( i = 0 ; i < dim->ntiles ; i++ ) + tiles->tileptrs[i] = xcfL(ptr+i*4); + } +#endif +} + +void +initLayer(struct xcfLayer *layer) { + if( layer->dim.ntiles == 0 || + (layer->pixels.hierarchy == 0 && layer->mask.hierarchy == 0) ) + return ; + switch(layer->type) { +#define DEF(X) case GIMP_##X##_IMAGE: layer->pixels.params = &convert##X; break + DEF(RGB); + DEF(RGBA); + DEF(GRAY); + DEF(GRAYA); + DEF(INDEXED); + DEF(INDEXEDA); + default: + FatalUnsupportedXCF(_("Layer type %s"),_(showGimpImageType(layer->type))); + } + initTileDirectory(&layer->dim,&layer->pixels, + _(showGimpImageType(layer->type))); + layer->mask.params = &convertChannel ; + initTileDirectory(&layer->dim,&layer->mask,"layer mask"); +} +static void copyStraightPixels(rgba *dest,unsigned npixels, + uint32_t ptr,convertParams *params); +void +initColormap(void) { + uint32_t ncolors ; + if( XCF.colormapptr == 0 ) { + colormapLength = 0 ; + return ; + } + ncolors = xcfL(XCF.colormapptr) ; + if( ncolors > 256 ) + FatalUnsupportedXCF(_("Color map has more than 256 entries")); + copyStraightPixels(colormap,ncolors,XCF.colormapptr+4,&convertColormap); + colormapLength = ncolors ; +#ifdef xDEBUG + { + unsigned j ; + fprintf(stderr,"Colormap decoding OK\n"); + for( j = 0 ; j < ncolors ; j++ ) { + if( j % 8 == 0 ) fprintf(stderr,"\n"); + fprintf(stderr," %08x",colormap[j]); + } + fprintf(stderr,"\n"); + } +#endif +} + +/* ****************************************************************** */ + +struct Tile * +newTile(struct rect r) +{ + unsigned npixels = (unsigned)(r.b-r.t) * (unsigned)(r.r-r.l) ; + struct Tile *data + = xcfmalloc(sizeof(struct Tile) - + sizeof(rgba)*(TILE_HEIGHT*TILE_WIDTH - npixels)) ; + data->count = npixels ; + data->refcount = 1 ; + data->summary = 0 ; + return data ; +} + +struct Tile * +forkTile(struct Tile* tile) +{ + if( ++tile->refcount <= 0 ) + FatalUnsupportedXCF(_("Unbelievably many layers?\n" + "More likely to be a bug in %s"),progname); + return tile ; +} + +void +freeTile(struct Tile* tile) +{ + if( --tile->refcount == 0 ) + xcffree(tile) ; +} + +summary_t +tileSummary(struct Tile *tile) +{ + unsigned i ; + summary_t summary ; + if( (tile->summary & TILESUMMARY_UPTODATE) != 0 ) + return tile->summary ; + summary = TILESUMMARY_ALLNULL + TILESUMMARY_ALLFULL + TILESUMMARY_CRISP ; + for( i=0; summary && icount; i++ ) { + if( FULLALPHA(tile->pixels[i]) ) + summary &= ~TILESUMMARY_ALLNULL ; + else if( NULLALPHA(tile->pixels[i]) ) + summary &= ~TILESUMMARY_ALLFULL ; + else + summary = 0 ; + } + summary += TILESUMMARY_UPTODATE ; + tile->summary = summary ; + return summary ; +} + +void +fillTile(struct Tile *tile,rgba data) +{ + unsigned i ; + for( i = 0 ; i < tile->count ; i++ ) + tile->pixels[i] = data ; + if( FULLALPHA(data) ) + tile->summary = TILESUMMARY_UPTODATE+TILESUMMARY_ALLFULL+TILESUMMARY_CRISP; + else if (NULLALPHA(data) ) + tile->summary = TILESUMMARY_UPTODATE+TILESUMMARY_ALLNULL+TILESUMMARY_CRISP; + else + tile->summary = TILESUMMARY_UPTODATE ; +} + +/* ****************************************************************** */ + +static void +copyStraightPixels(rgba *dest,unsigned npixels, + uint32_t ptr,convertParams *params) +{ + unsigned bpp = params->bpp; + const rgba *lookup = params->lookup; + rgba base_pixel = params->base_pixel ; + uint8_t *bp = xcf_file + ptr ; + xcfCheckspace(ptr,bpp*npixels, + "pixel array (%u x %d bpp) at %"PRIX32,npixels,bpp,ptr); + while( npixels-- ) { + rgba pixel = base_pixel ; + unsigned i ; + for( i = 0 ; i < bpp ; i++ ) { + if( params->shift[i] < 0 ) { + pixel += lookup[*bp++] ; + } else { + pixel += *bp++ << params->shift[i] ; + } + } + *dest++ = pixel ; + } +} + +static inline void +copyRLEpixels(rgba *dest,unsigned npixels,uint32_t ptr,convertParams *params) +{ + unsigned i,j ; + rgba base_pixel = params->base_pixel ; + +#ifdef xDEBUG + fprintf(stderr,"RLE stream at %x, want %u x %u pixels, base %x\n", + ptr,params->bpp,npixels,base_pixel); +#endif + + + /* This algorithm depends on the indexed byte always being the first one */ + if( params->shift[0] < -1 ) + base_pixel = 0 ; + for( j = npixels ; j-- ; ) + dest[j] = base_pixel ; + + for( i = 0 ; i < params->bpp ; i++ ) { + int shift = params->shift[i] ; + if( shift < 0 ) + shift = 0 ; + for( j = 0 ; j < npixels ; ) { + int countspec ; + unsigned count ; + xcfCheckspace(ptr,2,"RLE data stream"); + countspec = (int8_t) xcf_file[ptr++] ; + count = countspec >= 0 ? countspec+1 : -countspec ; + if( count == 128 ) { + xcfCheckspace(ptr,3,"RLE long count"); + count = xcf_file[ptr++] << 8 ; + count += xcf_file[ptr++] ; + } + if( j + count > npixels ) + FatalBadXCF("Overlong RLE run at %"PRIX32" (plane %u, %u left)", + ptr,i,npixels-j); + if( countspec >= 0 ) { + rgba data = (uint32_t) xcf_file[ptr++] << shift ; + while( count-- ) + dest[j++] += data ; + } else { + while( count-- ) + dest[j++] += (uint32_t) xcf_file[ptr++] << shift ; + } + } + if( i == 0 && params->shift[0] < 0 ) { + const rgba *lookup = params->lookup ; + base_pixel = params->base_pixel ; + for( j = npixels ; j-- ; ) { + dest[j] = lookup[dest[j]-base_pixel] + base_pixel ; + } + } + } +#ifdef xDEBUG + fprintf(stderr,"RLE decoding OK at %"PRIX32"\n",ptr); + /* + for( j = 0 ; j < npixels ; j++ ) { + if( j % 8 == 0 ) fprintf(stderr,"\n"); + fprintf(stderr," %8x",dest[j]); + } + fprintf(stderr,"\n"); + */ +#endif +} + +static inline void +copyTilePixels(struct Tile *dest, uint32_t ptr,convertParams *params) +{ + if( FULLALPHA(params->base_pixel) ) + dest->summary = TILESUMMARY_UPTODATE+TILESUMMARY_ALLFULL+TILESUMMARY_CRISP; + else + dest->summary = 0 ; + switch( XCF.compression ) { + case COMPRESS_NONE: + copyStraightPixels(dest->pixels,dest->count,ptr,params); + break ; + case COMPRESS_RLE: + copyRLEpixels(dest->pixels,dest->count,ptr,params); + break ; + default: + FatalUnsupportedXCF(_("%s compression"), + _(showXcfCompressionType(XCF.compression))); + } +} + +static struct Tile * +getMaskOrLayerTile(struct tileDimensions *dim, struct xcfTiles *tiles, + struct rect want) +{ + struct Tile *tile = newTile(want); + + assert( want.l < want.r && want.t < want.b ); + if( tiles->tileptrs == 0 ) { + fillTile(tile,0); + return tile ; + } + +#ifdef xDEBUG + fprintf(stderr,"getMaskOrLayer: (%d-%d),(%d-%d)\n",left,right,top,bottom); +#endif + + if( isSubrect(want,dim->c) && + (want.l - dim->c.l) % TILE_WIDTH == 0 && + (want.t - dim->c.t) % TILE_HEIGHT == 0 ) { + unsigned tx = (want.l - dim->c.l) / TILE_WIDTH ; + unsigned ty = (want.t - dim->c.t) / TILE_WIDTH ; + if( want.r == TILEXn(*dim,tx+1) && want.b == TILEYn(*dim,ty+1) ) { + /* The common case? An entire single tile from the layer */ + copyTilePixels(tile,tiles->tileptrs[tx + ty*dim->tilesx],tiles->params); + return tile ; + } + } + + /* OK, we must construct the wanted tile as a jigsaw */ + { + unsigned width = want.r-want.l ; + rgba *pixvert = tile->pixels ; + rgba *pixhoriz ; + unsigned y, ty, l0, l1, lstart, lnum ; + unsigned x, tx, c0, c1, cstart, cnum ; + + if( !isSubrect(want,dim->c) ) { + if( want.l < dim->c.l ) pixvert += (dim->c.l - want.l), + want.l = dim->c.l ; + if( want.r > dim->c.r ) want.r = dim->c.r ; + if( want.t < dim->c.t ) pixvert += (dim->c.t - want.t) * width, + want.t = dim->c.t ; + if( want.b > dim->c.b ) want.b = dim->c.b ; + fillTile(tile,0); + } else { + tile->summary = -1 ; /* I.e. whatever the jigsaw pieces say */ + } + +#ifdef xDEBUG + fprintf(stderr,"jig0 (%d-%d),(%d-%d)\n",left,right,top,bottom); +#endif + + for( y=want.t, ty=(want.t-dim->c.t)/TILE_HEIGHT, l0=TILEYn(*dim,ty); + y want.b ? want.b : l1) - y ; + + pixhoriz = pixvert ; + for( x=want.l, tx=(want.l-dim->c.l)/TILE_WIDTH, c0=TILEXn(*dim,tx); + x want.r ? want.r : c1) - x ; + + { + static struct Tile tmptile ; + unsigned dwidth = c1-c0 ; + unsigned i, j ; + tmptile.count = (c1-c0)*(l1-l0) ; +#ifdef xDEBUG + fprintf(stderr,"jig ty=%u(%u-%u-%u)(%u+%u) tx=%u(%u-%u-%u)(%u+%u)\n", + ty,l0,y,l1,lstart,lnum, + tx,c0,x,c1,cstart,cnum); +#endif + copyTilePixels(&tmptile, + tiles->tileptrs[tx+ty*dim->tilesx],tiles->params); + for(i=0; isummary &= tmptile.summary ; + } + } + } + } + return tile ; +} + +void +applyMask(struct Tile *tile, struct Tile *mask) +{ + unsigned i ; + assertTileCompatibility(tile,mask); + assert( tile->count == mask->count ); + INIT_SCALETABLE_IF(1); + invalidateSummary(tile,0); + for( i=0; i < tile->count ;i++ ) + tile->pixels[i] = NEWALPHA(tile->pixels[i], + scaletable[mask->pixels[i]>>ALPHA_SHIFT] + [ALPHA(tile->pixels[i])]); + freeTile(mask); +} + +struct Tile * +getLayerTile(struct xcfLayer *layer,const struct rect *where) +{ + struct Tile *data ; + +#ifdef xDEBUG + fprintf(stderr,"getLayerTile(%s): (%d-%d),(%d-%d)\n", + layer->name,where->l,where->r,where->t,where->b); +#endif + + if( disjointRects(*where,layer->dim.c) || + layer->opacity == 0 ) { + data = newTile(*where); + fillTile(data,0); + return data ; + } + + data = getMaskOrLayerTile(&layer->dim,&layer->pixels,*where); + if( (data->summary & TILESUMMARY_ALLNULL) != 0 ) + return data ; + if( layer->hasMask ) { + struct Tile *mask = getMaskOrLayerTile(&layer->dim,&layer->mask,*where); + applyMask(data,mask); + } + if( layer->opacity < 255 ) { + const uint8_t *ourtable ; + int i ; + invalidateSummary(data,~(TILESUMMARY_CRISP | TILESUMMARY_ALLFULL)); + INIT_SCALETABLE_IF(1); + ourtable = scaletable[layer->opacity] ; + for( i=0; i < data->count; i++ ) + data->pixels[i] + = NEWALPHA(data->pixels[i],ourtable[ALPHA(data->pixels[i])]) ; + } + return data ; +} + diff --git a/kernel/kls_xcf/xcf2pnm/pixels.h b/kernel/kls_xcf/xcf2pnm/pixels.h new file mode 100644 index 0000000..1ee5219 --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/pixels.h @@ -0,0 +1,128 @@ +/* Pixel and tile functions for xcftools + * + * Copyright (C) 2006 Henning Makholm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef PIXELS_H +#define PIXELS_H + +#include "xcftools.h" + +/* MACROS FOR INTERNAL PIXEL ORDERING HERE */ +/*=========================================*/ +/* In principle the internal representation of pixels may change. + * - this was supposed to allow an optimization where a layer could + * be represented as a pointer into the mmapped xcf file, if + * alignment, bpp, and endianness agreed (the point was that the + * pixel representation had to agree with the endianness). + * + * However, it turns out that the current Gimp _always_ saves images + * with RLE encoding of tiles, so such an effort would be in vain. + * + * Just for modularity, nevertheless try to isolate knowledge of + * the RGBA-to-machine-word packing in this section of the + * header file. Define new macros if necessary. + * + * Given that we don't have to agree with the uncompressed + * RLE format, we choose to have the alpha in the _least_ + * significant byte on all archs - it is tested and used more + * often than the visible channels. + */ +typedef uint32_t rgba ; + +#define ALPHA_SHIFT 0 +#define RED_SHIFT 8 +#define GREEN_SHIFT 16 +#define BLUE_SHIFT 24 + +#define ALPHA(rgba) ((uint8_t)(rgba)) +#define FULLALPHA(rgba) ((uint8_t)(rgba) == 255) +#define NULLALPHA(rgba) ((uint8_t)(rgba) == 0) +#define NEWALPHA(rgb,a) (((rgba)(rgb) & 0xFFFFFF00) + (a)) + +#ifdef PRECOMPUTED_SCALETABLE +extern const uint8_t scaletable[256][256] ; +#define INIT_SCALETABLE_IF(foo) ((void)0) +#else +extern uint8_t scaletable[256][256] ; +extern int ok_scaletable ; +void mk_scaletable(void); +#define INIT_SCALETABLE_IF(foo) \ + (ok_scaletable || !(foo) || (mk_scaletable(),0) ) +#endif + +extern const rgba graytable[256] ; +extern rgba colormap[256] ; +extern unsigned colormapLength ; +void initLayer(struct xcfLayer *); +void initColormap(); + +int degrayPixel(rgba); /* returns -1 for non-gray pixels */ + +/* ******************************************************* */ + +#define TILEXn(dim,tx) \ + ((tx)==(dim).tilesx ? (dim).c.r : (dim).c.l + ((tx)*TILE_WIDTH)) +#define TILEYn(dim,ty) \ + ((ty)==(dim).tilesy ? (dim).c.b : (dim).c.t + ((ty)*TILE_HEIGHT)) + +#if __i386__ +/* This is probably the only common architecture where small constants + * are more efficient for byte operations. + */ +typedef int8_t summary_t ; +typedef short int refcount_t ; +#else +typedef int summary_t ; +typedef int refcount_t ; +#endif + +#define TILESUMMARY_UPTODATE 8 +#define TILESUMMARY_ALLNULL 4 +#define TILESUMMARY_ALLFULL 2 +#define TILESUMMARY_CRISP 1 /* everyting either null or full */ +struct Tile { + refcount_t refcount ; + summary_t summary ; /* a combination of TIMESUMMARY_FOO constatns */ + unsigned count ; + rgba pixels[TILE_WIDTH * TILE_HEIGHT]; +}; +/* Actually, the Tile structures that get allocated many not have + * room for that many pixels. We subtract the space for those we don't + * use - which is Not Legal C, but ought to be portable. + * OTOH, one can also use a static struct Tile for temporary storage. + */ + + +#define assertTileCompatibility(t1,t2) assert((t1)->count==(t2)->count) + +struct Tile *newTile(struct rect); +struct Tile *forkTile(struct Tile*); +void freeTile(struct Tile*); +#define invalidateSummary(tile,mask) \ + do{ assert((tile)->refcount==1); (tile)->summary &= mask; } while(0) +summary_t __ATTRIBUTE__((pure)) tileSummary(struct Tile *); + +void fillTile(struct Tile*,rgba); + +/* applyMask() destructively changes tile, + * applyMask() gets ownership of mask + */ +void applyMask(struct Tile *tile, struct Tile *mask); + +struct Tile *getLayerTile(struct xcfLayer *,const struct rect *); + +#endif /* FLATTEN_H */ diff --git a/kernel/kls_xcf/xcf2pnm/scaletab.c b/kernel/kls_xcf/xcf2pnm/scaletab.c new file mode 100644 index 0000000..c09867e --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/scaletab.c @@ -0,0 +1,42 @@ +/* Run-time scaletable computation for Xcftools + * + * Copyright (C) 2006 Henning Makholm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "pixels.h" +#ifndef PRECOMPUTED_SCALETABLE + +uint8_t scaletable[256][256] ; +int ok_scaletable = 0 ; + +void +mk_scaletable(void) +{ + unsigned p, q, r ; + if( ok_scaletable ) return ; + for( p = 0 ; p < 128 ; p++ ) + for( q = 0 ; q <= p ; q++ ) { + r = (p*q+127)/255 ; + scaletable[p][q] = scaletable[q][p] = r ; + scaletable[255-p][q] = scaletable[q][255-p] = q-r ; + scaletable[p][255-q] = scaletable[255-q][p] = p-r ; + scaletable[255-p][255-q] = scaletable[255-q][255-p] = (255-q)-(p-r) ; + } + ok_scaletable = 1 ; +} + +#endif + diff --git a/kernel/kls_xcf/xcf2pnm/table.c b/kernel/kls_xcf/xcf2pnm/table.c new file mode 100644 index 0000000..9e76923 --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/table.c @@ -0,0 +1,263 @@ +/* Autogenerated by mktablec.pl */ +#include "pixels.h" +#ifdef PRECOMPUTED_SCALETABLE +#error PRECOMPUTED_SCALETABLE was not defined at generation time +#endif +const rgba graytable[256] = { + (rgba)0 << RED_SHIFT | (rgba)0 << GREEN_SHIFT | (rgba)0 << BLUE_SHIFT, + (rgba)1 << RED_SHIFT | (rgba)1 << GREEN_SHIFT | (rgba)1 << BLUE_SHIFT, + (rgba)2 << RED_SHIFT | (rgba)2 << GREEN_SHIFT | (rgba)2 << BLUE_SHIFT, + (rgba)3 << RED_SHIFT | (rgba)3 << GREEN_SHIFT | (rgba)3 << BLUE_SHIFT, + (rgba)4 << RED_SHIFT | (rgba)4 << GREEN_SHIFT | (rgba)4 << BLUE_SHIFT, + (rgba)5 << RED_SHIFT | (rgba)5 << GREEN_SHIFT | (rgba)5 << BLUE_SHIFT, + (rgba)6 << RED_SHIFT | (rgba)6 << GREEN_SHIFT | (rgba)6 << BLUE_SHIFT, + (rgba)7 << RED_SHIFT | (rgba)7 << GREEN_SHIFT | (rgba)7 << BLUE_SHIFT, + (rgba)8 << RED_SHIFT | (rgba)8 << GREEN_SHIFT | (rgba)8 << BLUE_SHIFT, + (rgba)9 << RED_SHIFT | (rgba)9 << GREEN_SHIFT | (rgba)9 << BLUE_SHIFT, + (rgba)10 << RED_SHIFT | (rgba)10 << GREEN_SHIFT | (rgba)10 << BLUE_SHIFT, + (rgba)11 << RED_SHIFT | (rgba)11 << GREEN_SHIFT | (rgba)11 << BLUE_SHIFT, + (rgba)12 << RED_SHIFT | (rgba)12 << GREEN_SHIFT | (rgba)12 << BLUE_SHIFT, + (rgba)13 << RED_SHIFT | (rgba)13 << GREEN_SHIFT | (rgba)13 << BLUE_SHIFT, + (rgba)14 << RED_SHIFT | (rgba)14 << GREEN_SHIFT | (rgba)14 << BLUE_SHIFT, + (rgba)15 << RED_SHIFT | (rgba)15 << GREEN_SHIFT | (rgba)15 << BLUE_SHIFT, + (rgba)16 << RED_SHIFT | (rgba)16 << GREEN_SHIFT | (rgba)16 << BLUE_SHIFT, + (rgba)17 << RED_SHIFT | (rgba)17 << GREEN_SHIFT | (rgba)17 << BLUE_SHIFT, + (rgba)18 << RED_SHIFT | (rgba)18 << GREEN_SHIFT | (rgba)18 << BLUE_SHIFT, + (rgba)19 << RED_SHIFT | (rgba)19 << GREEN_SHIFT | (rgba)19 << BLUE_SHIFT, + (rgba)20 << RED_SHIFT | (rgba)20 << GREEN_SHIFT | (rgba)20 << BLUE_SHIFT, + (rgba)21 << RED_SHIFT | (rgba)21 << GREEN_SHIFT | (rgba)21 << BLUE_SHIFT, + (rgba)22 << RED_SHIFT | (rgba)22 << GREEN_SHIFT | (rgba)22 << BLUE_SHIFT, + (rgba)23 << RED_SHIFT | (rgba)23 << GREEN_SHIFT | (rgba)23 << BLUE_SHIFT, + (rgba)24 << RED_SHIFT | (rgba)24 << GREEN_SHIFT | (rgba)24 << BLUE_SHIFT, + (rgba)25 << RED_SHIFT | (rgba)25 << GREEN_SHIFT | (rgba)25 << BLUE_SHIFT, + (rgba)26 << RED_SHIFT | (rgba)26 << GREEN_SHIFT | (rgba)26 << BLUE_SHIFT, + (rgba)27 << RED_SHIFT | (rgba)27 << GREEN_SHIFT | (rgba)27 << BLUE_SHIFT, + (rgba)28 << RED_SHIFT | (rgba)28 << GREEN_SHIFT | (rgba)28 << BLUE_SHIFT, + (rgba)29 << RED_SHIFT | (rgba)29 << GREEN_SHIFT | (rgba)29 << BLUE_SHIFT, + (rgba)30 << RED_SHIFT | (rgba)30 << GREEN_SHIFT | (rgba)30 << BLUE_SHIFT, + (rgba)31 << RED_SHIFT | (rgba)31 << GREEN_SHIFT | (rgba)31 << BLUE_SHIFT, + (rgba)32 << RED_SHIFT | (rgba)32 << GREEN_SHIFT | (rgba)32 << BLUE_SHIFT, + (rgba)33 << RED_SHIFT | (rgba)33 << GREEN_SHIFT | (rgba)33 << BLUE_SHIFT, + (rgba)34 << RED_SHIFT | (rgba)34 << GREEN_SHIFT | (rgba)34 << BLUE_SHIFT, + (rgba)35 << RED_SHIFT | (rgba)35 << GREEN_SHIFT | (rgba)35 << BLUE_SHIFT, + (rgba)36 << RED_SHIFT | (rgba)36 << GREEN_SHIFT | (rgba)36 << BLUE_SHIFT, + (rgba)37 << RED_SHIFT | (rgba)37 << GREEN_SHIFT | (rgba)37 << BLUE_SHIFT, + (rgba)38 << RED_SHIFT | (rgba)38 << GREEN_SHIFT | (rgba)38 << BLUE_SHIFT, + (rgba)39 << RED_SHIFT | (rgba)39 << GREEN_SHIFT | (rgba)39 << BLUE_SHIFT, + (rgba)40 << RED_SHIFT | (rgba)40 << GREEN_SHIFT | (rgba)40 << BLUE_SHIFT, + (rgba)41 << RED_SHIFT | (rgba)41 << GREEN_SHIFT | (rgba)41 << BLUE_SHIFT, + (rgba)42 << RED_SHIFT | (rgba)42 << GREEN_SHIFT | (rgba)42 << BLUE_SHIFT, + (rgba)43 << RED_SHIFT | (rgba)43 << GREEN_SHIFT | (rgba)43 << BLUE_SHIFT, + (rgba)44 << RED_SHIFT | (rgba)44 << GREEN_SHIFT | (rgba)44 << BLUE_SHIFT, + (rgba)45 << RED_SHIFT | (rgba)45 << GREEN_SHIFT | (rgba)45 << BLUE_SHIFT, + (rgba)46 << RED_SHIFT | (rgba)46 << GREEN_SHIFT | (rgba)46 << BLUE_SHIFT, + (rgba)47 << RED_SHIFT | (rgba)47 << GREEN_SHIFT | (rgba)47 << BLUE_SHIFT, + (rgba)48 << RED_SHIFT | (rgba)48 << GREEN_SHIFT | (rgba)48 << BLUE_SHIFT, + (rgba)49 << RED_SHIFT | (rgba)49 << GREEN_SHIFT | (rgba)49 << BLUE_SHIFT, + (rgba)50 << RED_SHIFT | (rgba)50 << GREEN_SHIFT | (rgba)50 << BLUE_SHIFT, + (rgba)51 << RED_SHIFT | (rgba)51 << GREEN_SHIFT | (rgba)51 << BLUE_SHIFT, + (rgba)52 << RED_SHIFT | (rgba)52 << GREEN_SHIFT | (rgba)52 << BLUE_SHIFT, + (rgba)53 << RED_SHIFT | (rgba)53 << GREEN_SHIFT | (rgba)53 << BLUE_SHIFT, + (rgba)54 << RED_SHIFT | (rgba)54 << GREEN_SHIFT | (rgba)54 << BLUE_SHIFT, + (rgba)55 << RED_SHIFT | (rgba)55 << GREEN_SHIFT | (rgba)55 << BLUE_SHIFT, + (rgba)56 << RED_SHIFT | (rgba)56 << GREEN_SHIFT | (rgba)56 << BLUE_SHIFT, + (rgba)57 << RED_SHIFT | (rgba)57 << GREEN_SHIFT | (rgba)57 << BLUE_SHIFT, + (rgba)58 << RED_SHIFT | (rgba)58 << GREEN_SHIFT | (rgba)58 << BLUE_SHIFT, + (rgba)59 << RED_SHIFT | (rgba)59 << GREEN_SHIFT | (rgba)59 << BLUE_SHIFT, + (rgba)60 << RED_SHIFT | (rgba)60 << GREEN_SHIFT | (rgba)60 << BLUE_SHIFT, + (rgba)61 << RED_SHIFT | (rgba)61 << GREEN_SHIFT | (rgba)61 << BLUE_SHIFT, + (rgba)62 << RED_SHIFT | (rgba)62 << GREEN_SHIFT | (rgba)62 << BLUE_SHIFT, + (rgba)63 << RED_SHIFT | (rgba)63 << GREEN_SHIFT | (rgba)63 << BLUE_SHIFT, + (rgba)64 << RED_SHIFT | (rgba)64 << GREEN_SHIFT | (rgba)64 << BLUE_SHIFT, + (rgba)65 << RED_SHIFT | (rgba)65 << GREEN_SHIFT | (rgba)65 << BLUE_SHIFT, + (rgba)66 << RED_SHIFT | (rgba)66 << GREEN_SHIFT | (rgba)66 << BLUE_SHIFT, + (rgba)67 << RED_SHIFT | (rgba)67 << GREEN_SHIFT | (rgba)67 << BLUE_SHIFT, + (rgba)68 << RED_SHIFT | (rgba)68 << GREEN_SHIFT | (rgba)68 << BLUE_SHIFT, + (rgba)69 << RED_SHIFT | (rgba)69 << GREEN_SHIFT | (rgba)69 << BLUE_SHIFT, + (rgba)70 << RED_SHIFT | (rgba)70 << GREEN_SHIFT | (rgba)70 << BLUE_SHIFT, + (rgba)71 << RED_SHIFT | (rgba)71 << GREEN_SHIFT | (rgba)71 << BLUE_SHIFT, + (rgba)72 << RED_SHIFT | (rgba)72 << GREEN_SHIFT | (rgba)72 << BLUE_SHIFT, + (rgba)73 << RED_SHIFT | (rgba)73 << GREEN_SHIFT | (rgba)73 << BLUE_SHIFT, + (rgba)74 << RED_SHIFT | (rgba)74 << GREEN_SHIFT | (rgba)74 << BLUE_SHIFT, + (rgba)75 << RED_SHIFT | (rgba)75 << GREEN_SHIFT | (rgba)75 << BLUE_SHIFT, + (rgba)76 << RED_SHIFT | (rgba)76 << GREEN_SHIFT | (rgba)76 << BLUE_SHIFT, + (rgba)77 << RED_SHIFT | (rgba)77 << GREEN_SHIFT | (rgba)77 << BLUE_SHIFT, + (rgba)78 << RED_SHIFT | (rgba)78 << GREEN_SHIFT | (rgba)78 << BLUE_SHIFT, + (rgba)79 << RED_SHIFT | (rgba)79 << GREEN_SHIFT | (rgba)79 << BLUE_SHIFT, + (rgba)80 << RED_SHIFT | (rgba)80 << GREEN_SHIFT | (rgba)80 << BLUE_SHIFT, + (rgba)81 << RED_SHIFT | (rgba)81 << GREEN_SHIFT | (rgba)81 << BLUE_SHIFT, + (rgba)82 << RED_SHIFT | (rgba)82 << GREEN_SHIFT | (rgba)82 << BLUE_SHIFT, + (rgba)83 << RED_SHIFT | (rgba)83 << GREEN_SHIFT | (rgba)83 << BLUE_SHIFT, + (rgba)84 << RED_SHIFT | (rgba)84 << GREEN_SHIFT | (rgba)84 << BLUE_SHIFT, + (rgba)85 << RED_SHIFT | (rgba)85 << GREEN_SHIFT | (rgba)85 << BLUE_SHIFT, + (rgba)86 << RED_SHIFT | (rgba)86 << GREEN_SHIFT | (rgba)86 << BLUE_SHIFT, + (rgba)87 << RED_SHIFT | (rgba)87 << GREEN_SHIFT | (rgba)87 << BLUE_SHIFT, + (rgba)88 << RED_SHIFT | (rgba)88 << GREEN_SHIFT | (rgba)88 << BLUE_SHIFT, + (rgba)89 << RED_SHIFT | (rgba)89 << GREEN_SHIFT | (rgba)89 << BLUE_SHIFT, + (rgba)90 << RED_SHIFT | (rgba)90 << GREEN_SHIFT | (rgba)90 << BLUE_SHIFT, + (rgba)91 << RED_SHIFT | (rgba)91 << GREEN_SHIFT | (rgba)91 << BLUE_SHIFT, + (rgba)92 << RED_SHIFT | (rgba)92 << GREEN_SHIFT | (rgba)92 << BLUE_SHIFT, + (rgba)93 << RED_SHIFT | (rgba)93 << GREEN_SHIFT | (rgba)93 << BLUE_SHIFT, + (rgba)94 << RED_SHIFT | (rgba)94 << GREEN_SHIFT | (rgba)94 << BLUE_SHIFT, + (rgba)95 << RED_SHIFT | (rgba)95 << GREEN_SHIFT | (rgba)95 << BLUE_SHIFT, + (rgba)96 << RED_SHIFT | (rgba)96 << GREEN_SHIFT | (rgba)96 << BLUE_SHIFT, + (rgba)97 << RED_SHIFT | (rgba)97 << GREEN_SHIFT | (rgba)97 << BLUE_SHIFT, + (rgba)98 << RED_SHIFT | (rgba)98 << GREEN_SHIFT | (rgba)98 << BLUE_SHIFT, + (rgba)99 << RED_SHIFT | (rgba)99 << GREEN_SHIFT | (rgba)99 << BLUE_SHIFT, + (rgba)100 << RED_SHIFT | (rgba)100 << GREEN_SHIFT | (rgba)100 << BLUE_SHIFT, + (rgba)101 << RED_SHIFT | (rgba)101 << GREEN_SHIFT | (rgba)101 << BLUE_SHIFT, + (rgba)102 << RED_SHIFT | (rgba)102 << GREEN_SHIFT | (rgba)102 << BLUE_SHIFT, + (rgba)103 << RED_SHIFT | (rgba)103 << GREEN_SHIFT | (rgba)103 << BLUE_SHIFT, + (rgba)104 << RED_SHIFT | (rgba)104 << GREEN_SHIFT | (rgba)104 << BLUE_SHIFT, + (rgba)105 << RED_SHIFT | (rgba)105 << GREEN_SHIFT | (rgba)105 << BLUE_SHIFT, + (rgba)106 << RED_SHIFT | (rgba)106 << GREEN_SHIFT | (rgba)106 << BLUE_SHIFT, + (rgba)107 << RED_SHIFT | (rgba)107 << GREEN_SHIFT | (rgba)107 << BLUE_SHIFT, + (rgba)108 << RED_SHIFT | (rgba)108 << GREEN_SHIFT | (rgba)108 << BLUE_SHIFT, + (rgba)109 << RED_SHIFT | (rgba)109 << GREEN_SHIFT | (rgba)109 << BLUE_SHIFT, + (rgba)110 << RED_SHIFT | (rgba)110 << GREEN_SHIFT | (rgba)110 << BLUE_SHIFT, + (rgba)111 << RED_SHIFT | (rgba)111 << GREEN_SHIFT | (rgba)111 << BLUE_SHIFT, + (rgba)112 << RED_SHIFT | (rgba)112 << GREEN_SHIFT | (rgba)112 << BLUE_SHIFT, + (rgba)113 << RED_SHIFT | (rgba)113 << GREEN_SHIFT | (rgba)113 << BLUE_SHIFT, + (rgba)114 << RED_SHIFT | (rgba)114 << GREEN_SHIFT | (rgba)114 << BLUE_SHIFT, + (rgba)115 << RED_SHIFT | (rgba)115 << GREEN_SHIFT | (rgba)115 << BLUE_SHIFT, + (rgba)116 << RED_SHIFT | (rgba)116 << GREEN_SHIFT | (rgba)116 << BLUE_SHIFT, + (rgba)117 << RED_SHIFT | (rgba)117 << GREEN_SHIFT | (rgba)117 << BLUE_SHIFT, + (rgba)118 << RED_SHIFT | (rgba)118 << GREEN_SHIFT | (rgba)118 << BLUE_SHIFT, + (rgba)119 << RED_SHIFT | (rgba)119 << GREEN_SHIFT | (rgba)119 << BLUE_SHIFT, + (rgba)120 << RED_SHIFT | (rgba)120 << GREEN_SHIFT | (rgba)120 << BLUE_SHIFT, + (rgba)121 << RED_SHIFT | (rgba)121 << GREEN_SHIFT | (rgba)121 << BLUE_SHIFT, + (rgba)122 << RED_SHIFT | (rgba)122 << GREEN_SHIFT | (rgba)122 << BLUE_SHIFT, + (rgba)123 << RED_SHIFT | (rgba)123 << GREEN_SHIFT | (rgba)123 << BLUE_SHIFT, + (rgba)124 << RED_SHIFT | (rgba)124 << GREEN_SHIFT | (rgba)124 << BLUE_SHIFT, + (rgba)125 << RED_SHIFT | (rgba)125 << GREEN_SHIFT | (rgba)125 << BLUE_SHIFT, + (rgba)126 << RED_SHIFT | (rgba)126 << GREEN_SHIFT | (rgba)126 << BLUE_SHIFT, + (rgba)127 << RED_SHIFT | (rgba)127 << GREEN_SHIFT | (rgba)127 << BLUE_SHIFT, + (rgba)128 << RED_SHIFT | (rgba)128 << GREEN_SHIFT | (rgba)128 << BLUE_SHIFT, + (rgba)129 << RED_SHIFT | (rgba)129 << GREEN_SHIFT | (rgba)129 << BLUE_SHIFT, + (rgba)130 << RED_SHIFT | (rgba)130 << GREEN_SHIFT | (rgba)130 << BLUE_SHIFT, + (rgba)131 << RED_SHIFT | (rgba)131 << GREEN_SHIFT | (rgba)131 << BLUE_SHIFT, + (rgba)132 << RED_SHIFT | (rgba)132 << GREEN_SHIFT | (rgba)132 << BLUE_SHIFT, + (rgba)133 << RED_SHIFT | (rgba)133 << GREEN_SHIFT | (rgba)133 << BLUE_SHIFT, + (rgba)134 << RED_SHIFT | (rgba)134 << GREEN_SHIFT | (rgba)134 << BLUE_SHIFT, + (rgba)135 << RED_SHIFT | (rgba)135 << GREEN_SHIFT | (rgba)135 << BLUE_SHIFT, + (rgba)136 << RED_SHIFT | (rgba)136 << GREEN_SHIFT | (rgba)136 << BLUE_SHIFT, + (rgba)137 << RED_SHIFT | (rgba)137 << GREEN_SHIFT | (rgba)137 << BLUE_SHIFT, + (rgba)138 << RED_SHIFT | (rgba)138 << GREEN_SHIFT | (rgba)138 << BLUE_SHIFT, + (rgba)139 << RED_SHIFT | (rgba)139 << GREEN_SHIFT | (rgba)139 << BLUE_SHIFT, + (rgba)140 << RED_SHIFT | (rgba)140 << GREEN_SHIFT | (rgba)140 << BLUE_SHIFT, + (rgba)141 << RED_SHIFT | (rgba)141 << GREEN_SHIFT | (rgba)141 << BLUE_SHIFT, + (rgba)142 << RED_SHIFT | (rgba)142 << GREEN_SHIFT | (rgba)142 << BLUE_SHIFT, + (rgba)143 << RED_SHIFT | (rgba)143 << GREEN_SHIFT | (rgba)143 << BLUE_SHIFT, + (rgba)144 << RED_SHIFT | (rgba)144 << GREEN_SHIFT | (rgba)144 << BLUE_SHIFT, + (rgba)145 << RED_SHIFT | (rgba)145 << GREEN_SHIFT | (rgba)145 << BLUE_SHIFT, + (rgba)146 << RED_SHIFT | (rgba)146 << GREEN_SHIFT | (rgba)146 << BLUE_SHIFT, + (rgba)147 << RED_SHIFT | (rgba)147 << GREEN_SHIFT | (rgba)147 << BLUE_SHIFT, + (rgba)148 << RED_SHIFT | (rgba)148 << GREEN_SHIFT | (rgba)148 << BLUE_SHIFT, + (rgba)149 << RED_SHIFT | (rgba)149 << GREEN_SHIFT | (rgba)149 << BLUE_SHIFT, + (rgba)150 << RED_SHIFT | (rgba)150 << GREEN_SHIFT | (rgba)150 << BLUE_SHIFT, + (rgba)151 << RED_SHIFT | (rgba)151 << GREEN_SHIFT | (rgba)151 << BLUE_SHIFT, + (rgba)152 << RED_SHIFT | (rgba)152 << GREEN_SHIFT | (rgba)152 << BLUE_SHIFT, + (rgba)153 << RED_SHIFT | (rgba)153 << GREEN_SHIFT | (rgba)153 << BLUE_SHIFT, + (rgba)154 << RED_SHIFT | (rgba)154 << GREEN_SHIFT | (rgba)154 << BLUE_SHIFT, + (rgba)155 << RED_SHIFT | (rgba)155 << GREEN_SHIFT | (rgba)155 << BLUE_SHIFT, + (rgba)156 << RED_SHIFT | (rgba)156 << GREEN_SHIFT | (rgba)156 << BLUE_SHIFT, + (rgba)157 << RED_SHIFT | (rgba)157 << GREEN_SHIFT | (rgba)157 << BLUE_SHIFT, + (rgba)158 << RED_SHIFT | (rgba)158 << GREEN_SHIFT | (rgba)158 << BLUE_SHIFT, + (rgba)159 << RED_SHIFT | (rgba)159 << GREEN_SHIFT | (rgba)159 << BLUE_SHIFT, + (rgba)160 << RED_SHIFT | (rgba)160 << GREEN_SHIFT | (rgba)160 << BLUE_SHIFT, + (rgba)161 << RED_SHIFT | (rgba)161 << GREEN_SHIFT | (rgba)161 << BLUE_SHIFT, + (rgba)162 << RED_SHIFT | (rgba)162 << GREEN_SHIFT | (rgba)162 << BLUE_SHIFT, + (rgba)163 << RED_SHIFT | (rgba)163 << GREEN_SHIFT | (rgba)163 << BLUE_SHIFT, + (rgba)164 << RED_SHIFT | (rgba)164 << GREEN_SHIFT | (rgba)164 << BLUE_SHIFT, + (rgba)165 << RED_SHIFT | (rgba)165 << GREEN_SHIFT | (rgba)165 << BLUE_SHIFT, + (rgba)166 << RED_SHIFT | (rgba)166 << GREEN_SHIFT | (rgba)166 << BLUE_SHIFT, + (rgba)167 << RED_SHIFT | (rgba)167 << GREEN_SHIFT | (rgba)167 << BLUE_SHIFT, + (rgba)168 << RED_SHIFT | (rgba)168 << GREEN_SHIFT | (rgba)168 << BLUE_SHIFT, + (rgba)169 << RED_SHIFT | (rgba)169 << GREEN_SHIFT | (rgba)169 << BLUE_SHIFT, + (rgba)170 << RED_SHIFT | (rgba)170 << GREEN_SHIFT | (rgba)170 << BLUE_SHIFT, + (rgba)171 << RED_SHIFT | (rgba)171 << GREEN_SHIFT | (rgba)171 << BLUE_SHIFT, + (rgba)172 << RED_SHIFT | (rgba)172 << GREEN_SHIFT | (rgba)172 << BLUE_SHIFT, + (rgba)173 << RED_SHIFT | (rgba)173 << GREEN_SHIFT | (rgba)173 << BLUE_SHIFT, + (rgba)174 << RED_SHIFT | (rgba)174 << GREEN_SHIFT | (rgba)174 << BLUE_SHIFT, + (rgba)175 << RED_SHIFT | (rgba)175 << GREEN_SHIFT | (rgba)175 << BLUE_SHIFT, + (rgba)176 << RED_SHIFT | (rgba)176 << GREEN_SHIFT | (rgba)176 << BLUE_SHIFT, + (rgba)177 << RED_SHIFT | (rgba)177 << GREEN_SHIFT | (rgba)177 << BLUE_SHIFT, + (rgba)178 << RED_SHIFT | (rgba)178 << GREEN_SHIFT | (rgba)178 << BLUE_SHIFT, + (rgba)179 << RED_SHIFT | (rgba)179 << GREEN_SHIFT | (rgba)179 << BLUE_SHIFT, + (rgba)180 << RED_SHIFT | (rgba)180 << GREEN_SHIFT | (rgba)180 << BLUE_SHIFT, + (rgba)181 << RED_SHIFT | (rgba)181 << GREEN_SHIFT | (rgba)181 << BLUE_SHIFT, + (rgba)182 << RED_SHIFT | (rgba)182 << GREEN_SHIFT | (rgba)182 << BLUE_SHIFT, + (rgba)183 << RED_SHIFT | (rgba)183 << GREEN_SHIFT | (rgba)183 << BLUE_SHIFT, + (rgba)184 << RED_SHIFT | (rgba)184 << GREEN_SHIFT | (rgba)184 << BLUE_SHIFT, + (rgba)185 << RED_SHIFT | (rgba)185 << GREEN_SHIFT | (rgba)185 << BLUE_SHIFT, + (rgba)186 << RED_SHIFT | (rgba)186 << GREEN_SHIFT | (rgba)186 << BLUE_SHIFT, + (rgba)187 << RED_SHIFT | (rgba)187 << GREEN_SHIFT | (rgba)187 << BLUE_SHIFT, + (rgba)188 << RED_SHIFT | (rgba)188 << GREEN_SHIFT | (rgba)188 << BLUE_SHIFT, + (rgba)189 << RED_SHIFT | (rgba)189 << GREEN_SHIFT | (rgba)189 << BLUE_SHIFT, + (rgba)190 << RED_SHIFT | (rgba)190 << GREEN_SHIFT | (rgba)190 << BLUE_SHIFT, + (rgba)191 << RED_SHIFT | (rgba)191 << GREEN_SHIFT | (rgba)191 << BLUE_SHIFT, + (rgba)192 << RED_SHIFT | (rgba)192 << GREEN_SHIFT | (rgba)192 << BLUE_SHIFT, + (rgba)193 << RED_SHIFT | (rgba)193 << GREEN_SHIFT | (rgba)193 << BLUE_SHIFT, + (rgba)194 << RED_SHIFT | (rgba)194 << GREEN_SHIFT | (rgba)194 << BLUE_SHIFT, + (rgba)195 << RED_SHIFT | (rgba)195 << GREEN_SHIFT | (rgba)195 << BLUE_SHIFT, + (rgba)196 << RED_SHIFT | (rgba)196 << GREEN_SHIFT | (rgba)196 << BLUE_SHIFT, + (rgba)197 << RED_SHIFT | (rgba)197 << GREEN_SHIFT | (rgba)197 << BLUE_SHIFT, + (rgba)198 << RED_SHIFT | (rgba)198 << GREEN_SHIFT | (rgba)198 << BLUE_SHIFT, + (rgba)199 << RED_SHIFT | (rgba)199 << GREEN_SHIFT | (rgba)199 << BLUE_SHIFT, + (rgba)200 << RED_SHIFT | (rgba)200 << GREEN_SHIFT | (rgba)200 << BLUE_SHIFT, + (rgba)201 << RED_SHIFT | (rgba)201 << GREEN_SHIFT | (rgba)201 << BLUE_SHIFT, + (rgba)202 << RED_SHIFT | (rgba)202 << GREEN_SHIFT | (rgba)202 << BLUE_SHIFT, + (rgba)203 << RED_SHIFT | (rgba)203 << GREEN_SHIFT | (rgba)203 << BLUE_SHIFT, + (rgba)204 << RED_SHIFT | (rgba)204 << GREEN_SHIFT | (rgba)204 << BLUE_SHIFT, + (rgba)205 << RED_SHIFT | (rgba)205 << GREEN_SHIFT | (rgba)205 << BLUE_SHIFT, + (rgba)206 << RED_SHIFT | (rgba)206 << GREEN_SHIFT | (rgba)206 << BLUE_SHIFT, + (rgba)207 << RED_SHIFT | (rgba)207 << GREEN_SHIFT | (rgba)207 << BLUE_SHIFT, + (rgba)208 << RED_SHIFT | (rgba)208 << GREEN_SHIFT | (rgba)208 << BLUE_SHIFT, + (rgba)209 << RED_SHIFT | (rgba)209 << GREEN_SHIFT | (rgba)209 << BLUE_SHIFT, + (rgba)210 << RED_SHIFT | (rgba)210 << GREEN_SHIFT | (rgba)210 << BLUE_SHIFT, + (rgba)211 << RED_SHIFT | (rgba)211 << GREEN_SHIFT | (rgba)211 << BLUE_SHIFT, + (rgba)212 << RED_SHIFT | (rgba)212 << GREEN_SHIFT | (rgba)212 << BLUE_SHIFT, + (rgba)213 << RED_SHIFT | (rgba)213 << GREEN_SHIFT | (rgba)213 << BLUE_SHIFT, + (rgba)214 << RED_SHIFT | (rgba)214 << GREEN_SHIFT | (rgba)214 << BLUE_SHIFT, + (rgba)215 << RED_SHIFT | (rgba)215 << GREEN_SHIFT | (rgba)215 << BLUE_SHIFT, + (rgba)216 << RED_SHIFT | (rgba)216 << GREEN_SHIFT | (rgba)216 << BLUE_SHIFT, + (rgba)217 << RED_SHIFT | (rgba)217 << GREEN_SHIFT | (rgba)217 << BLUE_SHIFT, + (rgba)218 << RED_SHIFT | (rgba)218 << GREEN_SHIFT | (rgba)218 << BLUE_SHIFT, + (rgba)219 << RED_SHIFT | (rgba)219 << GREEN_SHIFT | (rgba)219 << BLUE_SHIFT, + (rgba)220 << RED_SHIFT | (rgba)220 << GREEN_SHIFT | (rgba)220 << BLUE_SHIFT, + (rgba)221 << RED_SHIFT | (rgba)221 << GREEN_SHIFT | (rgba)221 << BLUE_SHIFT, + (rgba)222 << RED_SHIFT | (rgba)222 << GREEN_SHIFT | (rgba)222 << BLUE_SHIFT, + (rgba)223 << RED_SHIFT | (rgba)223 << GREEN_SHIFT | (rgba)223 << BLUE_SHIFT, + (rgba)224 << RED_SHIFT | (rgba)224 << GREEN_SHIFT | (rgba)224 << BLUE_SHIFT, + (rgba)225 << RED_SHIFT | (rgba)225 << GREEN_SHIFT | (rgba)225 << BLUE_SHIFT, + (rgba)226 << RED_SHIFT | (rgba)226 << GREEN_SHIFT | (rgba)226 << BLUE_SHIFT, + (rgba)227 << RED_SHIFT | (rgba)227 << GREEN_SHIFT | (rgba)227 << BLUE_SHIFT, + (rgba)228 << RED_SHIFT | (rgba)228 << GREEN_SHIFT | (rgba)228 << BLUE_SHIFT, + (rgba)229 << RED_SHIFT | (rgba)229 << GREEN_SHIFT | (rgba)229 << BLUE_SHIFT, + (rgba)230 << RED_SHIFT | (rgba)230 << GREEN_SHIFT | (rgba)230 << BLUE_SHIFT, + (rgba)231 << RED_SHIFT | (rgba)231 << GREEN_SHIFT | (rgba)231 << BLUE_SHIFT, + (rgba)232 << RED_SHIFT | (rgba)232 << GREEN_SHIFT | (rgba)232 << BLUE_SHIFT, + (rgba)233 << RED_SHIFT | (rgba)233 << GREEN_SHIFT | (rgba)233 << BLUE_SHIFT, + (rgba)234 << RED_SHIFT | (rgba)234 << GREEN_SHIFT | (rgba)234 << BLUE_SHIFT, + (rgba)235 << RED_SHIFT | (rgba)235 << GREEN_SHIFT | (rgba)235 << BLUE_SHIFT, + (rgba)236 << RED_SHIFT | (rgba)236 << GREEN_SHIFT | (rgba)236 << BLUE_SHIFT, + (rgba)237 << RED_SHIFT | (rgba)237 << GREEN_SHIFT | (rgba)237 << BLUE_SHIFT, + (rgba)238 << RED_SHIFT | (rgba)238 << GREEN_SHIFT | (rgba)238 << BLUE_SHIFT, + (rgba)239 << RED_SHIFT | (rgba)239 << GREEN_SHIFT | (rgba)239 << BLUE_SHIFT, + (rgba)240 << RED_SHIFT | (rgba)240 << GREEN_SHIFT | (rgba)240 << BLUE_SHIFT, + (rgba)241 << RED_SHIFT | (rgba)241 << GREEN_SHIFT | (rgba)241 << BLUE_SHIFT, + (rgba)242 << RED_SHIFT | (rgba)242 << GREEN_SHIFT | (rgba)242 << BLUE_SHIFT, + (rgba)243 << RED_SHIFT | (rgba)243 << GREEN_SHIFT | (rgba)243 << BLUE_SHIFT, + (rgba)244 << RED_SHIFT | (rgba)244 << GREEN_SHIFT | (rgba)244 << BLUE_SHIFT, + (rgba)245 << RED_SHIFT | (rgba)245 << GREEN_SHIFT | (rgba)245 << BLUE_SHIFT, + (rgba)246 << RED_SHIFT | (rgba)246 << GREEN_SHIFT | (rgba)246 << BLUE_SHIFT, + (rgba)247 << RED_SHIFT | (rgba)247 << GREEN_SHIFT | (rgba)247 << BLUE_SHIFT, + (rgba)248 << RED_SHIFT | (rgba)248 << GREEN_SHIFT | (rgba)248 << BLUE_SHIFT, + (rgba)249 << RED_SHIFT | (rgba)249 << GREEN_SHIFT | (rgba)249 << BLUE_SHIFT, + (rgba)250 << RED_SHIFT | (rgba)250 << GREEN_SHIFT | (rgba)250 << BLUE_SHIFT, + (rgba)251 << RED_SHIFT | (rgba)251 << GREEN_SHIFT | (rgba)251 << BLUE_SHIFT, + (rgba)252 << RED_SHIFT | (rgba)252 << GREEN_SHIFT | (rgba)252 << BLUE_SHIFT, + (rgba)253 << RED_SHIFT | (rgba)253 << GREEN_SHIFT | (rgba)253 << BLUE_SHIFT, + (rgba)254 << RED_SHIFT | (rgba)254 << GREEN_SHIFT | (rgba)254 << BLUE_SHIFT, + (rgba)255 << RED_SHIFT | (rgba)255 << GREEN_SHIFT | (rgba)255 << BLUE_SHIFT, +}; diff --git a/kernel/kls_xcf/xcf2pnm/utils.c b/kernel/kls_xcf/xcf2pnm/utils.c new file mode 100644 index 0000000..bde0782 --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/utils.c @@ -0,0 +1,164 @@ +/* Generic support functions for Xcftools + * + * Copyright (C) 2006 Henning Makholm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "xcftools.h" +#include +#include +#include +#include + +const char *progname = "$0" ; +int verboseFlag = 0 ; + + +static void __ATTRIBUTE__((noreturn)) +vFatalGeneric(int status,const char *format,va_list args) +{ + if( format ) { + if( *format == '!' ) { + vfprintf(stderr,format+1,args); + fprintf(stderr,": %s\n",strerror(errno)); + } else { + vfprintf(stderr,format,args); + fputc('\n',stderr); + } + } + exit(status); +} + +void +FatalGeneric(int status,const char* format,...) +{ + va_list v; va_start(v,format); + if( format ) fprintf(stderr,"%s: ",progname); + vFatalGeneric(status,format,v); +} + +void +FatalUnexpected(const char* format,...) +{ + va_list v; va_start(v,format); + fprintf(stderr,"%s: ",progname); + vFatalGeneric(127,format,v) ; +} + +void +FatalBadXCF(const char* format,...) +{ + va_list v; va_start(v,format); + fprintf(stderr,"%s: %s:\n ",progname,_("Corrupted or malformed XCF file")); + vFatalGeneric(125,format,v) ; +} + +void +xcfCheckspace(uint32_t addr,int spaceafter,const char *format,...) +{ + if( xcf_length < spaceafter || addr > xcf_length - spaceafter ) { + va_list v; va_start(v,format); + fprintf(stderr,"%s: %s\n ",progname,_("Corrupted or truncated XCF file")); + fprintf(stderr,"(0x%" PRIXPTR " bytes): ",(uintptr_t)xcf_length); + vFatalGeneric(125,format,v) ; + } +} + + +void +FatalUnsupportedXCF(const char* format,...) +{ + va_list v; va_start(v,format); + fprintf(stderr,"%s: %s\n ",progname, + _("The image contains features not understood by this program:")); + vFatalGeneric(123,format,v) ; +} + +void +gpl_blurb(void) +{ + fprintf(stderr,PACKAGE_STRING "\n"); + fprintf(stderr, + _("This program is free software; you can modify and distribute it\n" + "under the terms of the GNU General Public License, version 2.\n" + "There is no warranty for %s.\n\n"), + PACKAGE_NAME); + fprintf(stderr, + _("Type \"%s -h\" to get an option summary.\n"),progname); + exit(1) ; +} + +/* ******************************************************* */ + +void * +xcfmalloc(size_t size) +{ + void *ptr = malloc(size); + if( !ptr ) + FatalUnexpected(_("Out of memory")); + return ptr ; +} + +void +xcffree(void *block) +{ + if( xcf_file && + (uint8_t*)block >= xcf_file && + (uint8_t*)block < xcf_file + xcf_length ) + ; + else + free(block); +} + +/* ******************************************************* */ + +FILE * +openout(const char *name) +{ + FILE *newfile ; + if( strcmp(name,"-") == 0 ) + return stdout ; + newfile = fopen(name,"wb") ; + if( newfile == NULL ) + FatalUnexpected(_("!Cannot create file %s"),name); + return newfile ; +} + +void +closeout(FILE *f,const char *name) +{ + if( f == NULL ) + return ; + if( fflush(f) == 0 ) { + errno = 0 ; + if( !ferror(f) ) { + if( fclose(f) == 0 ) + return ; + } else if( errno == 0 ) { + /* Attempt to coax a valid errno out of the standard library, + * following an idea by Bruno Haible + * http://lists.gnu.org/archive/html/bug-gnulib/2003-09/msg00157.html + */ + if( fputc('\0', f) != EOF && + fflush(f) == 0 ) + errno = EIO ; /* Argh, everything succeds. Just call it an I/O error */ + } + } + FatalUnexpected(_("!Error writing file %s"),name); +} + + + + diff --git a/kernel/kls_xcf/xcf2pnm/xcf-general.c b/kernel/kls_xcf/xcf2pnm/xcf-general.c new file mode 100644 index 0000000..9231134 --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/xcf-general.c @@ -0,0 +1,287 @@ +/* Generic functions for reading XCF files + * + * Copyright (C) 2006 Henning Makholm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "xcftools.h" +#include +#include +#ifdef HAVE_ICONV +# include +#elif !defined(ICONV_CONST) +# define ICONV_CONST const +#endif + +uint8_t *xcf_file = 0 ; +size_t xcf_length ; +int use_utf8 = 0 ; + +uint32_t +xcfOffset(uint32_t addr,int spaceafter) +{ + uint32_t apparent ; + xcfCheckspace(addr,4,"(xcfOffset)"); + apparent = xcfL(addr); + xcfCheckspace(apparent,spaceafter, + "Too large offset (%" PRIX32 ") at position %" PRIX32, + apparent,addr); + return apparent ; +} + +int +xcfNextprop(uint32_t *master,uint32_t *body) +{ + uint32_t ptr, length, total, minlength ; + PropType type ; + ptr = *master ; + xcfCheckspace(ptr,8,"(property header)"); + type = xcfL(ptr); + length = xcfL(ptr+4); + *body = ptr+8 ; + + switch(type) { + case PROP_COLORMAP: + { + uint32_t ncolors ; + xcfCheckspace(ptr+8,4,"(colormap length)"); + ncolors = xcfL(ptr+8) ; + if( ncolors > 256 ) + FatalBadXCF("Colormap has %" PRIu32 " entries",ncolors); + /* Surprise! Some older verion of the Gimp computed the wrong length + * word, and the _reader_ always just reads three bytes per color + * and ignores the length tag! Duplicate this so we too can read + * the buggy XCF files. + */ + length = minlength = 4+3*ncolors; + break; + } + case PROP_COMPRESSION: minlength = 1; break; + case PROP_OPACITY: minlength = 4; break; + case PROP_APPLY_MASK: minlength = 4; break; + case PROP_OFFSETS: minlength = 8; break; + case PROP_MODE: minlength = 4; break; + default: minlength = 0; break; + } + if( length < minlength ) + FatalBadXCF("Short %s property at %" PRIX32 " (%" PRIu32 "<%" PRIu32 ")", + showPropType(type),ptr,length,minlength); + *master = ptr+8+length ; + total = 8 + length + (type != PROP_END ? 8 : 0) ; + if( total < length ) /* Check overwrap */ + FatalBadXCF("Overlong property at %" PRIX32, ptr); + xcfCheckspace(ptr,total,"Overlong property at %" PRIX32,ptr) ; + return type ; +} + +const char* +xcfString(uint32_t ptr,uint32_t *after) +{ + uint32_t length ; + unsigned i ; + ICONV_CONST char *utf8master ; + + xcfCheckspace(ptr,4,"(string length)"); + length = xcfL(ptr) ; + ptr += 4 ; + xcfCheckspace(ptr,length,"(string)"); + utf8master = (ICONV_CONST char*)(xcf_file+ptr) ; + if( after ) *after = ptr + length ; + if( length == 0 || utf8master[length-1] != 0 ) + FatalBadXCF("String at %" PRIX32 " not zero-terminated",ptr-4); + length-- ; + + if( use_utf8 ) return utf8master ; + + /* We assume that the local character set includes ASCII... + * Check if conversion is needed at all + */ + for( i=0 ; ; i++ ) { + if( i == length ) + return utf8master ; /* Only ASCII after all */ + if( utf8master[i] == 0 ) + FatalBadXCF("String at %" PRIX32 " has embedded zeroes",ptr-4); + if( (int8_t) utf8master[i] < 0 ) + break ; + } +#ifdef HAVE_ICONV + { + size_t targetsize = length+1 ; + int sloppy_translation = 0 ; + iconv_t cd = iconv_open("//TRANSLIT","UTF-8"); + if( cd == (iconv_t) -1 ) { + cd = iconv_open("","UTF-8"); + sloppy_translation = 1 ; + } + if( cd == (iconv_t) -1 ) + iconv_close(cd) ; /* Give up; perhaps iconv doesn't know UTF-8 */ + else + while(1) { + char *buffer = xcfmalloc(targetsize) ; + ICONV_CONST char *inbuf = utf8master ; + char *outbuf = buffer ; + size_t incount = length ; + size_t outcount = targetsize ; + while(1) { /* Loop for systems without //ICONV support */ + size_t result = iconv(cd,&inbuf,&incount,&outbuf,&outcount) ; + if( result == (size_t)-1 && errno == EILSEQ && + sloppy_translation && outcount > 0 ) { + *outbuf++ = '?' ; + outcount-- ; + while( (int8_t)*inbuf < 0 ) inbuf++, incount-- ; + continue ; + } + if( result != (size_t)-1 ) { + if( outcount == 0 ) + errno = E2BIG ; + else { + *outbuf = 0 ; + iconv_close(cd) ; + return buffer ; + } + } + break ; + } + if( errno == EILSEQ || errno == EINVAL ) + FatalBadXCF("Bad UTF-8 encoding '%s' at %" PRIXPTR, + inbuf,(uintptr_t)((inbuf-utf8master)+ptr)); + if( errno == E2BIG ) { + targetsize += 1+incount ; + xcffree(buffer) ; + continue ; + } + FatalUnexpected("!iconv on layer name at %"PRIX32,ptr); + } + } +#endif + { + static int warned = 0 ; + if( !warned ) { + fprintf(stderr,_("Warning: one or more layer names could not be\n" + " translated to the local character set.\n")); + warned = 1 ; + } + } + return utf8master ; +} + +/* ****************************************************************** */ + +void +computeDimensions(struct tileDimensions *d) +{ + d->c.r = d->c.l + d->width ; + d->c.b = d->c.t + d->height ; + d->tilesx = (d->width+TILE_WIDTH-1)/TILE_WIDTH ; + d->tilesy = (d->height+TILE_HEIGHT-1)/TILE_HEIGHT ; + d->ntiles = d->tilesx * d->tilesy ; +} + +struct xcfImage XCF ; + +void +getBasicXcfInfo(void) +{ + uint32_t ptr, data, layerfile ; + PropType type ; + int i ; + + xcfCheckspace(0,14+7*4,"(very short)"); + if( strcmp((char*)xcf_file,"gimp xcf file") == 0 ) + XCF.version = 0 ; + else if( xcf_file[13] == 0 && + sscanf((char*)xcf_file,"gimp xcf v%d",&XCF.version) == 1 ) + ; + else + FatalBadXCF(_("Not an XCF file at all (magic not recognized)")); + + if( XCF.version < 0 || XCF.version > 2 ) { + fprintf(stderr, + _("Warning: XCF version %d not supported (trying anyway...)\n"), + XCF.version); + } + + XCF.compression = COMPRESS_NONE ; + XCF.colormapptr = 0 ; + + ptr = 14 ; + XCF.width = xcfL(ptr); ptr += 4 ; + XCF.height = xcfL(ptr); ptr += 4 ; + XCF.type = xcfL(ptr); ptr += 4 ; + while( (type = xcfNextprop(&ptr,&data)) != PROP_END ) { + switch(type) { + case PROP_COLORMAP: + XCF.colormapptr = data ; + break ; + case PROP_COMPRESSION: + XCF.compression = xcf_file[data] ; + break ; + default: + /* Ignore unknown properties */ + break ; + } + } + + layerfile = ptr ; + for( XCF.numLayers = 0 ; xcfOffset(ptr,8*4) ; XCF.numLayers++, ptr+=4 ) + ; + XCF.layers = xcfmalloc(XCF.numLayers * sizeof(struct xcfLayer)) ; + for( i = 0 ; i < XCF.numLayers ; i++ ) { + struct xcfLayer *L = XCF.layers + i ; + ptr = xcfL(layerfile+4*(XCF.numLayers-1-i)) ; + L->mode = GIMP_NORMAL_MODE ; + L->opacity = 255 ; + L->isVisible = 1 ; + L->hasMask = 0 ; + L->dim.width = xcfL(ptr); ptr+=4 ; + L->dim.height = xcfL(ptr); ptr+=4 ; + L->type = xcfL(ptr); ptr+=4 ; + L->name = xcfString(ptr,&ptr); + L->propptr = ptr ; + while( (type = xcfNextprop(&ptr,&data)) != PROP_END ) { + switch(type) { + case PROP_OPACITY: + L->opacity = xcfL(data); + if( L->opacity > 255 ) + L->opacity = 255 ; + break ; + case PROP_VISIBLE: + L->isVisible = xcfL(data) != 0 ; + break ; + case PROP_APPLY_MASK: + L->hasMask = xcfL(data) != 0 ; + break ; + case PROP_OFFSETS: + L->dim.c.l = (int32_t)(xcfL(data )) ; + L->dim.c.t = (int32_t)(xcfL(data+4)) ; + break ; + case PROP_MODE: + L->mode = xcfL(data); + break ; + default: + /* Ignore unknown properties */ + break ; + } + } + xcfCheckspace(ptr,8,"(end of layer %s)",L->name); + L->pixels.tileptrs = 0 ; + L->pixels.hierarchy = xcfOffset(ptr ,4*4); + L->mask.tileptrs = 0 ; + L->mask.hierarchy = xcfOffset(ptr+4,4*4); + + computeDimensions(&L->dim); + } +} + diff --git a/kernel/kls_xcf/xcf2pnm/xcf2pnm.c b/kernel/kls_xcf/xcf2pnm/xcf2pnm.c new file mode 100644 index 0000000..06baf8d --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/xcf2pnm.c @@ -0,0 +1,269 @@ +/* Convert xcf files to ppm + * + * Copyright (C) 2006 Henning Makholm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "xcftools.h" +#include "flatten.h" +#include +#include +#include +#include +#if HAVE_GETOPT_H +#include +#else +#include +#endif +#ifndef HAVE_GETOPT_LONG +#define getopt_long(argc,argv,optstring,l1,l2) getopt(argc,argv,optstring) +#endif + +#include "xcf2pnm.oi" + +static int suppress_byline ; +static struct FlattenSpec flatspec ; +static FILE *outfile = NULL ; +static FILE *transfile = NULL ; + +static void +start_writing(FILE **f,int version) +{ + const char *format[] = {"(format zero)", + "PBM-ascii", + "PGM-ascii", + "PPM-ascii", + "PBM", + "PGM", + "PPM" }; + + if( verboseFlag ) + fprintf(stderr,f == &outfile ? _("Writing converted image as %s\n") + : _("Writing transparency map as %s\n"), + format[version]); + + *f = openout( f == &outfile ? flatspec.output_filename + : flatspec.transmap_filename ); + fprintf(*f,"P%d",version); + if( suppress_byline ) + ; + else if( f == &outfile ) + fprintf(*f,_(" # Converted by xcf2pnm %s"),PACKAGE_VERSION); + else + fprintf(*f,_(" # Transparency map by xcf2pnm %s"),PACKAGE_VERSION); + fprintf(*f,"\n%d %d\n%s", + flatspec.dim.width, + flatspec.dim.height, + version == 4 ? "" : "255\n"); +} + +int +put_pbm_row(FILE *file,unsigned num,rgba *pixels,rgba mask); + +int +put_pbm_row(FILE *file,unsigned num,rgba *pixels,rgba mask) { + unsigned out ; + unsigned i ; + int bitsleft = 8 ; + out = 0 ; + for( i=0; i> RED_SHIFT) & 0xFF , outfile ); + putc( (pixels[i] >> GREEN_SHIFT) & 0xFF , outfile ); + putc( (pixels[i] >> BLUE_SHIFT) & 0xFF , outfile ); + } + callback_common(num,pixels); +} + +static void +pgm_callback(unsigned num,rgba *pixels) +{ + unsigned i ; + if( outfile == NULL ) start_writing(&outfile,5); + for( i=0; i < num; i++ ) { + int gray = degrayPixel(pixels[i]) ; + if( gray == -1 ) + FatalGeneric(103, + _("Grayscale output selected, but colored pixel(s) found")); + putc( gray, outfile ); + } + callback_common(num,pixels); +} + +static void +pbm_callback(unsigned num,rgba *pixels) +{ + if( outfile == NULL ) start_writing(&outfile,4); + if( !put_pbm_row(outfile,num,pixels, + ((rgba)255 << RED_SHIFT) + + ((rgba)255 << GREEN_SHIFT) + + ((rgba)255 << BLUE_SHIFT)) ) + FatalGeneric(103,_("Monochrome output selected, but not all pixels " + "are black or white")); + callback_common(num,pixels); +} + +static enum out_color_mode +guess_color_mode(const char *string) +{ + if( strlen(string) >= 3 ) { + string += strlen(string)-3 ; + if( strcmp(string,"ppm")==0 ) return COLOR_RGB ; + if( strcmp(string,"pgm")==0 ) return COLOR_GRAY ; + if( strcmp(string,"pbm")==0 ) return COLOR_MONO ; + } + return COLOR_BY_FILENAME ; +} + +static lineCallback +selectCallback(void) +{ + if( flatspec.transmap_filename && ALPHA(flatspec.default_pixel) >= 128 ) + FatalGeneric(101,_("The -a option was given, " + "but the image has no transparency")); + + switch( flatspec.out_color_mode ) { + default: + case COLOR_RGB: return &ppm_callback ; + case COLOR_GRAY: return &pgm_callback ; + case COLOR_MONO: return &pbm_callback ; + } +} + +int +main(int argc,char **argv) +{ + int option ; + const char *unzipper = NULL ; + const char *infile = NULL ; + + setlocale(LC_ALL,""); + progname = argv[0] ; + nls_init(); + + if( argc <= 1 ) gpl_blurb() ; + + init_flatspec(&flatspec) ; + flatspec.out_color_mode = COLOR_BY_FILENAME ; + while( (option=getopt_long(argc,argv,"-@#"OPTSTRING,longopts,NULL)) >= 0 ) + switch(option) { + +#define OPTION(char,long,desc,man) case char: +#include "options.i" + + case 1: + if( infile ) + add_layer_request(&flatspec,optarg); + else + infile = optarg ; + break ; + case '?': + exit(1); + case '@': + /* Non-documented option for build-time test */ + suppress_byline = 1 ; + break ; + case '#': + /* Non-documented option for xcfview */ + flatspec.default_pixel = CHECKERED_BACKGROUND ; + break ; + default: + FatalUnexpected("Getopt(_long) unexpectedly returned '%c'",option); + } + if( infile == NULL ) { + exit(1); + } + + if( flatspec.out_color_mode == COLOR_BY_FILENAME && + strlen(flatspec.output_filename) > 4 && + flatspec.output_filename[strlen(flatspec.output_filename)-4] == '.' ) + flatspec.out_color_mode = guess_color_mode(flatspec.output_filename); + + /* If the output filename was not enough cue, see if we're running + * through a symlink/hardlink that gives the required output format + */ + if( flatspec.out_color_mode == COLOR_BY_FILENAME && + strlen(progname) > 3 ) + flatspec.out_color_mode = guess_color_mode(progname); + + if( flatspec.out_color_mode == COLOR_BY_FILENAME ) + flatspec.out_color_mode = COLOR_BY_CONTENTS ; + + read_or_mmap_xcf(infile,unzipper); + getBasicXcfInfo() ; + initColormap(); + + complete_flatspec(&flatspec,NULL); + if( flatspec.process_in_memory ) { + rgba **allPixels = flattenAll(&flatspec); + analyse_colormode(&flatspec,allPixels,NULL); + shipoutWithCallback(&flatspec,allPixels,selectCallback()); + } else { + flattenIncrementally(&flatspec,selectCallback()); + } + closeout(outfile,flatspec.output_filename) ; + closeout(transfile,flatspec.transmap_filename) ; + return 0 ; +} diff --git a/kernel/kls_xcf/xcf2pnm/xcf2pnm.oi b/kernel/kls_xcf/xcf2pnm/xcf2pnm.oi new file mode 100644 index 0000000..382bd96 --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/xcf2pnm.oi @@ -0,0 +1,41 @@ +/* Autogenerated by mkopti.pl xcf2pnm */ +#define XCF2PNM +#define OPTI_TARGET "xcf2pnm" +#define XCF2FOO +#define OPTIONGROUP(a,b) + +#ifdef HAVE_GETOPT_LONG +static const struct option longopts[] = { + { "help", 0, 0, 'h'}, + { "version", 0, 0, 'V'}, + { "verbose", 0, 0, 'v'}, + { "bzip", 0, 0, 'j'}, + { "gzip", 0, 0, 'z'}, + { "unpack", 1, 0, 'Z'}, + { "output", 1, 0, 'o'}, + { "alpha", 1, 0, 'a'}, + { "background", 1, 0, 'b'}, + { "force-alpha", 0, 0, 'A'}, + { "color", 0, 0, 'c'}, + { "colour", 0, 0, 'c'}, + { "gray", 0, 0, 'g'}, + { "grey", 0, 0, 'g'}, + { "mono", 0, 0, 'm'}, + { "pnm", 0, 0, 'n'}, + { "truecolor", 0, 0, 'T'}, + { "for-gif", 0, 0, 'G'}, + { "dissolve", 0, 0, 'D'}, + { "full-image", 0, 0, 'f'}, + { "size", 1, 0, 'S'}, + { "offset", 1, 0, 'O'}, + { "autocrop", 0, 0, 'C'}, + { "mode", 1, 0, 300}, + { "percent", 1, 0, 301}, + { "opacity", 1, 0, 302}, + { "mask", 0, 0, 303}, + { "nomask", 0, 0, 304}, + { "utf8", 0, 0, 'u'}, +{0}}; +#endif + +#define OPTSTRING "hVvjzZ:o:a:b:AcgmnTGDfS:O:Cu" diff --git a/kernel/kls_xcf/xcf2pnm/xcftools.h b/kernel/kls_xcf/xcf2pnm/xcftools.h new file mode 100644 index 0000000..d3efbab --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/xcftools.h @@ -0,0 +1,182 @@ +/* Generic functions and macros for reading XCF files + * + * Copyright (C) 2006 Henning Makholm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef XCFTOOLS_H +#define XCFTOOLS_H + +#include "enums.h" +#include +#include + +#define _(s) (s) +#define nls_init() (void)0 +#define N_(s) (s) + +#if HAVE_INTTYPES_H +# define __STDC_FORMAT_MACROS +# include +#else +/* These legacy fall-backs will probably work on every system + * that does not supply a inttypes.h ... */ +typedef unsigned char uint8_t ; +typedef unsigned long int uint32_t, uintptr_t ; +typedef signed char int8_t ; +typedef signed long int int32_t ; +# define PRIX32 "lX" +# define PRIu32 "lu" +# define PRIXPTR "lX" +#endif + +#if __GNUC__ +# define __ATTRIBUTE__ __attribute__ +#else +# define __ATTRIBUTE__(x) +#endif + +#if HAVE_NETINET_IN_H +# include +#elif HAVE_ARPA_INET_H +# include +#elif WORDS_BIGENDIAN +# define ntohl(x) (x) +#else +static inline uint32_t ntohl(uint32_t a) { + return (a << 24) + ((a & 0xFF00) << 8) + ((a >> 8) & 0xFF00) + (a >> 24) ; +} +#endif + +#ifndef HAVE_STRCASECMP +#define strcasecmp strcmp +#endif + +/* Read a single word value from the XCF file */ + +/* Use + instead of | because that allows LEA instructions */ +#define xcfBE(a) ( ((uint32_t)xcf_file[(a) ] << 24) + \ + ((uint32_t)xcf_file[(a)+1] << 16) + \ + ((uint32_t)xcf_file[(a)+2] << 8 ) + \ + ((uint32_t)xcf_file[(a)+3] ) ) +#define xcfLE(a) ( ((uint32_t)xcf_file[(a) ] ) + \ + ((uint32_t)xcf_file[(a)+1] << 8 ) + \ + ((uint32_t)xcf_file[(a)+2] << 16) + \ + ((uint32_t)xcf_file[(a)+3] << 24) ) + +#if CAN_DO_UNALIGNED_WORDS +# define xcfL(a) ntohl(*(uint32_t *)(xcf_file + (a))) +#else +# define xcfL(a) ((a) & 3 ? xcfBE(a) : ntohl(*(uint32_t *)(xcf_file + (a)))) +#endif + +/* ****************************************************************** */ + +/* The following are exported from am OS-specific source file; + * io-unix.c on unixish systems. + */ +void read_or_mmap_xcf(const char* filename, const char *unzipper); +void free_or_close_xcf(void); + +/* ****************************************************************** */ +/* utils.c */ + +extern const char *progname ; +extern int verboseFlag ; + +void *xcfmalloc(size_t size); +void xcffree(void*); + +void FatalGeneric(int status,const char* format,...) + __ATTRIBUTE__((format(printf,2,3),noreturn)) ; +void FatalUnexpected(const char* format,...) + __ATTRIBUTE__((format(printf,1,2),noreturn)) ; +void FatalBadXCF(const char* format,...) + __ATTRIBUTE__((format(printf,1,2),noreturn)) ; +void FatalUnsupportedXCF(const char* format,...) + __ATTRIBUTE__((format(printf,1,2),noreturn)) ; + +void gpl_blurb(void) __ATTRIBUTE__((noreturn)); + +FILE* openout(const char*); +void closeout(FILE *,const char*); + +struct rect { + int t, b, l, r ; +}; + +#define isSubrect(A,B) \ + ((A).l >= (B).l && (A).r <= (B).r && (A).t >= (B).t && (A).b <= (B).b) +#define disjointRects(A,B) \ + ((A).l >= (B).r || (A).r <= (B).l || (A).t >= (B).b || (A).b <= (B).t) + +/* ****************************************************************** */ +/* xcf-general.c */ + +extern uint8_t *xcf_file ; +extern size_t xcf_length ; +extern int use_utf8 ; + +void xcfCheckspace(uint32_t addr,int spaceafter, const char *format,...) + __ATTRIBUTE__((format(printf,3,4))); +uint32_t xcfOffset(uint32_t addr,int spaceafter); + +int xcfNextprop(uint32_t *master,uint32_t *body); +const char* xcfString(uint32_t ptr,uint32_t *after); + +/* These are hardcoded in the Gimp sources: */ +#define TILE_WIDTH 64 +#define TILE_HEIGHT 64 + +struct tileDimensions { + struct rect c ; + unsigned width, height ; + unsigned tilesx, tilesy ; + unsigned ntiles ; +}; +/* computeDimensions assumes that width, height, c.l, and c.t are set */ +void computeDimensions(struct tileDimensions *); + +struct xcfTiles { + const struct _convertParams *params ; + uint32_t *tileptrs ; + uint32_t hierarchy ; +}; + +struct xcfLayer { + struct tileDimensions dim ; + const char *name ; + GimpLayerModeEffects mode ; + GimpImageType type ; + unsigned int opacity ; + int isVisible, hasMask ; + uint32_t propptr ; + struct xcfTiles pixels ; + struct xcfTiles mask ; +}; + +extern struct xcfImage { + int version ; + unsigned width, height ; + GimpImageBaseType type ; + XcfCompressionType compression ; + int numLayers ; + struct xcfLayer *layers ; + uint32_t colormapptr ; +} XCF ; + +void getBasicXcfInfo(void); + +#endif /* XCFTOOLS_H */ diff --git a/kernel/kls_xcur/Makefile.am b/kernel/kls_xcur/Makefile.am new file mode 100644 index 0000000..9554260 --- /dev/null +++ b/kernel/kls_xcur/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_xcur.la + +libkls_xcur_la_SOURCES = fmt_codec_xcur.cpp fmt_codec_xcur_defs.h + +libkls_xcur_la_LDFLAGS = ${SQ_RELEASE} + +libkls_xcur_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_xcur/fmt_codec_xcur.cpp b/kernel/kls_xcur/fmt_codec_xcur.cpp new file mode 100644 index 0000000..28d42f1 --- /dev/null +++ b/kernel/kls_xcur/fmt_codec_xcur.cpp @@ -0,0 +1,166 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_xcur_defs.h" +#include "fmt_codec_xcur.h" + +#include "../xpm/codec_xcur.xpm" + +/* + * + * Library to support X cursors. + * + * You can test it with nice cursors from http://kde-apps.org + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.4.0"; + o->name = "X Cursors"; + o->filter = ""; + o->config = ""; + o->mime = "Xcur"; + o->mimetype = "image/x-xcursor"; + o->pixmap = codec_xcur; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + currentToc = -1; + + if(!frs.readK(&xcur_h, sizeof(XCUR_HEADER))) return SQE_R_BADFILE; + + tocs = new XCUR_CHUNK_DESC [xcur_h.ntoc]; + + if(!tocs) + return SQE_R_NOMEMORY; + + if(!frs.readK(tocs, sizeof(XCUR_CHUNK_DESC) * xcur_h.ntoc)) return SQE_R_BADFILE; + + lastToc = false; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(lastToc) + { + finfo.animated = (currentToc > 0); + return SQE_NOTOK; + } + + do + { + currentToc++; + } + while(tocs[currentToc].type != XCUR_CHUNK_TYPE_IMAGE && currentToc < (s32)xcur_h.ntoc); + + if(currentToc == (s32)xcur_h.ntoc-1) + lastToc = true; + + fmt_image image; + + frs.seekg(tocs[currentToc].pos, ios::beg); + + if(!frs.readK(&xcur_chunk, sizeof(XCUR_CHUNK_HEADER))) return SQE_R_BADFILE; + if(!frs.readK(&xcur_im, sizeof(XCUR_CHUNK_IMAGE))) return SQE_R_BADFILE; + + image.w = xcur_im.width; + image.h = xcur_im.height; + image.bpp = 32; + image.delay = xcur_im.delay; + image.hasalpha = true; + image.compression = "-"; + image.colorspace = "ARGB"; + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGBA rgba; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + for(s32 i = 0;i < im->w;i++) + { + if(!frs.readK(&rgba, sizeof(RGBA))) return SQE_R_BADFILE; + + (scan+i)->r = rgba.b; + (scan+i)->g = rgba.g; + (scan+i)->b = rgba.r; + (scan+i)->a = rgba.a; + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + delete [] tocs; + tocs = NULL; + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_xcur/fmt_codec_xcur_defs.h b/kernel/kls_xcur/fmt_codec_xcur_defs.h new file mode 100644 index 0000000..301bfab --- /dev/null +++ b/kernel/kls_xcur/fmt_codec_xcur_defs.h @@ -0,0 +1,76 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_xcur +#define KSQUIRREL_READ_IMAGE_xcur + +struct XCUR_CHUNK_DESC +{ + u32 type; + u32 subtype; + u32 pos; + +}PACKED; + +struct XCUR_HEADER +{ + u32 magic; + u32 header; + u32 version; + u32 ntoc; + +}PACKED; +/* Array of XCUR_CHUNK_DESC comes here */ + +struct XCUR_CHUNK_HEADER +{ + u32 header; + u32 type; + u32 subtype; + u32 version; + +}PACKED; + +struct XCUR_COMMENT_HEADER +{ +// u32 version; + u32 length; +// s8 *text; + +}PACKED; + +struct XCUR_CHUNK_IMAGE +{ +// u32 version; +// u32 size; + u32 width; + u32 height; + u32 xhot; + u32 yhot; + u32 delay; + +}PACKED; + + +#define XCUR_CHUNK_TYPE_COMMENT 0xFFFE0001 +#define XCUR_CHUNK_TYPE_IMAGE 0xFFFD0002 + +#endif diff --git a/kernel/kls_xim/Makefile.am b/kernel/kls_xim/Makefile.am new file mode 100644 index 0000000..c14de1e --- /dev/null +++ b/kernel/kls_xim/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I../include + +bin_SCRIPTS = ksquirrel-libs-xim2ppm + +pkglib_LTLIBRARIES = libkls_xim.la + +libkls_xim_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h + +libkls_xim_la_LDFLAGS = ${SQ_RELEASE} + +libkls_xim_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DCODEC_NETPBM -DCODEC_XIM -DNETPBM_S=\"${bindir}/ksquirrel-libs-xim2ppm\" + +EXTRA_DIST = ksquirrel-libs-xim2ppm.in diff --git a/kernel/kls_xim/fmt_codec_pnm.cpp b/kernel/kls_xim/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_xim/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include + +// we will use fork() +#if defined CODEC_DJVU \ + || defined CODEC_CAMERA \ + || defined CODEC_DXF \ + || defined CODEC_XCF \ + || defined CODEC_TTF \ + || defined CODEC_FIG \ + || defined CODEC_LJPEG \ + || defined CODEC_NETPBM +#include +#include +#include +#include +#endif + +#ifdef CODEC_EPS +#include +#include +#include +#endif + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_pnm_defs.h" +#include "fmt_codec_pnm.h" + +#if defined CODEC_CAMERA +#include "../xpm/codec_camera.xpm" +#elif defined CODEC_DJVU +#include "../xpm/codec_djvu.xpm" +#elif defined CODEC_XCF +#include "../xpm/codec_xcf.xpm" +#elif defined CODEC_DXF +#include "../xpm/codec_dxf.xpm" +#elif defined CODEC_NEO +#include "../xpm/codec_neo.xpm" +#elif defined CODEC_LEAF +#include "../xpm/codec_leaf.xpm" +#elif defined CODEC_PI1 +#include "../xpm/codec_pi1.xpm" +#elif defined CODEC_PI3 +#include "../xpm/codec_pi3.xpm" +#elif defined CODEC_XIM +#include "../xpm/codec_xim.xpm" +#elif defined CODEC_UTAH +#include "../xpm/codec_utah.xpm" +#elif defined CODEC_PICT +#include "../xpm/codec_pict.xpm" +#elif defined CODEC_IFF +#include "../xpm/codec_iff.xpm" +#elif defined CODEC_MAC +#include "../xpm/codec_mac.xpm" +#elif defined CODEC_TTF +#include "../xpm/codec_ttf.xpm" +#elif defined CODEC_FIG +#include "../xpm/codec_fig.xpm" +#elif defined CODEC_LJPEG +#include "../xpm/codec_ljpeg.xpm" +#elif defined CODEC_EPS +#include "../xpm/codec_eps.xpm" +#else +#include "../xpm/codec_pnm.xpm" +#endif + +/* + * + * PBM, PGM, + * PNM, and PPM are + * intermediate formats used in the conversion of many little known + * formats via pbmplus, the Portable Bitmap Utilities. These + * formats are mainly available under UNIX and + * on Intel-based PCs. + * + */ + +static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)}; + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{ +#ifdef CODEC_DXF + std::string tmmp = tmp + ".ppm"; + unlink(tmmp.c_str()); +#endif +} + +void fmt_codec::options(codec_options *o) +{ +#if defined CODEC_CAMERA + o->version = "8.77"; // dcraw version + o->name = "Photos from different cameras"; + o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f "; + o->config = std::string(CAMERA_UI); + o->mime = ""; + o->mimetype = "image/x-raw"; + o->pixmap = codec_camera; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DJVU + o->version = "1.0.0"; + o->name = "DjVu Document"; + o->filter = "*.djvu *.djv *.iw4 *.iw44 "; + o->config = std::string(DJVU_UI); + o->mime = ""; + o->mimetype = "image/x-djvu;image/x.djvu"; + o->pixmap = codec_djvu; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_DXF + o->version = "1.0.0"; + o->name = "AutoCAD/QCAD Drawing"; + o->filter = "*.dxf "; + o->config = std::string(DXF_UI); + o->mime = ""; + o->mimetype = "image/x-dxf"; + o->pixmap = codec_dxf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XCF + o->version = "1.0.0"; + o->name = "GIMP XCF"; + o->filter = "*.xcf "; + o->config = std::string(XCF_UI); + o->mime = ""; + o->mimetype = "image/x-xcf-gimp"; + o->pixmap = codec_xcf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_NEO + o->version = "1.0.0"; + o->name = "Neochrome NEO"; + o->filter = "*.neo "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-neo"; + o->pixmap = codec_neo; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LEAF + o->version = "1.0.0"; + o->name = "ILEAF Image"; + o->filter = "*.leaf "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-leaf"; + o->pixmap = codec_leaf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI1 + o->version = "1.0.0"; + o->name = "Degas PI1"; + o->filter = "*.pi1 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi1"; + o->pixmap = codec_pi1; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PI3 + o->version = "1.0.0"; + o->name = "Degas PI3"; + o->filter = "*.pi3 "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pi3"; + o->pixmap = codec_pi3; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_XIM + o->version = "1.0.0"; + o->name = "X IMage"; + o->filter = "*.xim "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xim"; + o->pixmap = codec_xim; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_UTAH + o->version = "1.0.0"; + o->name = "UTAH RLE"; + o->filter = "*.rle "; + o->config = ""; + o->mime = "\x0052\x00CC"; + o->mimetype = "image/x-utah"; + o->pixmap = codec_utah; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_PICT + o->version = "1.0.0"; + o->name = "Macintosh PICT"; + o->filter = "*.pict "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-pict"; + o->pixmap = codec_pict; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_IFF + o->version = "1.0.0"; + o->name = "Interchange File Format"; + o->filter = "*.iff *.ilbm *.lbm "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-iff"; + o->pixmap = codec_iff; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_MAC + o->version = "1.0.0"; + o->name = "Macintosh Paint"; + o->filter = "*.mac "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-mac"; + o->pixmap = codec_mac; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_FIG + o->version = "0.1.0"; + o->name = "XFIG"; + o->filter = "*.fig "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xfig"; + o->pixmap = codec_fig; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_TTF + o->version = "0.3.0"; + o->name = "TrueType and Other Fonts"; + o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf "; + o->config = ""; + o->mime = ""; + o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1"; + o->pixmap = codec_ttf; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_LJPEG + o->version = "0.1.0"; + o->name = "Lossless JPEG"; + o->filter = "*.ljpg *.ljpeg "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/ljpeg"; + o->pixmap = codec_ljpeg; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#elif defined CODEC_EPS + o->version = "0.1.0"; + o->name = "Encapsulated PostScript"; + o->filter = "*.eps "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-eps"; + o->pixmap = codec_eps; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = true; +#else + o->version = "0.6.4"; + o->name = "Portable aNy Map"; + o->filter = "*.pnm *.pgm *.pbm *.ppm "; + o->config = ""; + o->mime = "P[123456]"; + o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap"; + o->pixmap = codec_pnm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = true; + o->writeanimated = false; + o->needtempfile = false; +#endif +} + +#if defined CODEC_CAMERA +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // scale factor in percents + val.type = settings_value::v_bool; + + val.bVal = true; + m_settings["half_size"] = val; + m_settings["automatic_white"] = val; + m_settings["camera_white"] = val; + + val.bVal = false; + m_settings["dontstretch"] = val; + m_settings["camera_date"] = val; + m_settings["document_mode"] = val; + m_settings["interpolate_rggb"] = val; + m_settings["icc_cam"] = val; + m_settings["embedded_cm"] = val; + + val.type = settings_value::v_int; + val.iVal = 0; + m_settings["highlights"] = val; + m_settings["different"] = val; + m_settings["flipping"] = val; // 0 means camera settings + + val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation + m_settings["quick"] = val; + val.iVal = -1; // don't use black pixel + m_settings["black"] = val; + val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold + m_settings["threshold"] = val; + val.iVal = 1; + m_settings["brightness"] = val; + + val.type = settings_value::v_string; + val.sVal = ""; + m_settings["icc_file"] = val; +} +#elif defined CODEC_DJVU +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 1; + m_settings["page"] = val; + + val.iVal = 2; + m_settings["scaledown"] = val; +} +#elif defined CODEC_DXF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // page number + val.type = settings_value::v_int; + + val.iVal = 0; + m_settings["width"] = val; + val.iVal = 0; + m_settings["height"] = val; +} +#elif defined CODEC_XCF +void fmt_codec::fill_default_settings() +{ + settings_value val; + + // background color + val.type = settings_value::v_string; + val.sVal = "#ffffff"; + m_settings["background"] = val; + + val.type = settings_value::v_bool; + val.bVal = false; + m_settings["autocrop"] = val; +} +#endif + +#ifdef CODEC_EPS + +/* + * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is + * under GNU LGPL + */ + +#define BUFLEN 200 + +#define BBOX "%%BoundingBox:" +#define BBOX_LEN strlen(BBOX) + +static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size) +{ + char buf[4]; // We at most need to read 4 bytes at a time + ps_offset = 0L; + ps_size = 0L; + + if(!io->readK(buf, 2)) // Read first two bytes + return false; + + if(buf[0]=='%' && buf[1]=='!') // Check %! magic + { + } + else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic + { // May be a MS-DOS EPS file + if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic + return false; + + if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic + { + if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + ps_offset // Offset is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file. + return false; + + ps_size // Size is in little endian + = ((unsigned char) buf[0]) + + ((unsigned char) buf[1] << 8) + + ((unsigned char) buf[2] << 16) + + ((unsigned char) buf[3] << 24); + + if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file. + return false; + + if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code + return false; + + if(buf[0] != '%' || buf[1] != '!') // Check %! magic + return false; + } + else + return false; + } + else + return false; + + return true; +} + +static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2) +{ + char buf[BUFLEN+1]; + + bool ret = false; + + while(io->getline(buf, BUFLEN).good() && strlen(buf)) + { + if(strncmp(buf, BBOX, BBOX_LEN) == 0) + { + // Some EPS files have non-integer values for the bbox + // We don't support that currently, but at least we parse it + float _x1, _y1, _x2, _y2; + + if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) + { + *x1 = (int)_x1; + *y1 = (int)_y1; + *x2 = (int)_x2; + *y2 = (int)_y2; + + ret = true; + break; + } + } + } + + return ret; +} + +#endif + +s32 fmt_codec::read_init(const std::string &file) +{ + fptr = 0; + +#if defined CODEC_CAMERA + std::vector params; + int status; + + bool half_size, + dontstretch, + camera_date, + automatic_white, + camera_white, + document_mode, + interpolate_rggb, + icc_cam, + embedded_cm; + + int quick, + threshold, + black, + different, + highlights, + flipping, + brightness; + + std::string icc_file; + + fmt_settings::iterator it = m_settings.find("half_size"); + half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("icc_cam"); + icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("embedded_cm"); + embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("dontstretch"); + dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("camera_date"); + camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("automatic_white"); + automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("camera_white"); + camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + true : (*it).second.bVal; + + it = m_settings.find("document_mode"); + document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("interpolate_rggb"); + interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + it = m_settings.find("quick"); + quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(quick < 0 || quick > 3) + quick = 0; + + it = m_settings.find("highlights"); + highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(highlights < 0 || highlights > 9) + highlights = 0; // revert to default value + + it = m_settings.find("flipping"); + flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6) + flipping = 0; // revert to default value + + it = m_settings.find("black"); + black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + -1 : (*it).second.iVal; + + if(black < -1 || black > 255) + black = -1; + + it = m_settings.find("different"); + different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + if(different < 0 || different > 99) + different = 0; // revert to default + + it = m_settings.find("threshold"); + threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 100 : (*it).second.iVal; + + if(threshold < 99 || threshold > 1000) + threshold = 99; // revert to default + + it = m_settings.find("brightness"); + brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + if(brightness < 1 || brightness > 255) + brightness = 1; + + it = m_settings.find("icc_file"); + icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "" : (*it).second.sVal; + + if(embedded_cm) + params.push_back("+M"); + else + params.push_back("-M"); + + if(half_size) params.push_back("-h"); + if(dontstretch) params.push_back("-j"); + if(camera_date) params.push_back("-z"); + if(automatic_white) params.push_back("-a"); + if(camera_white) params.push_back("-w"); + if(document_mode) params.push_back("-d"); + if(interpolate_rggb) params.push_back("-f"); + + char ss[32]; + + if(quick) + { + if(quick == 1) + quick = 0; + + sprintf(ss, "%d", quick); + params.push_back("-q"); + params.push_back(ss); + } + + if(threshold != 99) + { + sprintf(ss, "%d", threshold); + params.push_back("-n"); + params.push_back(ss); + } + + if(black >= 0) + { + sprintf(ss, "%d", black); + params.push_back("-k"); + params.push_back(ss); + } + + sprintf(ss, "%d", different); + params.push_back("-s"); + params.push_back(ss); + + sprintf(ss, "%d", brightness); + params.push_back("-b"); + params.push_back(ss); + + sprintf(ss, "%d", highlights); + params.push_back("-H"); + params.push_back(ss); + + if(flipping) + { + if(flipping == 1) + flipping = 0; // 0, 3, 5, 6 are accepted + + sprintf(ss, "%d", flipping); + params.push_back("-t"); + params.push_back(ss); + } + +#ifndef NO_LCMS + if(icc_cam) + { + params.push_back("-p"); + params.push_back("embed"); + } + else if(icc_file.length()) + { + params.push_back("-p"); + params.push_back(icc_file); + } +#endif + + const s32 argc = 9 + params.size(); + + const char *argv[argc]; + argv[0] = KLDCRAW_S; + + for(int i = 1;i < argc-8;i++) + argv[i] = params[i-1].c_str(); + + argv[argc-8] = "-c"; // write to stdout + argv[argc-7] = "--input"; + argv[argc-6] = file.c_str(); + argv[argc-5] = "--binary"; + argv[argc-4] = KLDCRAW; + argv[argc-3] = "--output"; + argv[argc-2] = tmp.c_str(); + argv[argc-1] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(argv[0], (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DJVU + + fmt_settings::iterator it = m_settings.find("scaledown"); + + // get aspect + s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(aspect < 1 || aspect > 12) + aspect = 2; + + it = m_settings.find("page"); + + // get page number + s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 1 : (*it).second.iVal; + + // correct + if(ipage < 0 || ipage > 1000) + ipage = 1; + + int status; + + s8 subsample[20]; + s8 pagesp[20]; + + snprintf(subsample, 20, "-subsample=%d", aspect); + snprintf(pagesp, 20, "-page=%d", ipage); + + pid_t pid = fork(); + + if(!pid) + { + execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_DXF + + std::string tmmp = tmp + ".ppm"; + fmt_settings::iterator it = m_settings.find("width"); + + // get aspect + s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(width < 0 || width > 10000) + width = 0; + + it = m_settings.find("height"); + + // get page number + s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ? + 0 : (*it).second.iVal; + + // correct + if(height < 0 || height > 10000) + height = 0; + + s32 status; + + s8 swidth[20], sheight[20]; + + const int argc = 8; + const char *argv[argc]; + const char *x = "-x", *y = "-y"; + + int i = 3; + argv[0] = VEC2WEB; + argv[1] = file.c_str(); + argv[2] = tmmp.c_str(); + + if(width) + { + snprintf(swidth, 20, "%d", width); + argv[i++] = x; + argv[i++] = swidth; + } + + if(height) + { + snprintf(sheight, 20, "%d", height); + argv[i++] = y; + argv[i++] = sheight; + } + + argv[i] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(VEC2WEB, (char* const*)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmmp.c_str(), "rb"); + +#elif defined CODEC_XCF + + const s32 argc = 9; + int status; + + fmt_settings::iterator it = m_settings.find("background"); + + // background for transparent images + std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ? + "#ffffff" : (*it).second.sVal; + + it = m_settings.find("autocrop"); + + // autocrop ? + bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ? + false : (*it).second.bVal; + + const char *argv[argc]; + argv[0] = KLXCF2PNM; + + std::string bg = "-b"; + bg += bkgr; + argv[1] = bg.c_str(); + + int i = 2; + + if(autocrop) + { + argv[i++] = "-C"; + } + + argv[i++] = "-T"; + argv[i++] = "-c"; + argv[i++] = "-o"; + argv[i++] = tmp.c_str(); + argv[i++] = file.c_str(); + argv[i++] = (char *)0; + + pid_t pid = fork(); + + if(!pid) + { + execvp(KLXCF2PNM, (char *const *)argv); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); // TODO check for errors + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_NETPBM + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_LJPEG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_FIG + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_TTF + + int status; + + pid_t pid = fork(); + + if(!pid) + { + execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0); + exit(1); + } + else if(pid == -1) + return SQE_R_BADFILE; + + ::waitpid(pid, &status, 0); + + if(WIFEXITED(status)) + if(WEXITSTATUS(status)) + return SQE_R_BADFILE; + else; + else + return SQE_R_BADFILE; + + fptr = fopen(tmp.c_str(), "rb"); + +#elif defined CODEC_EPS + + /* + * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL. + */ + + FILE * ghostfd; + int x1, y1, x2, y2; + + std::string cmdBuf; + + size_t ps_offset, ps_size; + + ifstreamK io; + io.open(file.c_str(), ios::in); + + if(!io.good()) + return SQE_R_NOFILE; + + // find start of PostScript code + if (!seekToCodeStart(&io, ps_offset, ps_size)) + return SQE_R_BADFILE; + + // find bounding box + if(!bbox(&io, &x1, &y1, &x2, &y2)) + return SQE_R_BADFILE; + + x2 -= x1; + y2 -= y1; + + double xScale = 1.0; + double yScale = 1.0; + bool needsScaling = false; + int wantedWidth = x2; + int wantedHeight = y2; + + std::stringstream str(cmdBuf); + + str << EPS2PPM << " -sOutputFile="; + str << tmp; + str << " -q -g"; + str << wantedWidth << "x" << wantedHeight; + str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c " + "0 0 moveto " + "1000 0 lineto " + "1000 1000 lineto " + "0 1000 lineto " + "1 1 254 255 div setrgbcolor fill " + "0 0 0 setrgbcolor - -c showpage quit"; + + ghostfd = popen(str.str().c_str(), "w"); + + if(ghostfd == 0) + return SQE_R_BADFILE; + + fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale))); + + if(needsScaling) + fprintf(ghostfd, "%g %g scale\n", xScale, yScale); + + io.seekg(0, ios::beg); + + char bbuf[4096]; + + if(ps_offset > 0) // We have an offset + io.seekg(ps_offset, ios::beg); + + std::string buffer; + + while(!io.eof()) + { + io.read(bbuf, sizeof(bbuf)); + buffer.append(bbuf, io.gcount()); + } + + // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size + if (ps_size <= 0 || ps_size > buffer.size()) + ps_size = buffer.size(); + + fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd); + + pclose(ghostfd); + + fptr = fopen(tmp.c_str(), "rb"); + +#else + + fptr = fopen(file.c_str(), "rb"); + +#endif + + if(!fptr) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s8 str[256]; + s32 w, h; + u32 maxcolor; + + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + pnm = str[1] - 48; + + if(pnm < 1 || pnm > 6) + return SQE_R_BADFILE; + + while(true) + { + if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE; + + if(str[0] != '#') + break; + } + + sscanf(str, "%d%d", &w, &h); + + image.w = w; + image.h = h; + + switch(pnm) + { + case 1: + case 4: + image.bpp = 1; + break; + + case 2: + case 5: + image.bpp = 8; + break; + + case 3: + case 6: + image.bpp = 8; + break; + } + + if(pnm != 4 && pnm != 1) + { + fscanf(fptr, "%d", &maxcolor); + + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + if((pnm == 5 || pnm == 6) && maxcolor > 255) + return SQE_R_BADFILE; + + if(pnm == 2 || pnm == 3) + { + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + else + { + u8 dummy; + if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE; + } + + if(maxcolor <= 9) + strcpy(format, "%1d"); + else if(maxcolor >= 9 && maxcolor <= 99) + strcpy(format, "%2d"); + else if(maxcolor > 99 && maxcolor <= 999) + strcpy(format, "%3d"); + else if(maxcolor > 999 && maxcolor <= 9999) + strcpy(format, "%4d"); + + koeff = 255.0 / maxcolor; + } + else if(pnm == 1) + { + strcpy(format, "%1d"); + koeff = 1.0; + } + + image.compression = "-"; + image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed"); + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + RGB rgb; + u8 bt; + s32 i, a; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(pnm) + { + case 1: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memcpy(scan+i, palmono+a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 2: + { + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + a = (s32)(a * koeff); + + memset(scan+i, a, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + } + break; + + case 3: + for(i = 0;i < im->w;i++) + { + fscanf(fptr, format, &a); rgb.r = a; + fscanf(fptr, format, &a); rgb.g = a; + fscanf(fptr, format, &a); rgb.b = a; + if(sq_ferror(fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + if(!skip_flood(fptr)) + return SQE_R_BADFILE; + break; + + case 6: + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + break; + + case 5: + { + for(i = 0;i < im->w;i++) + { + if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE; + + memset(scan+i, int(bt*koeff), sizeof(RGB)); + } + } + break; + + case 4: + { + s32 index;//, remain = im->w % 8; + + for(i = 0;;) + { + if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE; + + index = (bt&128)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&64)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&32)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&16)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&8)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&4)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&2)?1:0; + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + index = (bt&1); + memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break; + } + } + break; + } + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(fptr) + fclose(fptr); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool skip_flood(FILE *f) +{ + s32 pos; + u8 b; + + while(true) + { + pos = ftell(f); + if(!sq_fread(&b, 1, 1, f)) return false; + + if(!isspace(b)) + { + if(b == '#') + { + while(true) + { + if(!sq_fgetc(f, &b)) return false; + + if(b == '\n') + break; + } + } + + break; + } + } + + fsetpos(f, (fpos_t*)&pos); + + return true; +} + +#ifdef CODEC_PNM + +void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt) +{ + opt->interlaced = false; + opt->compression_scheme = CompressionNo; + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + opt->passes = 1; + opt->needflip = false; + opt->palette_flags = 0 | fmt_image::pure32; +} + +s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +s32 fmt_codec::write_next() +{ + fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl; + + return fws.good() ? SQE_OK : SQE_W_ERROR; +} + +s32 fmt_codec::write_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::write_scanline(RGBA *scan) +{ + for(s32 i = 0;i < writeimage.w;i++) + { + if(!fws.writeK(scan+i, sizeof(RGB))) + return SQE_W_ERROR; + } + + return SQE_OK; +} + +void fmt_codec::write_close() +{ + fws.close(); +} + +std::string fmt_codec::extension(const s32 /*bpp*/) +{ + return std::string("pnm"); +} + +#endif // CODEC_PNM + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_xim/fmt_codec_pnm_defs.h b/kernel/kls_xim/fmt_codec_pnm_defs.h new file mode 100644 index 0000000..bc61ec4 --- /dev/null +++ b/kernel/kls_xim/fmt_codec_pnm_defs.h @@ -0,0 +1,64 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_pnm +#define KSQUIRREL_READ_IMAGE_pnm + +bool skip_flood(FILE *); + +bool sq_fgetc(FILE *f, u8 *c) +{ + s32 e = fgetc(f); + + if(ferror(f) || feof(f)) + return false; + + *c = e; + + return true; +} + +bool sq_fgets(s8 *s, s32 size, FILE *stream) +{ + s8 *r = (s8*)fgets((char*)s, size, stream); + + if(ferror(stream) || feof(stream) || !r) + return false; + + return true; +} + +bool sq_ferror(FILE *f) +{ + return (ferror(f) || feof(f)); +} + +bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t r = fread(ptr, size, nmemb, stream); + + if(ferror(stream) || feof(stream) || r != nmemb) + return false; + + return true; +} + +#endif diff --git a/kernel/kls_xim/ksquirrel-libs-xim2ppm.in b/kernel/kls_xim/ksquirrel-libs-xim2ppm.in new file mode 100644 index 0000000..a14442f --- /dev/null +++ b/kernel/kls_xim/ksquirrel-libs-xim2ppm.in @@ -0,0 +1,3 @@ +#!/bin/sh + +@XIMTOPPM@ "$1" > "$2" \ No newline at end of file diff --git a/kernel/kls_xpm/Makefile.am b/kernel/kls_xpm/Makefile.am new file mode 100644 index 0000000..0188af0 --- /dev/null +++ b/kernel/kls_xpm/Makefile.am @@ -0,0 +1,17 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_xpm.la + +libkls_xpm_la_SOURCES = fmt_codec_xpm.cpp fmt_codec_xpm_defs.h xpm_utils.h + +libkls_xpm_la_LDFLAGS = ${SQ_RELEASE} + +libkls_xpm_la_LIBADD = ${SQ_LOCAL_RPATH} + +AM_CXXFLAGS = -DSQ_RGBMAP=\"${pkgdatadir}/rgbmap\" + +EXTRA_DIST = rgbmap + +install-data-am: + $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) + $(INSTALL) --mode=0644 rgbmap $(DESTDIR)$(pkgdatadir)/rgbmap \ No newline at end of file diff --git a/kernel/kls_xpm/fmt_codec_xpm.cpp b/kernel/kls_xpm/fmt_codec_xpm.cpp new file mode 100644 index 0000000..e3503df --- /dev/null +++ b/kernel/kls_xpm/fmt_codec_xpm.cpp @@ -0,0 +1,258 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" +#include "ksquirrel-libs/fmt_utils.h" + +#include "fmt_codec_xpm.h" +#include "fmt_codec_xpm_defs.h" + +#include "xpm_utils.h" + +#include "../xpm/codec_xpm.xpm" + +/* + * + * The XPM (X PixMap) format is the current de facto standard for storing X Window + * pixmap data to a disk file. This format is supported by many image editors, + * graphics window managers, and image file converters. + * + * + * XPM is capable of storing black-and-white, gray-scale, or color image data. + * Hotspot information for cursor bitmaps may also be stored. Although small + * collections of data, such as icons, are typically associated with XPM files, + * there is no limit to the size of an image or the number of colors that may be + * stored in an XPM file. + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{ + fillmap(); +} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.6.4"; + o->name = "X11 Pixmap"; + o->filter = "*.xpm "; + o->config = ""; + o->mime = "/\\* XPM \\*/\n"; + o->mimetype = "image/x-xpm"; + o->pixmap = codec_xpm; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &fl) +{ + frs.open(fl.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + + finfo.animated = false; + + file.clear(); + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + s32 i; + s8 str[256]; + + s32 ret; + + while(true) { ret = skip_comments(frs); if(ret == 1) continue; else if(!ret) break; else return SQE_R_BADFILE; } + if(!frs.getS(str, 256)) return SQE_R_BADFILE; + if(strncmp(str, "static", 6) != 0) return SQE_R_BADFILE; + while(true) { ret = skip_comments(frs); if(ret == 1) continue; else if(!ret) break; else return SQE_R_BADFILE; } + if(!frs.getS(str, 256)) return SQE_R_BADFILE; + while(true) { ret = skip_comments(frs); if(ret == 1) continue; else if(!ret) break; else return SQE_R_BADFILE; } + + sscanf(str, "\"%d %d %d %d", &image.w, &image.h, &numcolors, (int*)&cpp); + + if(!numcolors) + return SQE_R_BADFILE; + + s8 name[KEY_LENGTH], c[3], color[10], *found; + + for(i = 0;i < numcolors;i++) + { + if(!frs.getS(str, 256)) return SQE_R_BADFILE; + + if(*str != '\"') + { + numcolors = i; + break; + } + + strcpy(name, ""); + + found = str; + found++; + + strncpy(name, found, cpp); + name[cpp] = 0; + + sscanf(found+cpp+1, "%s %s", c, color); + + found = strstr(color, "\""); + if(found) *found = 0; + + file[name] = hex2rgb(color); + } + + if(!numcolors) + return SQE_R_BADFILE; + + while(true) { ret = skip_comments(frs); if(ret == 1) continue; else if(!ret) break; else return SQE_R_BADFILE; } + + image.bpp = 24; + image.hasalpha = true; + image.passes = 1; + image.compression = "-"; + image.colorspace = "Indexed RGBA"; + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + const s32 bpl = im->w * (cpp+2); + s32 i, j; + s8 line[bpl], key[KEY_LENGTH]; + + memset(key, 0, sizeof(key)); + memset(line, 0, sizeof(line)); + + switch(im->bpp) + { + case 24: + { + RGBA rgba; + bool f; + + i = j = 0; + if(!frs.getS(line, sizeof(line))) return SQE_R_BADFILE; + + while(line[i++] != '\"') // skip spaces + {} + + for(;j < im->w;j++) + { + strncpy(key, line+i, cpp); + i += cpp; + + std::map::const_iterator it = file.find(key); + + f = (it != file.end()); + + if(!f) + { + cerr << "XPM decoder: WARNING: color \"" << key << "\" not found, assuming transparent instead" << endl; + memset(&rgba, 0, sizeof(RGBA)); + } + else + rgba = (*it).second; + + memcpy(scan+j, &rgba, sizeof(RGBA)); + } + } + break; + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); + + file.clear(); +} + +void fmt_codec::fillmap() +{ + s8 name[80]; + s32 r, g, b, a; + + std::ifstream rgb_fstream; + + rgb_fstream.open(SQ_RGBMAP, ios::in); + + if(!rgb_fstream.good()) + { + std::cerr << "libkls_xpm.so: rgbmap not found" << std::endl; + return; + } + + typedef std::pair xpm_pair; + + while(rgb_fstream.good()) + { + rgb_fstream >> name >> r >> g >> b >> a; + + named.insert(xpm_pair(name, RGBA(r,g,b,a))); + } + + rgb_fstream.close(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_xpm/fmt_codec_xpm_defs.h b/kernel/kls_xpm/fmt_codec_xpm_defs.h new file mode 100644 index 0000000..b0a8316 --- /dev/null +++ b/kernel/kls_xpm/fmt_codec_xpm_defs.h @@ -0,0 +1,25 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_xpm +#define KSQUIRREL_READ_IMAGE_xpm + +#endif diff --git a/kernel/kls_xpm/rgbmap b/kernel/kls_xpm/rgbmap new file mode 100644 index 0000000..399c88e --- /dev/null +++ b/kernel/kls_xpm/rgbmap @@ -0,0 +1,719 @@ +AliceBlue 240 248 255 255 +AntiqueWhite 250 235 215 255 +AntiqueWhite1 255 239 219 255 +AntiqueWhite2 238 223 204 255 +AntiqueWhite3 205 192 176 255 +AntiqueWhite4 139 131 120 255 +BlanchedAlmond 255 235 205 255 +BlueViolet 138 43 226 255 +CadetBlue 95 158 160 255 +CadetBlue1 152 245 255 255 +CadetBlue2 142 229 238 255 +CadetBlue3 122 197 205 255 +CadetBlue4 83 134 139 255 +CornflowerBlue 100 149 237 255 +DarkBlue 0 0 139 255 +DarkCyan 0 139 139 255 +DarkGoldenrod 184 134 11 255 +DarkGoldenrod1 255 185 15 255 +DarkGoldenrod2 238 173 14 255 +DarkGoldenrod3 205 149 12 255 +DarkGoldenrod4 139 101 8 255 +DarkGray 169 169 169 255 +DarkGreen 0 100 0 255 +DarkGrey 169 169 169 255 +DarkKhaki 189 183 107 255 +DarkMagenta 139 0 139 255 +DarkOliveGreen 85 107 47 255 +DarkOliveGreen1 202 255 112 255 +DarkOliveGreen2 188 238 104 255 +DarkOliveGreen3 162 205 90 255 +DarkOliveGreen4 110 139 61 255 +DarkOrange 255 140 0 255 +DarkOrange1 255 127 0 255 +DarkOrange2 238 118 0 255 +DarkOrange3 205 102 0 255 +DarkOrange4 139 69 0 255 +DarkOrchid 153 50 204 255 +DarkOrchid1 191 62 255 255 +DarkOrchid2 178 58 238 255 +DarkOrchid3 154 50 205 255 +DarkOrchid4 104 34 139 255 +DarkRed 139 0 0 255 +DarkSalmon 233 150 122 255 +DarkSeaGreen 143 188 143 255 +DarkSeaGreen1 193 255 193 255 +DarkSeaGreen2 180 238 180 255 +DarkSeaGreen3 155 205 155 255 +DarkSeaGreen4 105 139 105 255 +DarkSlateBlue 72 61 139 255 +DarkSlateGray 47 79 79 255 +DarkSlateGray1 151 255 255 255 +DarkSlateGray2 141 238 238 255 +DarkSlateGray3 121 205 205 255 +DarkSlateGray4 82 139 139 255 +DarkSlateGrey 47 79 79 255 +DarkTurquoise 0 206 209 255 +DarkViolet 148 0 211 255 +DeepPink 255 20 147 255 +DeepPink1 255 20 147 255 +DeepPink2 238 18 137 255 +DeepPink3 205 16 118 255 +DeepPink4 139 10 80 255 +DeepSkyBlue 0 191 255 255 +DeepSkyBlue1 0 191 255 255 +DeepSkyBlue2 0 178 238 255 +DeepSkyBlue3 0 154 205 255 +DeepSkyBlue4 0 104 139 255 +DimGray 105 105 105 255 +DimGrey 105 105 105 255 +DodgerBlue 30 144 255 255 +DodgerBlue1 30 144 255 255 +DodgerBlue2 28 134 238 255 +DodgerBlue3 24 116 205 255 +DodgerBlue4 16 78 139 255 +FloralWhite 255 250 240 255 +ForestGreen 34 139 34 255 +GhostWhite 248 248 255 255 +GreenYellow 173 255 47 255 +HotPink 255 105 180 255 +HotPink1 255 110 180 255 +HotPink2 238 106 167 255 +HotPink3 205 96 144 255 +HotPink4 139 58 98 255 +IndianRed 205 92 92 255 +IndianRed1 255 106 106 255 +IndianRed2 238 99 99 255 +IndianRed3 205 85 85 255 +IndianRed4 139 58 58 255 +LavenderBlush 255 240 245 255 +LavenderBlush1 255 240 245 255 +LavenderBlush2 238 224 229 255 +LavenderBlush3 205 193 197 255 +LavenderBlush4 139 131 134 255 +LawnGreen 124 252 0 255 +LemonChiffon 255 250 205 255 +LemonChiffon1 255 250 205 255 +LemonChiffon2 238 233 191 255 +LemonChiffon3 205 201 165 255 +LemonChiffon4 139 137 112 255 +LightBlue 173 216 230 255 +LightBlue1 191 239 255 255 +LightBlue2 178 223 238 255 +LightBlue3 154 192 205 255 +LightBlue4 104 131 139 255 +LightCoral 240 128 128 255 +LightCyan 224 255 255 255 +LightCyan1 224 255 255 255 +LightCyan2 209 238 238 255 +LightCyan3 180 205 205 255 +LightCyan4 122 139 139 255 +LightGoldenrod 238 221 130 255 +LightGoldenrod1 255 236 139 255 +LightGoldenrod2 238 220 130 255 +LightGoldenrod3 205 190 112 255 +LightGoldenrod4 139 129 76 255 +LightGoldenrodYellow 250 250 210 255 +LightGray 211 211 211 255 +LightGreen 144 238 144 255 +LightGrey 211 211 211 255 +LightPink 255 182 193 255 +LightPink1 255 174 185 255 +LightPink2 238 162 173 255 +LightPink3 205 140 149 255 +LightPink4 139 95 101 255 +LightSalmon 255 160 122 255 +LightSalmon1 255 160 122 255 +LightSalmon2 238 149 114 255 +LightSalmon3 205 129 98 255 +LightSalmon4 139 87 66 255 +LightSeaGreen 32 178 170 255 +LightSkyBlue 135 206 250 255 +LightSkyBlue1 176 226 255 255 +LightSkyBlue2 164 211 238 255 +LightSkyBlue3 141 182 205 255 +LightSkyBlue4 96 123 139 255 +LightSlateBlue 132 112 255 255 +LightSlateGray 119 136 153 255 +LightSlateGrey 119 136 153 255 +LightSteelBlue 176 196 222 255 +LightSteelBlue1 202 225 255 255 +LightSteelBlue2 188 210 238 255 +LightSteelBlue3 162 181 205 255 +LightSteelBlue4 110 123 139 255 +LightYellow 255 255 224 255 +LightYellow1 255 255 224 255 +LightYellow2 238 238 209 255 +LightYellow3 205 205 180 255 +LightYellow4 139 139 122 255 +LimeGreen 50 205 50 255 +MediumAquamarine 102 205 170 255 +MediumBlue 0 0 205 255 +MediumOrchid 186 85 211 255 +MediumOrchid1 224 102 255 255 +MediumOrchid2 209 95 238 255 +MediumOrchid3 180 82 205 255 +MediumOrchid4 122 55 139 255 +MediumPurple 147 112 219 255 +MediumPurple1 171 130 255 255 +MediumPurple2 159 121 238 255 +MediumPurple3 137 104 205 255 +MediumPurple4 93 71 139 255 +MediumSeaGreen 60 179 113 255 +MediumSlateBlue 123 104 238 255 +MediumSpringGreen 0 250 154 255 +MediumTurquoise 72 209 204 255 +MediumVioletRed 199 21 133 255 +MidnightBlue 25 25 112 255 +MintCream 245 255 250 255 +MistyRose 255 228 225 255 +MistyRose1 255 228 225 255 +MistyRose2 238 213 210 255 +MistyRose3 205 183 181 255 +MistyRose4 139 125 123 255 +NavajoWhite 255 222 173 255 +NavajoWhite1 255 222 173 255 +NavajoWhite2 238 207 161 255 +NavajoWhite3 205 179 139 255 +NavajoWhite4 139 121 94 255 +NavyBlue 0 0 128 255 +OldLace 253 245 230 255 +OliveDrab 107 142 35 255 +OliveDrab1 192 255 62 255 +OliveDrab2 179 238 58 255 +OliveDrab3 154 205 50 255 +OliveDrab4 105 139 34 255 +OrangeRed 255 69 0 255 +OrangeRed1 255 69 0 255 +OrangeRed2 238 64 0 255 +OrangeRed3 205 55 0 255 +OrangeRed4 139 37 0 255 +PaleGoldenrod 238 232 170 255 +PaleGreen 152 251 152 255 +PaleGreen1 154 255 154 255 +PaleGreen2 144 238 144 255 +PaleGreen3 124 205 124 255 +PaleGreen4 84 139 84 255 +PaleTurquoise 175 238 238 255 +PaleTurquoise1 187 255 255 255 +PaleTurquoise2 174 238 238 255 +PaleTurquoise3 150 205 205 255 +PaleTurquoise4 102 139 139 255 +PaleVioletRed 219 112 147 255 +PaleVioletRed1 255 130 171 255 +PaleVioletRed2 238 121 159 255 +PaleVioletRed3 205 104 137 255 +PaleVioletRed4 139 71 93 255 +PapayaWhip 255 239 213 255 +PeachPuff 255 218 185 255 +PeachPuff1 255 218 185 255 +PeachPuff2 238 203 173 255 +PeachPuff3 205 175 149 255 +PeachPuff4 139 119 101 255 +PowderBlue 176 224 230 255 +RosyBrown 188 143 143 255 +RosyBrown1 255 193 193 255 +RosyBrown2 238 180 180 255 +RosyBrown3 205 155 155 255 +RosyBrown4 139 105 105 255 +RoyalBlue 65 105 225 255 +RoyalBlue1 72 118 255 255 +RoyalBlue2 67 110 238 255 +RoyalBlue3 58 95 205 255 +RoyalBlue4 39 64 139 255 +SaddleBrown 139 69 19 255 +SandyBrown 244 164 96 255 +SeaGreen 46 139 87 255 +SeaGreen1 84 255 159 255 +SeaGreen2 78 238 148 255 +SeaGreen3 67 205 128 255 +SeaGreen4 46 139 87 255 +SkyBlue 135 206 235 255 +SkyBlue1 135 206 255 255 +SkyBlue2 126 192 238 255 +SkyBlue3 108 166 205 255 +SkyBlue4 74 112 139 255 +SlateBlue 106 90 205 255 +SlateBlue1 131 111 255 255 +SlateBlue2 122 103 238 255 +SlateBlue3 105 89 205 255 +SlateBlue4 71 60 139 255 +SlateGray 112 128 144 255 +SlateGray1 198 226 255 255 +SlateGray2 185 211 238 255 +SlateGray3 159 182 205 255 +SlateGray4 108 123 139 255 +SlateGrey 112 128 144 255 +SpringGreen 0 255 127 255 +SpringGreen1 0 255 127 255 +SpringGreen2 0 238 118 255 +SpringGreen3 0 205 102 255 +SpringGreen4 0 139 69 255 +SteelBlue 70 130 180 255 +SteelBlue1 99 184 255 255 +SteelBlue2 92 172 238 255 +SteelBlue3 79 148 205 255 +SteelBlue4 54 100 139 255 +VioletRed 208 32 144 255 +VioletRed1 255 62 150 255 +VioletRed2 238 58 140 255 +VioletRed3 205 50 120 255 +VioletRed4 139 34 82 255 +WhiteSmoke 245 245 245 255 +YellowGreen 154 205 50 255 +alice 240 248 255 255 +antique 250 235 215 255 +aquamarine 127 255 212 255 +aquamarine1 127 255 212 255 +aquamarine2 118 238 198 255 +aquamarine3 102 205 170 255 +aquamarine4 69 139 116 255 +azure 240 255 255 255 +azure1 240 255 255 255 +azure2 224 238 238 255 +azure3 193 205 205 255 +azure4 131 139 139 255 +beige 245 245 220 255 +bisque 255 228 196 255 +bisque1 255 228 196 255 +bisque2 238 213 183 255 +bisque3 205 183 158 255 +bisque4 139 125 107 255 +black 0 0 0 255 +blanched 255 235 205 255 +blue 138 43 226 255 +blue 0 0 255 255 +blue1 0 0 255 255 +blue2 0 0 238 255 +blue3 0 0 205 255 +blue4 0 0 139 255 +brown 165 42 42 255 +brown1 255 64 64 255 +brown2 238 59 59 255 +brown3 205 51 51 255 +brown4 139 35 35 255 +burlywood 222 184 135 255 +burlywood1 255 211 155 255 +burlywood2 238 197 145 255 +burlywood3 205 170 125 255 +burlywood4 139 115 85 255 +cadet 95 158 160 255 +chartreuse 127 255 0 255 +chartreuse1 127 255 0 255 +chartreuse2 118 238 0 255 +chartreuse3 102 205 0 255 +chartreuse4 69 139 0 255 +chocolate 210 105 30 255 +chocolate1 255 127 36 255 +chocolate2 238 118 33 255 +chocolate3 205 102 29 255 +chocolate4 139 69 19 255 +coral 255 127 80 255 +coral1 255 114 86 255 +coral2 238 106 80 255 +coral3 205 91 69 255 +coral4 139 62 47 255 +cornflower 100 149 237 255 +cornsilk 255 248 220 255 +cornsilk1 255 248 220 255 +cornsilk2 238 232 205 255 +cornsilk3 205 200 177 255 +cornsilk4 139 136 120 255 +cyan 0 255 255 255 +cyan1 0 255 255 255 +cyan2 0 238 238 255 +cyan3 0 205 205 255 +cyan4 0 139 139 255 +dark 72 61 139 255 +dark 0 100 0 255 +deep 255 20 147 255 +deep 0 191 255 255 +dim 105 105 105 255 +dim 105 105 105 255 +dodger 30 144 255 255 +firebrick 178 34 34 255 +firebrick1 255 48 48 255 +firebrick2 238 44 44 255 +firebrick3 205 38 38 255 +firebrick4 139 26 26 255 +floral 255 250 240 255 +forest 34 139 34 255 +gainsboro 220 220 220 255 +ghost 248 248 255 255 +gold 255 215 0 255 +gold1 255 215 0 255 +gold2 238 201 0 255 +gold3 205 173 0 255 +gold4 139 117 0 255 +goldenrod 218 165 32 255 +goldenrod1 255 193 37 255 +goldenrod2 238 180 34 255 +goldenrod3 205 155 29 255 +goldenrod4 139 105 20 255 +gray 190 190 190 255 +gray0 0 0 0 255 +gray1 3 3 3 255 +gray10 26 26 26 255 +gray100 255 255 255 255 +gray11 28 28 28 255 +gray12 31 31 31 255 +gray13 33 33 33 255 +gray14 36 36 36 255 +gray15 38 38 38 255 +gray16 41 41 41 255 +gray17 43 43 43 255 +gray18 46 46 46 255 +gray19 48 48 48 255 +gray2 5 5 5 255 +gray20 51 51 51 255 +gray21 54 54 54 255 +gray22 56 56 56 255 +gray23 59 59 59 255 +gray24 61 61 61 255 +gray25 64 64 64 255 +gray26 66 66 66 255 +gray27 69 69 69 255 +gray28 71 71 71 255 +gray29 74 74 74 255 +gray3 8 8 8 255 +gray30 77 77 77 255 +gray31 79 79 79 255 +gray32 82 82 82 255 +gray33 84 84 84 255 +gray34 87 87 87 255 +gray35 89 89 89 255 +gray36 92 92 92 255 +gray37 94 94 94 255 +gray38 97 97 97 255 +gray39 99 99 99 255 +gray4 10 10 10 255 +gray40 102 102 102 255 +gray41 105 105 105 255 +gray42 107 107 107 255 +gray43 110 110 110 255 +gray44 112 112 112 255 +gray45 115 115 115 255 +gray46 117 117 117 255 +gray47 120 120 120 255 +gray48 122 122 122 255 +gray49 125 125 125 255 +gray5 13 13 13 255 +gray50 127 127 127 255 +gray51 130 130 130 255 +gray52 133 133 133 255 +gray53 135 135 135 255 +gray54 138 138 138 255 +gray55 140 140 140 255 +gray56 143 143 143 255 +gray57 145 145 145 255 +gray58 148 148 148 255 +gray59 150 150 150 255 +gray6 15 15 15 255 +gray60 153 153 153 255 +gray61 156 156 156 255 +gray62 158 158 158 255 +gray63 161 161 161 255 +gray64 163 163 163 255 +gray65 166 166 166 255 +gray66 168 168 168 255 +gray67 171 171 171 255 +gray68 173 173 173 255 +gray69 176 176 176 255 +gray7 18 18 18 255 +gray70 179 179 179 255 +gray71 181 181 181 255 +gray72 184 184 184 255 +gray73 186 186 186 255 +gray74 189 189 189 255 +gray75 191 191 191 255 +gray76 194 194 194 255 +gray77 196 196 196 255 +gray78 199 199 199 255 +gray79 201 201 201 255 +gray8 20 20 20 255 +gray80 204 204 204 255 +gray81 207 207 207 255 +gray82 209 209 209 255 +gray83 212 212 212 255 +gray84 214 214 214 255 +gray85 217 217 217 255 +gray86 219 219 219 255 +gray87 222 222 222 255 +gray88 224 224 224 255 +gray89 227 227 227 255 +gray9 23 23 23 255 +gray90 229 229 229 255 +gray91 232 232 232 255 +gray92 235 235 235 255 +gray93 237 237 237 255 +gray94 240 240 240 255 +gray95 242 242 242 255 +gray96 245 245 245 255 +gray97 247 247 247 255 +gray98 250 250 250 255 +gray99 252 252 252 255 +green 173 255 47 255 +green 0 255 0 255 +green1 0 255 0 255 +green2 0 238 0 255 +green3 0 205 0 255 +green4 0 139 0 255 +grey 190 190 190 255 +grey0 0 0 0 255 +grey1 3 3 3 255 +grey10 26 26 26 255 +grey100 255 255 255 255 +grey11 28 28 28 255 +grey12 31 31 31 255 +grey13 33 33 33 255 +grey14 36 36 36 255 +grey15 38 38 38 255 +grey16 41 41 41 255 +grey17 43 43 43 255 +grey18 46 46 46 255 +grey19 48 48 48 255 +grey2 5 5 5 255 +grey20 51 51 51 255 +grey21 54 54 54 255 +grey22 56 56 56 255 +grey23 59 59 59 255 +grey24 61 61 61 255 +grey25 64 64 64 255 +grey26 66 66 66 255 +grey27 69 69 69 255 +grey28 71 71 71 255 +grey29 74 74 74 255 +grey3 8 8 8 255 +grey30 77 77 77 255 +grey31 79 79 79 255 +grey32 82 82 82 255 +grey33 84 84 84 255 +grey34 87 87 87 255 +grey35 89 89 89 255 +grey36 92 92 92 255 +grey37 94 94 94 255 +grey38 97 97 97 255 +grey39 99 99 99 255 +grey4 10 10 10 255 +grey40 102 102 102 255 +grey41 105 105 105 255 +grey42 107 107 107 255 +grey43 110 110 110 255 +grey44 112 112 112 255 +grey45 115 115 115 255 +grey46 117 117 117 255 +grey47 120 120 120 255 +grey48 122 122 122 255 +grey49 125 125 125 255 +grey5 13 13 13 255 +grey50 127 127 127 255 +grey51 130 130 130 255 +grey52 133 133 133 255 +grey53 135 135 135 255 +grey54 138 138 138 255 +grey55 140 140 140 255 +grey56 143 143 143 255 +grey57 145 145 145 255 +grey58 148 148 148 255 +grey59 150 150 150 255 +grey6 15 15 15 255 +grey60 153 153 153 255 +grey61 156 156 156 255 +grey62 158 158 158 255 +grey63 161 161 161 255 +grey64 163 163 163 255 +grey65 166 166 166 255 +grey66 168 168 168 255 +grey67 171 171 171 255 +grey68 173 173 173 255 +grey69 176 176 176 255 +grey7 18 18 18 255 +grey70 179 179 179 255 +grey71 181 181 181 255 +grey72 184 184 184 255 +grey73 186 186 186 255 +grey74 189 189 189 255 +grey75 191 191 191 255 +grey76 194 194 194 255 +grey77 196 196 196 255 +grey78 199 199 199 255 +grey79 201 201 201 255 +grey8 20 20 20 255 +grey80 204 204 204 255 +grey81 207 207 207 255 +grey82 209 209 209 255 +grey83 212 212 212 255 +grey84 214 214 214 255 +grey85 217 217 217 255 +grey86 219 219 219 255 +grey87 222 222 222 255 +grey88 224 224 224 255 +grey89 227 227 227 255 +grey9 23 23 23 255 +grey90 229 229 229 255 +grey91 232 232 232 255 +grey92 235 235 235 255 +grey93 237 237 237 255 +grey94 240 240 240 255 +grey95 242 242 242 255 +grey96 245 245 245 255 +grey97 247 247 247 255 +grey98 250 250 250 255 +grey99 252 252 252 255 +honeydew 240 255 240 255 +honeydew1 240 255 240 255 +honeydew2 224 238 224 255 +honeydew3 193 205 193 255 +honeydew4 131 139 131 255 +hot 255 105 180 255 +indian 205 92 92 255 +ivory 255 255 240 255 +ivory1 255 255 240 255 +ivory2 238 238 224 255 +ivory3 205 205 193 255 +ivory4 139 139 131 255 +khaki 240 230 140 255 +khaki1 255 246 143 255 +khaki2 238 230 133 255 +khaki3 205 198 115 255 +khaki4 139 134 78 255 +lavender 230 230 250 255 +lavender 255 240 245 255 +lawn 124 252 0 255 +lemon 255 250 205 255 +light 238 221 130 255 +lime 50 205 50 255 +linen 250 240 230 255 +magenta 255 0 255 255 +magenta1 255 0 255 255 +magenta2 238 0 238 255 +magenta3 205 0 205 255 +magenta4 139 0 139 255 +maroon 176 48 96 255 +maroon1 255 52 179 255 +maroon2 238 48 167 255 +maroon3 205 41 144 255 +maroon4 139 28 98 255 +medium 0 0 205 255 +medium 186 85 211 255 +medium 0 250 154 255 +medium 199 21 133 255 +medium 72 209 204 255 +medium 102 205 170 255 +medium 60 179 113 255 +medium 123 104 238 255 +medium 147 112 219 255 +midnight 25 25 112 255 +mint 245 255 250 255 +misty 255 228 225 255 +moccasin 255 228 181 255 +navajo 255 222 173 255 +navy 0 0 128 255 +navy 0 0 128 255 +old 253 245 230 255 +olive 107 142 35 255 +orange 255 69 0 255 +orange 255 165 0 255 +orange1 255 165 0 255 +orange2 238 154 0 255 +orange3 205 133 0 255 +orange4 139 90 0 255 +orchid 218 112 214 255 +orchid1 255 131 250 255 +orchid2 238 122 233 255 +orchid3 205 105 201 255 +orchid4 139 71 137 255 +pale 175 238 238 255 +pale 152 251 152 255 +pale 219 112 147 255 +pale 238 232 170 255 +papaya 255 239 213 255 +peach 255 218 185 255 +peru 205 133 63 255 +pink 255 192 203 255 +pink1 255 181 197 255 +pink2 238 169 184 255 +pink3 205 145 158 255 +pink4 139 99 108 255 +plum 221 160 221 255 +plum1 255 187 255 255 +plum2 238 174 238 255 +plum3 205 150 205 255 +plum4 139 102 139 255 +powder 176 224 230 255 +purple 160 32 240 255 +purple1 155 48 255 255 +purple2 145 44 238 255 +purple3 125 38 205 255 +purple4 85 26 139 255 +red 255 0 0 255 +red1 255 0 0 255 +red2 238 0 0 255 +red3 205 0 0 255 +red4 139 0 0 255 +rosy 188 143 143 255 +royal 65 105 225 255 +saddle 139 69 19 255 +salmon 250 128 114 255 +salmon1 255 140 105 255 +salmon2 238 130 98 255 +salmon3 205 112 84 255 +salmon4 139 76 57 255 +sandy 244 164 96 255 +sea 46 139 87 255 +seashell 255 245 238 255 +seashell1 255 245 238 255 +seashell2 238 229 222 255 +seashell3 205 197 191 255 +seashell4 139 134 130 255 +sienna 160 82 45 255 +sienna1 255 130 71 255 +sienna2 238 121 66 255 +sienna3 205 104 57 255 +sienna4 139 71 38 255 +sky 135 206 235 255 +slate 112 128 144 255 +slate 112 128 144 255 +slate 106 90 205 255 +snow 255 250 250 255 +snow1 255 250 250 255 +snow2 238 233 233 255 +snow3 205 201 201 255 +snow4 139 137 137 255 +spring 0 255 127 255 +steel 70 130 180 255 +tan 210 180 140 255 +tan1 255 165 79 255 +tan2 238 154 73 255 +tan3 205 133 63 255 +tan4 139 90 43 255 +thistle 216 191 216 255 +thistle1 255 225 255 255 +thistle2 238 210 238 255 +thistle3 205 181 205 255 +thistle4 139 123 139 255 +tomato 255 99 71 255 +tomato1 255 99 71 255 +tomato2 238 92 66 255 +tomato3 205 79 57 255 +tomato4 139 54 38 255 +turquoise 64 224 208 255 +turquoise1 0 245 255 255 +turquoise2 0 229 238 255 +turquoise3 0 197 205 255 +turquoise4 0 134 139 255 +violet 208 32 144 255 +violet 238 130 238 255 +wheat 245 222 179 255 +wheat1 255 231 186 255 +wheat2 238 216 174 255 +wheat3 205 186 150 255 +wheat4 139 126 102 255 +white 255 255 255 255 +white 245 245 245 255 +yellow 255 255 0 255 +yellow 154 205 50 255 +yellow1 255 255 0 255 +yellow2 238 238 0 255 +yellow3 205 205 0 255 +yellow4 139 139 0 255 \ No newline at end of file diff --git a/kernel/kls_xpm/xpm_utils.h b/kernel/kls_xpm/xpm_utils.h new file mode 100644 index 0000000..d44b2e9 --- /dev/null +++ b/kernel/kls_xpm/xpm_utils.h @@ -0,0 +1,103 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include + +#define KEY_LENGTH 25 + +RGBA fmt_codec::hex2rgb(const s8 *hex) +{ + RGBA rgba; + s8 c[3]; + const s8 add = (const s8)strlen(hex+1) / 3 - 2; + + if(!strncasecmp(hex, "none", 4) || !strncasecmp(hex, "one", 3)) // not pretty hack + { + memset(&rgba, 0, sizeof(RGBA)); + return rgba; + } + + if(isalpha(*hex)) + { + RGBA trgba; + bool f;// = BinSearch(named, 0, sizeof(named) / sizeof(XPM_NAMED_COLOR) - 1, hex); + + std::map::const_iterator it = named.find(hex); + + f = (it != named.end()); + + if(!f) + { + cerr << "XPM decoder: WARNING: named color \"" << hex << "\" not found, assuming transparent instead" << endl; + memset(&rgba, 0, sizeof(RGBA)); + return rgba; + } + + trgba = named[std::string(hex)]; + + return trgba; + } + + hex++; + + memcpy(c, hex, 2); + c[2] = 0; + rgba.r = (s8)strtol(c, NULL, 16); + hex = hex + 2 + add; + + memcpy(c, hex, 2); + c[2] = 0; + rgba.g = (s8)strtol(c, NULL, 16); + hex = hex + 2 + add; + + memcpy(c, hex, 2); + c[2] = 0; + rgba.b = (s8)strtol(c, NULL, 16); + + rgba.a = 255; + + return rgba; +} + +/* skip a single line C-like comment */ +s32 skip_comments(ifstreamK &ff) +{ + s8 str[4096]; + fstream::pos_type pos; + bool skipped = false; + + pos = ff.tellg(); + + ff.getline(str, sizeof(str)-1); + + if(ff.eof()) return 2; + + if((*str == '\n' && *(str+1) == '\0') || (*str == '\n' && *(str+1) == '\r' && *(str+2) == '\0') || (*str == '\r' && *(str+1) == '\n' && *(str+2) == '\0')) + skipped = true; + + if(strstr(str, "/*") || *str == '#' || !strlen(str)) + skipped = true; + + if(!skipped) + ff.seekg(pos); + + return (int)skipped; +} diff --git a/kernel/kls_xwd/Makefile.am b/kernel/kls_xwd/Makefile.am new file mode 100644 index 0000000..9815d7d --- /dev/null +++ b/kernel/kls_xwd/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I../include + +pkglib_LTLIBRARIES = libkls_xwd.la + +libkls_xwd_la_SOURCES = fmt_codec_xwd.cpp fmt_codec_xwd_defs.h + +libkls_xwd_la_LDFLAGS = ${SQ_RELEASE} + +libkls_xwd_la_LIBADD = ${SQ_LOCAL_RPATH} diff --git a/kernel/kls_xwd/fmt_codec_xwd.cpp b/kernel/kls_xwd/fmt_codec_xwd.cpp new file mode 100644 index 0000000..0ba5226 --- /dev/null +++ b/kernel/kls_xwd/fmt_codec_xwd.cpp @@ -0,0 +1,214 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +#include "ksquirrel-libs/fmt_types.h" +#include "ksquirrel-libs/fmt_utils.h" +#include "ksquirrel-libs/fileio.h" +#include "ksquirrel-libs/error.h" + +#include "fmt_codec_xwd_defs.h" +#include "fmt_codec_xwd.h" + +#include "../xpm/codec_xwd.xpm" + +/* + * + * The XWD (X Window Dump) format is used specifically to store screen + * dumps + * + * Created by the X Window System. Under X11, screen dumps are created by the + * xwd client. Using xwd, the window or background is selected to + * dump and an XWD file is produced containing an image of the window. If you + * issue the following command: + * + * $ xwd -root > output.xwd + * + */ + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.4.3"; + o->name = "X Window Dump"; + o->filter = "*.xwd "; + o->config = ""; + o->mime = ""; + o->mimetype = "image/x-xwd"; + o->pixmap = codec_xwd; + o->readable = true; + o->canbemultiple = false; + o->writestatic = false; + o->writeanimated = false; + o->needtempfile = false; +} + +s32 fmt_codec::read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQE_R_NOFILE; + + currentImage = -1; + pal = NULL; + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + XWDFileHeader xfh; + + currentImage++; + + if(currentImage) + return SQE_NOTOK; + + fmt_image image; + + XWDColor color; + s8 str[256]; + s32 i, ncolors; + + if(!frs.readK(&xfh, sizeof(XWDFileHeader))) return SQE_R_BADFILE; + + xfh.file_version = fmt_utils::konvertLong(xfh.file_version); + + if(xfh.file_version != XWD_FILE_VERSION) + return SQE_R_BADFILE; + + frs.get(str, 255, '\n'); + + frs.clear(); + + frs.seekg(fmt_utils::konvertLong(xfh.header_size), ios::beg); + + pal_entr = ncolors = fmt_utils::konvertLong(xfh.ncolors); + + pal = new RGB [ncolors]; + + if(!pal) + return SQE_R_NOMEMORY; + + for(i = 0;i < ncolors;i++) + { + if(!frs.readK(&color, sizeof(XWDColor))) return SQE_R_BADFILE; + + pal[i].r = (s8)fmt_utils::konvertWord(color.red); + pal[i].g = (s8)fmt_utils::konvertWord(color.green); + pal[i].b = (s8)fmt_utils::konvertWord(color.blue); + } + + image.w = fmt_utils::konvertLong(xfh.pixmap_width); + image.h = fmt_utils::konvertLong(xfh.pixmap_height); + image.bpp = fmt_utils::konvertLong(xfh.bits_per_pixel);//fmt_utils::konvertLong(xfh.pixmap_depth); + + if(image.bpp != 24 && image.bpp != 32) + return SQE_R_NOTSUPPORTED; + + fmt_metaentry mt; + + mt.group = "Window Name"; + mt.data = str; + + addmeta(mt); + + image.compression = "-"; + image.colorspace = "RGB"; + + filler = fmt_utils::konvertLong(xfh.bytes_per_line) - image.w * image.bpp / 8; + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + s32 i; + RGBA rgba; + RGB rgb; + u8 d; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + switch(im->bpp) + { + case 24: + for(i = 0;i < im->w;i++) + { + if(!frs.readK(&rgb, sizeof(RGB))) return SQE_R_BADFILE; + + memcpy(scan+i, &rgb, sizeof(RGB)); + } + + for(s32 s = 0;s < filler;s++) + if(!frs.readK(&d, 1)) + return SQE_R_BADFILE; + break; + + case 32: + for(i = 0;i < im->w;i++) + { + if(!frs.readK(&rgba, sizeof(RGBA))) return SQE_R_BADFILE; + + scan[i].r = rgba.b; + scan[i].g = rgba.g; + scan[i].b = rgba.r; + } + + for(s32 s = 0;s < filler;s++) + if(!frs.readK(&d, 1)) + return SQE_R_BADFILE; + break; + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + frs.close(); + + delete [] pal; + pal = NULL; + + finfo.meta.clear(); + finfo.image.clear(); +} + +#include "fmt_codec_cd_func.h" diff --git a/kernel/kls_xwd/fmt_codec_xwd_defs.h b/kernel/kls_xwd/fmt_codec_xwd_defs.h new file mode 100644 index 0000000..1211f14 --- /dev/null +++ b/kernel/kls_xwd/fmt_codec_xwd_defs.h @@ -0,0 +1,27 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + as32 with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSQUIRREL_READ_IMAGE_xwd +#define KSQUIRREL_READ_IMAGE_xwd + +#include + +#endif diff --git a/kernel/ksquirrel-libs/Makefile.am b/kernel/ksquirrel-libs/Makefile.am new file mode 100644 index 0000000..54258cb --- /dev/null +++ b/kernel/ksquirrel-libs/Makefile.am @@ -0,0 +1,8 @@ +INCLUDES = -I../include + +# create small development library. KSquirrel will use it. +lib_LTLIBRARIES = libksquirrel-libs.la + +libksquirrel_libs_la_SOURCES = fileio.cpp fmt_utils.cpp + +libksquirrel_libs_la_LDFLAGS = ${SQ_RELEASE} \ No newline at end of file diff --git a/kernel/ksquirrel-libs/fileio.cpp b/kernel/ksquirrel-libs/fileio.cpp new file mode 100644 index 0000000..b7cea5c --- /dev/null +++ b/kernel/ksquirrel-libs/fileio.cpp @@ -0,0 +1,136 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#include +#include + +#include "ksquirrel-libs/fileio.h" + +// implement read methods +ifstreamK::ifstreamK() : ifstream() +{} + +bool ifstreamK::readK(void *data, int size) +{ + read((char *)data, size); + + return good(); +} + +bool ifstreamK::getS(char *s, const int sz) +{ + getline(s, sz); + + return good(); +} + +bool ifstreamK::be_getchar(u8 *c) +{ + return readK(c, 1); +} + +bool ifstreamK::be_getshort(u16 *s) +{ + u8 buf[2]; + + if(!readK(buf, 2)) + return false; + + *s = (buf[0] << 8) + buf[1]; + + return good(); +} + +bool ifstreamK::be_getlong(u32 *l) +{ + u8 buf[4]; + + if(!readK(buf, 4)) + return false; + + *l = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + (buf[3]); + + return good(); +} + +void ifstreamK::close() +{ + ifstream::close(); + + clear(); +} + +bool ifstreamK::readCHex(u32 &hex) +{ + s8 prefix1, prefix2; + s8 h[9], c; + u32 i = 0; + + if(!readK(&prefix1, sizeof(s8))) + return false; + + if(!readK(&prefix2, sizeof(s8))) + return false; + + if(prefix1 != '0' || prefix2 != 'x') + return false; + + while(true) + { + if(!readK(&c, sizeof(s8))) + return false; + + if(c < '0' || c > '9') + { + if(c != 'A' && c != 'B' && c != 'C' && c != 'D' && c != 'E' && c != 'F') + { + seekg(-1, ios::cur); + break; + } + } + + h[i++] = c; + } + + h[i] = '\0'; + + hex = strtol(h, NULL, 16); + + return good(); +} + + +// implement write methods +ofstreamK::ofstreamK() : ofstream() +{} + +bool ofstreamK::writeK(void *data, int size) +{ + write((char *)data, size); + + return good(); +} + +void ofstreamK::close() +{ + ofstream::close(); + + clear(); +} diff --git a/kernel/ksquirrel-libs/fmt_utils.cpp b/kernel/ksquirrel-libs/fmt_utils.cpp new file mode 100644 index 0000000..306fee9 --- /dev/null +++ b/kernel/ksquirrel-libs/fmt_utils.cpp @@ -0,0 +1,187 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2004 Dmitry Baryshev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#include +#include + +#include "ksquirrel-libs/fmt_utils.h" +#include "ksquirrel-libs/fmt_defs.h" + +#include + +void fmt_utils::fillAlpha(RGBA *scan, int w, u8 value) +{ + if(scan) + { + for(int i = 0;i < w;i++) + (scan + i)->a = value; + } +} + +void fmt_utils::flipv(s8 *image, s32 bytes_w, s32 h) +{ + s32 i; + + if(!image) + return; + + s8 *hptr = new s8 [bytes_w]; + + if(!hptr) + return; + + for(i = 0; i < h/2; i++) + { + memcpy(hptr, image + i * bytes_w, bytes_w); + memcpy(image + i * bytes_w, image + (h - i - 1) * bytes_w, bytes_w); + memcpy(image + (h - i - 1) * bytes_w, hptr, bytes_w); + } + + delete hptr; +} + +void fmt_utils::fliph(s8 *image, s32 w, s32 h, s32 bpp) +{ + s32 x, y, x2; + s32 bpl = w * bpp; + s8 a[bpp], *t; + + if(!image) + return; + + for(y = 0;y < h;y++) + { + for(x = 0, x2 = w-1;x < w/2;x++,x2--) + { + t = image + y*bpl; + + memcpy(a, t + x2*bpp, bpp); + memcpy(t + x2*bpp, t + x*bpp, bpp); + memcpy(t + x*bpp, a, bpp); + } + } +} + +u16 fmt_utils::konvertWord(u16 a) +{ + u16 i = a, b; + + b = i & 255; + b = b << 8; + b = b|0; + i = i >> 8; + i = i|0; + + return i|b; +} + +u32 fmt_utils::konvertLong(u32 a) +{ + u32 i = a, b, c; + u16 m, n; + + b = i >> 16; // high word + c = i << 16; + c = c >> 16; // low word + + m = (u16)b; + n = (u16)c; + + m = fmt_utils::konvertWord(m); + n = fmt_utils::konvertWord(n); + + b = m; + c = n; + c = c << 16; + + b = b|0; + c = c|0; + + return b|c; +} + +std::string fmt_utils::colorSpaceByBpp(const int bpp) +{ + switch(bpp) + { + case 1: + return std::string("Monochrome"); + + case 4: + case 8: + case 15: + case 16: + return std::string("Color indexed"); + + case 24: + return std::string("RGB"); + + case 32: + return std::string("RGBA"); + + default: + return std::string("Unknown"); + } +} + +void fmt_utils::expandMono1Byte(const u32 byte, u8 *array) +{ + u8 mask = 0x80; + u8 *p = array; + u8 b = byte & 0xff; + + for(s32 i = 0;i < 8;i++) + { + *p = (b & mask) ? 1 : 0; + + p++; + mask >>= 1; + } +} + +void fmt_utils::expandMono2Byte(const u32 byte, u8 *array) +{ + u16 mask = 0x8000; + u8 *p = array; + u16 b = byte & 0xffff; + + for(s32 i = 0;i < 16;i++) + { + *p = (b & mask) ? 1 : 0; + + p++; + mask >>= 1; + } +} + +void fmt_utils::expandMono4Byte(const u32 byte, u8 *array) +{ + u32 mask = 0x80000000; + u8 *p = array; + u32 b = byte & 0xffffffff; + + for(s32 i = 0;i < 32;i++) + { + *p = (b & mask) ? 1 : 0; + + p++; + mask >>= 1; + } +} diff --git a/kernel/link b/kernel/link new file mode 100755 index 0000000..9256b03 --- /dev/null +++ b/kernel/link @@ -0,0 +1,24 @@ +#!/bin/sh + +# create symlinks from all codecs (bmp/.libs/libkls_bmp.so, ...) +# to /usr/lib/ksquirrel-libs/ +# +# Can be used by developers +# +# Usage: +# $ cd ksquirrel-libs/kernel/ +# $ ./link +# + +KSQUIRREL_LIBS="/usr/lib/ksquirrel-libs/" + +rm -f $KSQUIRREL_LIBS/* + +mkdir $KSQUIRREL_LIBS > /dev/null 2>&1 + +for i in avs bmp camera cut dds dicom eps fli gif hdr ico iff fig jbig jpeg jpeg2000 koala ljpeg lif mac mdl mng msp mtv openexr pcx pix png pnm psd psp pxr ras rawrgb sct sgi sun svg tga tiff ttf utah wal wbmp wmf xbm xcur xpm xwd djvu dxf xcf neo leaf pi1 pi3 xim pict; +do echo "Linking libkls_$i.so ..." && ln -s `pwd`/kls_$i/.libs/libkls_$i.so $KSQUIRREL_LIBS; +done + +rm -f /usr/lib/libksquirrel-libs.so +ln -s `pwd`/ksquirrel-libs/.libs/libksquirrel-libs.so /usr/lib diff --git a/kernel/plusx b/kernel/plusx new file mode 100755 index 0000000..4d26ba8 --- /dev/null +++ b/kernel/plusx @@ -0,0 +1,3 @@ +#!/bin/sh + +for i in /usr/bin/ksquirrel-libs-*; do chmod +x $i; done \ No newline at end of file diff --git a/kernel/xpm/codec_avs.xpm b/kernel/xpm/codec_avs.xpm new file mode 100644 index 0000000..c80bd7c --- /dev/null +++ b/kernel/xpm/codec_avs.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_avs[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #020202", +". c #464646", +"X c #4E4E4E", +"o c #CF0008", +"O c #9EFE02", +"+ c #AEAEAE", +"@ c #B2B2B2", +"# c #CACACA", +"$ c gray87", +"% c gray95", +"& c #FEFEFE", +"* c None", +/* pixels */ +"XXXXXXXXXX@*****", +"X########X$+****", +"X#&&&&&&#X%$@***", +"X#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"X...............", +"XOOOOOOOOOOOOOO.", +"XO O OO O O.", +"XO O O OO O OOO.", +"XO O OO O O.", +"XO O O OOO O.", +"XO O OO OO O.", +"XOOOOOOOOOOOOOO.", +"X...............", +"X###########X***", +"*XXXXXXXXXXXX***" +}; diff --git a/kernel/xpm/codec_bmp.xpm b/kernel/xpm/codec_bmp.xpm new file mode 100644 index 0000000..8048e2b --- /dev/null +++ b/kernel/xpm/codec_bmp.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_bmp[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #3F3FBA", +"o c #CF0008", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".XXXXXXXXXXXXXX ", +".X&&&X&XX&X&&&X ", +".X&X&X&&&&X&X&X ", +".X&&&X&XX&X&&&X ", +".X&X&X&XX&X&XXX ", +".X&&&X&XX&X&XXX ", +".XXXXXXXXXXXXXX ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_camera.xpm b/kernel/xpm/codec_camera.xpm new file mode 100644 index 0000000..56f1cc6 --- /dev/null +++ b/kernel/xpm/codec_camera.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_camera[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #CF0008", +"o c #FF00A4", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".oooooooooooooo ", +".o&&&oo&oo&oo&o ", +".o&o&o&&&o&&&&o ", +".o&ooo&o&o&oo&o ", +".o&o&o&&&o&oo&o ", +".o&&&o&o&o&oo&o ", +".oooooooooooooo ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_cut.xpm b/kernel/xpm/codec_cut.xpm new file mode 100644 index 0000000..c3f6c28 --- /dev/null +++ b/kernel/xpm/codec_cut.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_cut[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #CF0008", +"o c #842FA3", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".oooooooooooooo ", +".oo&&oo&o&o&&&o ", +".o&oo&o&o&oo&oo ", +".o&oooo&o&oo&oo ", +".o&oo&o&o&oo&oo ", +".oo&&oo&&&oo&oo ", +".oooooooooooooo ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_dds.xpm b/kernel/xpm/codec_dds.xpm new file mode 100644 index 0000000..8dcdb37 --- /dev/null +++ b/kernel/xpm/codec_dds.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char * codec_dds[] = { +"16 16 11 1", +" c None", +". c #4E4E4E", +"+ c #B2B2B2", +"@ c #CACACA", +"# c #DEDEDE", +"$ c #AEAEAE", +"% c #FEFEFE", +"& c #F2F2F2", +"* c #464646", +"= c #F389FA", +"- c #000000", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".=--==--==---==*", +".=-=-=-=-=-====*", +".=-=-=-=-=---==*", +".=-=-=-=-===-==*", +".=--==--==---==*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_dicom.xpm b/kernel/xpm/codec_dicom.xpm new file mode 100644 index 0000000..48f7106 --- /dev/null +++ b/kernel/xpm/codec_dicom.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char * codec_dicom[] = { +"16 16 11 1", +" c None", +". c #4E4E4E", +"+ c #B2B2B2", +"@ c #CACACA", +"# c #DEDEDE", +"$ c #AEAEAE", +"% c #FEFEFE", +"& c #F2F2F2", +"* c #464646", +"= c #D8FC0F", +"- c #000000", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".=--==---=-==-=*", +".=-=-=-===----=*", +".=-=-=-===-==-=*", +".=-=-=-===-==-=*", +".=--==---=-==-=*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_djvu.xpm b/kernel/xpm/codec_djvu.xpm new file mode 100644 index 0000000..4fcfbae --- /dev/null +++ b/kernel/xpm/codec_djvu.xpm @@ -0,0 +1,31 @@ +/* XPM */ +static const char *codec_djvu[] = { +"16 16 12 1", +" c None", +". c #4E4E4E", +"+ c #B2B2B2", +"@ c #CACACA", +"# c #DEDEDE", +"$ c #AEAEAE", +"% c #FEFEFE", +"& c #F2F2F2", +"* c #464646", +"= c #35C3E7", +"- c #FFFFFF", +"; c #D9F3FA", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".=---==---=-=-=*", +".=-=--===-=-=-=*", +".=-==-===-=-=-=*", +".=-=--===-=-=-=*", +".=---==--;=;-;=*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_dxf.xpm b/kernel/xpm/codec_dxf.xpm new file mode 100644 index 0000000..86463ee --- /dev/null +++ b/kernel/xpm/codec_dxf.xpm @@ -0,0 +1,36 @@ +/* XPM */ +static const char *codec_dxf[] = { +"16 16 17 1", +" c None", +". c #4E4E4E", +"+ c #B2B2B2", +"@ c #CACACA", +"# c #DEDEDE", +"$ c #AEAEAE", +"% c #FEFEFE", +"& c #F2F2F2", +"* c #464646", +"= c #C69DC1", +"- c #C69CC1", +"; c #C69BC1", +"> c #C69AC1", +", c #C699C1", +"' c #C698C1", +") c #C698C2", +"! c #FFFFFF", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".=--;;>>,''))))*", +".)!!!))!)!)!!!)*", +".)!)!!)!)!)!)))*", +".)!))!))!))!!!)*", +".)!)!!)!)!)!)))*", +".)!!!))!)!)!)))*", +".))))))))))))))*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_eps.xpm b/kernel/xpm/codec_eps.xpm new file mode 100644 index 0000000..8715b8c --- /dev/null +++ b/kernel/xpm/codec_eps.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char *codec_eps[] = { +"16 16 11 1", +" c None", +". c #4E4E4E", +"+ c #B2B2B2", +"@ c #CACACA", +"# c #DEDEDE", +"$ c #AEAEAE", +"% c #FEFEFE", +"& c #F2F2F2", +"* c #464646", +"= c #EC23B1", +"- c #000000", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".=---=---=---==*", +".=-===-=-=-====*", +".=--==---=---==*", +".=-===-=====-==*", +".=---=-===---==*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_fig.xpm b/kernel/xpm/codec_fig.xpm new file mode 100644 index 0000000..0b3777d --- /dev/null +++ b/kernel/xpm/codec_fig.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char * codec_fig[] = { +"16 16 11 1", +" c None", +". c #4C4C4C", +"+ c #B0B0B0", +"@ c #C8C8C8", +"# c #DDDDDD", +"$ c #AEAEAE", +"% c #FFFFFF", +"& c #F3F3F3", +"* c #454545", +"= c #555353", +"- c #EDFF23", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".=-=-=---=----=*", +".=-=-=-===-====*", +".==-==---=-=--=*", +".=-=-=-===-==-=*", +".=-=-=-===----=*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_fits.xpm b/kernel/xpm/codec_fits.xpm new file mode 100644 index 0000000..dbbd69f --- /dev/null +++ b/kernel/xpm/codec_fits.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char * codec_fits[] = { +"16 16 11 1", +" c None", +". c #4E4E4E", +"+ c #B2B2B2", +"@ c #CACACA", +"# c #DEDEDE", +"$ c #AEAEAE", +"% c #FEFEFE", +"& c #F2F2F2", +"* c #464646", +"= c #D01866", +"- c #FFFFFF", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".=---=---=---==*", +".=-====-==-====*", +".=---==-==---==*", +".=-====-====-==*", +".=-====-==---==*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_fli.xpm b/kernel/xpm/codec_fli.xpm new file mode 100644 index 0000000..eba7881 --- /dev/null +++ b/kernel/xpm/codec_fli.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_fli[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #CF0008", +"o c #AA0889", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".oooooooooooooo ", +".o&&&&o&ooo&&&o ", +".o&oooo&oooo&oo ", +".o&&&oo&oooo&oo ", +".o&oooo&oooo&oo ", +".o&oooo&&&o&&&o ", +".oooooooooooooo ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_gif.xpm b/kernel/xpm/codec_gif.xpm new file mode 100644 index 0000000..f878e33 --- /dev/null +++ b/kernel/xpm/codec_gif.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_gif[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #008000", +"o c #CF0008", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".XXXXXXXXXXXXXX ", +".XXX&&&X&X&&&XX ", +".XX&XXXX&X&XXXX ", +".XX&X&&X&X&&XXX ", +".XX&XX&X&X&XXXX ", +".XXX&&&X&X&XXXX ", +".XXXXXXXXXXXXXX ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_hdr.xpm b/kernel/xpm/codec_hdr.xpm new file mode 100644 index 0000000..031a577 --- /dev/null +++ b/kernel/xpm/codec_hdr.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_hdr[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #020202", +". c #170100", +"X c #464646", +"o c #4E4E4E", +"O c #AEAEAE", +"+ c #B2B2B2", +"@ c #FEE6A2", +"# c #CACACA", +"$ c gray87", +"% c gray95", +"& c #FEFEFE", +"* c None", +/* pixels */ +"oooooooooo+*****", +"o########o$O****", +"o#&&&&&&#o%$+***", +"o#&&&&&&#oooo***", +"o#&&&&&&####o***", +"oXXXXXXXXXXXXXXX", +"o@@@@@@@@@@@@@@X", +"o@ @ @ @@ @X", +"o@ @ @ @ @ @ @X", +"o@ @ @@ @ @X", +"o@ @ @ @ @ @ @X", +"o@ @ @ @@ @ @X", +"o@@@@@@@@@@@@@@X", +"oXXXXXXXXXXXXXXX", +"o###########o***", +"*oooooooooooo***" +}; diff --git a/kernel/xpm/codec_ico.xpm b/kernel/xpm/codec_ico.xpm new file mode 100644 index 0000000..4d860eb --- /dev/null +++ b/kernel/xpm/codec_ico.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_ico[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #02026E", +". c #464646", +"X c #4E4E4E", +"o c #CF0008", +"O c #AEAEAE", +"+ c #B2B2B2", +"@ c #A2FEA2", +"# c #CACACA", +"$ c gray87", +"% c gray95", +"& c #FEFEFE", +"* c None", +/* pixels */ +"XXXXXXXXXX+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#XXX.***", +".#&&&&&&####X***", +"X...............", +". .", +"X @ @@ @@ .", +"X @ @ @ @ @ .", +". @ @ @ @ .", +"X @ @ @ @ @ .", +"X @ @@ @@ .", +"X .", +"X...............", +"X###########.***", +"*X.........XX***" +}; diff --git a/kernel/xpm/codec_iff.xpm b/kernel/xpm/codec_iff.xpm new file mode 100644 index 0000000..6f6fc74 --- /dev/null +++ b/kernel/xpm/codec_iff.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_iff[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #CF0008", +"o c red", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".oooooooooooooo ", +".ooo&o&&&o&&&oo ", +".ooo&o&ooo&oooo ", +".ooo&o&&oo&&ooo ", +".ooo&o&ooo&oooo ", +".ooo&o&ooo&oooo ", +".oooooooooooooo ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_jbig.xpm b/kernel/xpm/codec_jbig.xpm new file mode 100644 index 0000000..78ebbb7 --- /dev/null +++ b/kernel/xpm/codec_jbig.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_jbig[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c black", +". c gray27", +"X c #4C4C4C", +"o c #6D6969", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"XXXXXXXXXX+*****", +"X########X$O****", +"X#&&&&&&#X%$+***", +"X#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"X...............", +"Xoooooooooooooo.", +"Xo&&&o&&&o&&&&o.", +"Xooo&o&o&o&oooo.", +"Xooo&o&&&o&o&&o.", +"Xooo&o&o&o&oo&o.", +"Xo&&&o&&&o&&&&o.", +"Xoooooooooooooo.", +"X...............", +"X###########X***", +"*XXXXXXXXXXXX***" +}; diff --git a/kernel/xpm/codec_jpeg.xpm b/kernel/xpm/codec_jpeg.xpm new file mode 100644 index 0000000..1df6098 --- /dev/null +++ b/kernel/xpm/codec_jpeg.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_jpeg[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #CF0008", +"o c #808000", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".oooooooooooooo ", +".oo&o&&&ooo&&&o ", +".oo&o&oo&o&oooo ", +".oo&o&&&oo&o&&o ", +".&o&o&oooo&oo&o ", +".&&oo&ooooo&&&o ", +".oooooooooooooo ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_jpeg2000.xpm b/kernel/xpm/codec_jpeg2000.xpm new file mode 100644 index 0000000..1285008 --- /dev/null +++ b/kernel/xpm/codec_jpeg2000.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_jpeg2000[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #803F00", +"o c #CF62EA", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".oooooooooooooo ", +".ooo&o&&&o&&&oo ", +".ooo&o&o&o&o&oo ", +".ooo&o&&&ooo&oo ", +".o&o&o&oooo&ooo ", +".o&&oo&ooo&&&oo ", +".oooooooooooooo ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_koala.xpm b/kernel/xpm/codec_koala.xpm new file mode 100644 index 0000000..26f8930 --- /dev/null +++ b/kernel/xpm/codec_koala.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_koala[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c black", +". c gray27", +"X c #4C4C4C", +"o c #BC7079", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"XXXXXXXXXX+*****", +"X########X$O****", +"X#&&&&&&#X%$+***", +"X#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"X...............", +"Xoooooooooooooo.", +"Xo&oo&o&&&o&&&o.", +"Xo&&&oo&o&o&o&o.", +"Xo&&ooo&o&o&o&o.", +"Xo&&&oo&o&o&&&o.", +"Xo&oo&o&&&o&o&o.", +"Xoooooooooooooo.", +"X...............", +"X###########X***", +"*XXXXXXXXXXXX***" +}; diff --git a/kernel/xpm/codec_lbm.xpm b/kernel/xpm/codec_lbm.xpm new file mode 100644 index 0000000..4e8145c --- /dev/null +++ b/kernel/xpm/codec_lbm.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char * codec_lbm[] = { +"16 16 11 1", +" c None", +". c #4E4E4E", +"+ c #B2B2B2", +"@ c #CACACA", +"# c #DEDEDE", +"$ c #AEAEAE", +"% c #FEFEFE", +"& c #F2F2F2", +"* c #464646", +"= c #DFCE49", +"- c #1B0D0D", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".=-===---=-==-=*", +".=-===-=-=----=*", +".=-===---=-==-=*", +".=-===-=-=-==-=*", +".=---=---=-==-=*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_leaf.xpm b/kernel/xpm/codec_leaf.xpm new file mode 100644 index 0000000..bd92645 --- /dev/null +++ b/kernel/xpm/codec_leaf.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char * codec_leaf[] = { +"16 16 11 1", +" c None", +". c #4E4E4E", +"+ c #B2B2B2", +"@ c #CACACA", +"# c #DEDEDE", +"$ c #AEAEAE", +"% c #FEFEFE", +"& c #F2F2F2", +"* c #464646", +"= c #FFA10D", +"- c #1B1414", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".=-==--=---=--=*", +".=-==-==-=-=-==*", +".=-==--=---=--=*", +".=-==-==-=-=-==*", +".=--=--=-=-=-==*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_lif.xpm b/kernel/xpm/codec_lif.xpm new file mode 100644 index 0000000..fb0b194 --- /dev/null +++ b/kernel/xpm/codec_lif.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_lif[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c black", +". c gray27", +"X c #4C4C4C", +"o c #0AD38D", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"XXXXXXXXXX+*****", +"X########X$O****", +"X#&&&&&&#X%$+***", +"X#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"X...............", +"Xoooooooooooooo.", +"Xo.ooo...o....o.", +"Xo.oooo.oo.oo.o.", +"Xo.oooo.oo..ooo.", +"Xo.oooo.oo.oooo.", +"Xo...o...o.oooo.", +"Xoooooooooooooo.", +"X...............", +"X###########X***", +"*XXXXXXXXXXXX***" +}; diff --git a/kernel/xpm/codec_ljpeg.xpm b/kernel/xpm/codec_ljpeg.xpm new file mode 100644 index 0000000..dae859d --- /dev/null +++ b/kernel/xpm/codec_ljpeg.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char * codec_ljpeg[] = { +"16 16 10 1", +" c None", +". c #4C4C4C", +"+ c #B0B0B0", +"@ c #C8C8C8", +"# c #DDDDDD", +"$ c #AEAEAE", +"% c #FFFFFF", +"& c #F3F3F3", +"* c #454545", +"= c #808000", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".=%=====%=%%%==*", +".=%=====%=%==%=*", +".=%=====%=%%%==*", +".=%===%=%=%====*", +".=%%%=%%==%====*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_mac.xpm b/kernel/xpm/codec_mac.xpm new file mode 100644 index 0000000..7b23e88 --- /dev/null +++ b/kernel/xpm/codec_mac.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_mac[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #0E7175", +". c gray27", +"X c #4C4C4C", +"o c #CF0008", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"XXXXXXXXXX+*****", +"X########X$O****", +"X#&&&&&&#X%$+***", +"X#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"X...............", +"X .", +"X & & &&& &&& .", +"X &&&& & & & .", +"X & & &&& & .", +"X & & & & & .", +"X & & & & &&& .", +"X .", +"X...............", +"X###########X***", +"*XXXXXXXXXXXX***" +}; diff --git a/kernel/xpm/codec_mdl.xpm b/kernel/xpm/codec_mdl.xpm new file mode 100644 index 0000000..f77b4d0 --- /dev/null +++ b/kernel/xpm/codec_mdl.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_mdl[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #CF0008", +"o c #950AD1", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".oooooooooooooo ", +".o&oo&o&&&o&ooo ", +".o&&&&o&o&o&ooo ", +".o&oo&o&o&o&ooo ", +".o&oo&o&o&o&ooo ", +".o&oo&o&&&o&&&o ", +".oooooooooooooo ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_mng.xpm b/kernel/xpm/codec_mng.xpm new file mode 100644 index 0000000..6ae4737 --- /dev/null +++ b/kernel/xpm/codec_mng.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_mng[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c black", +". c gray27", +"X c #4C4C4C", +"o c #C24E1A", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"XXXXXXXXXX+*****", +"X########X$O****", +"X#&&&&&&#X%$+***", +"X#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"X...............", +"Xoooooooooooooo.", +"Xo&oo&o&&oo&&&o.", +"Xo&&&&o&o&o&ooo.", +"Xo&oo&o&o&o&o&o.", +"Xo&oo&o&o&o&o&o.", +"Xo&oo&o&o&o&&&o.", +"Xoooooooooooooo.", +"X...............", +"X###########X***", +"*XXXXXXXXXXXX***" +}; diff --git a/kernel/xpm/codec_msp.xpm b/kernel/xpm/codec_msp.xpm new file mode 100644 index 0000000..c581155 --- /dev/null +++ b/kernel/xpm/codec_msp.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_msp[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #000028", +". c gray27", +"X c #4C4C4C", +"o c #E62E8B", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"XXXXXXXXXX+*****", +"X########X$O****", +"X#&&&&&&#X%$+***", +"X#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"X...............", +"Xoooooooooooooo.", +"Xo&oo&o&&&o&&&o.", +"Xo&&&&o&ooo&o&o.", +"Xo&oo&o&&&o&&&o.", +"Xo&oo&ooo&o&ooo.", +"Xo&oo&o&&&o&ooo.", +"Xoooooooooooooo.", +"X...............", +"X###########X***", +"*XXXXXXXXXXXX***" +}; diff --git a/kernel/xpm/codec_mtv.xpm b/kernel/xpm/codec_mtv.xpm new file mode 100644 index 0000000..851a5e3 --- /dev/null +++ b/kernel/xpm/codec_mtv.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_mtv[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #020202", +". c #464646", +"X c #4E4E4E", +"o c #CF0008", +"O c #FEE202", +"+ c #AEAEAE", +"@ c #B2B2B2", +"# c #CACACA", +"$ c gray87", +"% c gray95", +"& c #FEFEFE", +"* c None", +/* pixels */ +"XXXXXXXXXX@*****", +"X########X$+****", +"X#&&&&&&#X%$@***", +"X#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"X...............", +"XOOOOOOOOOOOOOO.", +"XO OO O O O O.", +"XO OO OO O O.", +"XO OO OO OO O O.", +"XO OO OO OO O O.", +"XO OO OO OOO OO.", +"XOOOOOOOOOOOOOO.", +"X...............", +"X###########X***", +"*XXXXXXXXXXXX***" +}; diff --git a/kernel/xpm/codec_neo.xpm b/kernel/xpm/codec_neo.xpm new file mode 100644 index 0000000..df48672 --- /dev/null +++ b/kernel/xpm/codec_neo.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char * codec_neo[] = { +"16 16 11 1", +" c None", +". c #4E4E4E", +"+ c #B2B2B2", +"@ c #CACACA", +"# c #DEDEDE", +"$ c #AEAEAE", +"% c #FEFEFE", +"& c #F2F2F2", +"* c #464646", +"= c #0DFF2F", +"- c #000000", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".=--==---=---==*", +".=-=-=-===-=-==*", +".=-=-=--==-=-==*", +".=-=-=-===-=-==*", +".=-=-=---=---==*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_openexr.xpm b/kernel/xpm/codec_openexr.xpm new file mode 100644 index 0000000..72d7ff0 --- /dev/null +++ b/kernel/xpm/codec_openexr.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_openexr[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #020202", +". c #170100", +"X c #464646", +"o c #4E4E4E", +"O c #FEB602", +"+ c #AEAEAE", +"@ c #B2B2B2", +"# c #CACACA", +"$ c gray87", +"% c gray95", +"& c #FEFEFE", +"* c None", +/* pixels */ +"oooooooooo@*****", +"o########o$+****", +"o#&&&&&&#o%$@***", +"o#&&&&&&#oooo***", +"o#&&&&&&####o***", +"oXXXXXXXXXXXXXXX", +"oOOOOOOOOOOOOOOX", +"oO O O O OX", +" O OOOO O O O OX", +" O OOO OO OX", +" O OOOO O O O OX", +" O O O O O OX", +"oOOOOOOOOOOOOOOX", +"oXXXXXXXXXXXXXXX", +"o###########o***", +"*oooooooooooo***" +}; diff --git a/kernel/xpm/codec_pcx.xpm b/kernel/xpm/codec_pcx.xpm new file mode 100644 index 0000000..298d35b --- /dev/null +++ b/kernel/xpm/codec_pcx.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_pcx[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #CF0008", +"o c #808080", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".oooooooooooooo ", +".o&&&oo&&&o&o&o ", +".o&oo&o&o&o&o&o ", +".o&&&oo&oooo&oo ", +".o&oooo&o&o&o&o ", +".o&oooo&&&o&o&o ", +".oooooooooooooo ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_pi1.xpm b/kernel/xpm/codec_pi1.xpm new file mode 100644 index 0000000..3433ebf --- /dev/null +++ b/kernel/xpm/codec_pi1.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char * codec_pi1[] = { +"16 16 11 1", +" c None", +". c #4E4E4E", +"+ c #B2B2B2", +"@ c #CACACA", +"# c #DEDEDE", +"$ c #AEAEAE", +"% c #FEFEFE", +"& c #F2F2F2", +"* c #464646", +"= c #54375E", +"- c #FFFFFF", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".==---=---==-==*", +".==-=-==-==--==*", +".==---==-===-==*", +".==-====-===-==*", +".==-===---==-==*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_pi3.xpm b/kernel/xpm/codec_pi3.xpm new file mode 100644 index 0000000..f9ff285 --- /dev/null +++ b/kernel/xpm/codec_pi3.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char * codec_pi3[] = { +"16 16 11 1", +" c None", +". c #4E4E4E", +"+ c #B2B2B2", +"@ c #CACACA", +"# c #DEDEDE", +"$ c #AEAEAE", +"% c #FEFEFE", +"& c #F2F2F2", +"* c #464646", +"= c #54375E", +"- c #FFFFFF", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".==---=---=---=*", +".==-=-==-====-=*", +".==---==-===--=*", +".==-====-====-=*", +".==-===---=---=*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_pict.xpm b/kernel/xpm/codec_pict.xpm new file mode 100644 index 0000000..c5c3517 --- /dev/null +++ b/kernel/xpm/codec_pict.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char * codec_pict[] = { +"16 16 11 1", +" c None", +". c #4E4E4E", +"+ c #B2B2B2", +"@ c #CACACA", +"# c #DEDEDE", +"$ c #AEAEAE", +"% c #FEFEFE", +"& c #F2F2F2", +"* c #464646", +"= c #33C8FF", +"- c #000000", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".=---=-=--=---=*", +".=-=-=-=-===-==*", +".=---=-=-===-==*", +".=-===-=-===-==*", +".=-===-=--==-==*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_pix.xpm b/kernel/xpm/codec_pix.xpm new file mode 100644 index 0000000..575286f --- /dev/null +++ b/kernel/xpm/codec_pix.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_pix[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #020202", +". c #464646", +"X c #4E4E4E", +"o c #CF0008", +"O c #FECE32", +"+ c #AEAEAE", +"@ c #B2B2B2", +"# c #CACACA", +"$ c gray87", +"% c gray95", +"& c #FEFEFE", +"* c None", +/* pixels */ +"XXXXXXXXXX@*****", +"X########X$+****", +"X#&&&&&&#.%$@***", +".#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"................", +"XOOOOOOOOOOOOOO.", +".OO OO O O OO.", +"XOO OO O O O OO.", +".OO OO OO OOO.", +"XOO OOOO O O OO.", +".OO OOOO O O OO.", +"XOOOOOOOOOOOOOO.", +"................", +"X###@#######.***", +"*..XX......XX***" +}; diff --git a/kernel/xpm/codec_png.xpm b/kernel/xpm/codec_png.xpm new file mode 100644 index 0000000..2947900 --- /dev/null +++ b/kernel/xpm/codec_png.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_png[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #800000", +"o c #CF0008", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".XXXXXXXXXXXXXX ", +".&&&XX&XX&XX&&& ", +".&XX&X&&X&X&XXX ", +".&&&XX&X&&X&X&& ", +".&XXXX&XX&X&XX& ", +".&XXXX&XX&XX&&& ", +".XXXXXXXXXXXXXX ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_pnm.xpm b/kernel/xpm/codec_pnm.xpm new file mode 100644 index 0000000..42413d3 --- /dev/null +++ b/kernel/xpm/codec_pnm.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_pnm[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #CF0008", +"o c #FF5050", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".oooooooooooooo ", +".&&&oo&oo&o&oo& ", +".&oo&o&&o&o&&&& ", +".&&&oo&o&&o&oo& ", +".&oooo&oo&o&oo& ", +".&oooo&oo&o&oo& ", +".oooooooooooooo ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_psd.xpm b/kernel/xpm/codec_psd.xpm new file mode 100644 index 0000000..1729db8 --- /dev/null +++ b/kernel/xpm/codec_psd.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_psd[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #464646", +". c #4E4E4E", +"X c #5A5A5A", +"o c #CF0008", +"O c #FEFE02", +"+ c #AEAEAE", +"@ c #B2B2B2", +"# c #CACACA", +"$ c gray87", +"% c gray95", +"& c #FEFEFE", +"* c None", +/* pixels */ +"..........@*****", +" ######## $+****", +" #&&&&&&# %$@***", +" #&&&&&&#... ***", +" #&&&&&&####.***", +". ", +" OOOOOOOOOOOOOO ", +".XXXOOOXXXOXXXO ", +" XOOXOXOOOOXOOX ", +".XXXOOOXXOOXOOX ", +".XOOOOOOOXOXOOX ", +" XOOOOXXXOOXXXO ", +".OOOOOOOOOOOOOO ", +" ", +".########### ***", +"*. . . . .***" +}; diff --git a/kernel/xpm/codec_psp.xpm b/kernel/xpm/codec_psp.xpm new file mode 100644 index 0000000..8fe9419 --- /dev/null +++ b/kernel/xpm/codec_psp.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char * codec_psp[] = { +"16 16 11 1", +" c None", +". c #4C4C4C", +"+ c #B0B0B0", +"@ c #C8C8C8", +"# c #DDDDDD", +"$ c #AEAEAE", +"% c #FFFFFF", +"& c #F3F3F3", +"* c #454545", +"= c #4CC4F0", +"- c #000000", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".=---=---=---==*", +".=-=-=-===-=-==*", +".=---=---=---==*", +".=-=====-=-====*", +".=-===---=-====*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_pxr.xpm b/kernel/xpm/codec_pxr.xpm new file mode 100644 index 0000000..d61249f --- /dev/null +++ b/kernel/xpm/codec_pxr.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_pxr[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c black", +". c gray27", +"X c #4C4C4C", +"o c #7D1AC2", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"XXXXXXXXXX+*****", +"X########X$O****", +"X#&&&&&&#X%$+***", +"X#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"X...............", +"Xoooooooooooooo.", +"Xo&&&o&o&o&&&oo.", +"Xo&o&o&o&o&o&oo.", +"Xo&&&oo&oo&&&oo.", +"Xo&ooo&o&o&o&oo.", +"Xo&ooo&o&o&o&oo.", +"Xoooooooooooooo.", +"X...............", +"X###########X***", +"*XXXXXXXXXXXX***" +}; diff --git a/kernel/xpm/codec_ras.xpm b/kernel/xpm/codec_ras.xpm new file mode 100644 index 0000000..15d5627 --- /dev/null +++ b/kernel/xpm/codec_ras.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_ras[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #020202", +". c #464646", +"X c #4E4E4E", +"o c #66FECE", +"O c #CF0008", +"+ c #AEAEAE", +"@ c #B2B2B2", +"# c #CACACA", +"$ c gray87", +"% c gray95", +"& c #FEFEFE", +"* c None", +/* pixels */ +"XXXXXXXXXX@*****", +"X########X$+****", +"X#&&&&&&#.%$@***", +".#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"................", +"Xoooooooooooooo.", +"X ooo ooo .", +"X oo oo oo ooo.", +"X oo oo oo o.", +"X oo o oooo .", +"X oo o oo o o.", +"Xoooooooooooooo.", +"................", +"X###########.***", +"*..........XX***" +}; diff --git a/kernel/xpm/codec_rawrgb.xpm b/kernel/xpm/codec_rawrgb.xpm new file mode 100644 index 0000000..f96bf2d --- /dev/null +++ b/kernel/xpm/codec_rawrgb.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_rawrgb[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #464646", +". c #4E4E4E", +"X c #566A8E", +"o c #CF0008", +"O c #AEAEAE", +"+ c #B2B2B2", +"@ c #CACACA", +"# c gray87", +"$ c #EEEEFE", +"% c gray95", +"& c #FEFEFE", +"* c None", +/* pixels */ +"..........+*****", +" @@@@@@@@ #O****", +" @&&&&&&@ %#+***", +" @&&&&&&@... ***", +" @&&&&&&@@@@.***", +". ", +" XXXXXXXXXXXXXX ", +".$$$XX$$$X$XXX$ ", +" $XX$X#X$X$X$X$ ", +".$#$XX$X$X#X$X$ ", +".$XX$X$$$XX$X#X ", +" $XX$X$X$XX$X$X ", +".XXXXXXXXXXXXXX ", +" ", +".@@@@@@@@@@@ ***", +"* ..***" +}; diff --git a/kernel/xpm/codec_sct.xpm b/kernel/xpm/codec_sct.xpm new file mode 100644 index 0000000..370bbce --- /dev/null +++ b/kernel/xpm/codec_sct.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_sct[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #CF0008", +"o c #E05787", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".oooooooooooooo ", +".oo&&&o&&&o&&&o ", +".o&oooo&oooo&oo ", +".oo&&oo&oooo&oo ", +".oooo&o&oooo&oo ", +".o&&&oo&&&oo&oo ", +".oooooooooooooo ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_sgi.xpm b/kernel/xpm/codec_sgi.xpm new file mode 100644 index 0000000..0bcbaf9 --- /dev/null +++ b/kernel/xpm/codec_sgi.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_sgi[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #CF0008", +"o c magenta", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".oooooooooooooo ", +".oo&&&oo&&&o&&o ", +".o&oooo&ooooo&o ", +".oo&&oo&o&&oo&o ", +".oooo&o&oo&oo&o ", +".o&&&ooo&&&o&&o ", +".oooooooooooooo ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_sun.xpm b/kernel/xpm/codec_sun.xpm new file mode 100644 index 0000000..9f97753 --- /dev/null +++ b/kernel/xpm/codec_sun.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_sun[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #464646", +". c #4E4E4E", +"X c #727272", +"o c #CF0008", +"O c #AEAEAE", +"+ c #B2B2B2", +"@ c #96FEAA", +"# c #CACACA", +"$ c gray87", +"% c gray95", +"& c #FEFEFE", +"* c None", +/* pixels */ +"..........+*****", +" ######## $O****", +" #&&&&&&# %$+***", +" #&&&&&&#... ***", +" #&&&&&&####.***", +". ", +" XXXXXXXXXXXXXX ", +" X@@@X@XX@X@XX@ ", +" @XXXX@XX@X@@X@ ", +" X@@XX@XX@X@X@@ ", +" XXX@X@XX@X@XX@ ", +" @@@XXX@@XX@XX@ ", +" XXXXXXXXXXXXXX ", +" ", +" ##+#+#+##+# ***", +"* . .. . ***" +}; diff --git a/kernel/xpm/codec_svg.xpm b/kernel/xpm/codec_svg.xpm new file mode 100644 index 0000000..570b577 --- /dev/null +++ b/kernel/xpm/codec_svg.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_svg[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #000028", +". c gray27", +"X c #4C4C4C", +"o c #D86800", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"XXXXXXXXXX+*****", +"X########X$O****", +"X#&&&&&&#X%$+***", +"X#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"X...............", +"Xoooooooooooooo.", +"Xo&&&o&o&o&&&oo.", +"Xo&ooo&o&o&oooo.", +"Xo&&&o&o&o&o&&o.", +"Xooo&o&&&o&oo&o.", +"Xo&&&oo&oo&&&&o.", +"Xoooooooooooooo.", +"X...............", +"X###########X***", +"*XXXXXXXXXXXX***" +}; diff --git a/kernel/xpm/codec_tga.xpm b/kernel/xpm/codec_tga.xpm new file mode 100644 index 0000000..3368d8d --- /dev/null +++ b/kernel/xpm/codec_tga.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_tga[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #008080", +"o c #CF0008", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".XXXXXXXXXXXXXX ", +".X&&&XX&&&X&&&X ", +".XX&XX&XXXX&X&X ", +".XX&XX&X&&X&X&X ", +".XX&XX&XX&X&&&X ", +".XX&XXX&&&X&X&X ", +".XXXXXXXXXXXXXX ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_tiff.xpm b/kernel/xpm/codec_tiff.xpm new file mode 100644 index 0000000..594fdc6 --- /dev/null +++ b/kernel/xpm/codec_tiff.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_tiff[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #000099", +"o c #CF0008", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".XXXXXXXXXXXXXX ", +".X&&&X&X&&X&&&X ", +".XX&XX&X&XX&XXX ", +".XX&XX&X&&X&&XX ", +".XX&XX&X&XX&XXX ", +".XX&XX&X&XX&XXX ", +".XXXXXXXXXXXXXX ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_ttf.xpm b/kernel/xpm/codec_ttf.xpm new file mode 100644 index 0000000..faeb818 --- /dev/null +++ b/kernel/xpm/codec_ttf.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_ttf[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c black", +". c gray27", +"X c #4C4C4C", +"o c #E94A8D", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"XXXXXXXXXX+*****", +"X########X$O****", +"X#&&&&&&#X%$+***", +"X#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"X...............", +"Xoooooooooooooo.", +"Xo&&&o&&&o&&&&o.", +"Xoo&ooo&oo&oooo.", +"Xoo&ooo&oo&&&oo.", +"Xoo&ooo&oo&oooo.", +"Xoo&ooo&oo&oooo.", +"Xoooooooooooooo.", +"X...............", +"X###########X***", +"*XXXXXXXXXXXX***" +}; diff --git a/kernel/xpm/codec_utah.xpm b/kernel/xpm/codec_utah.xpm new file mode 100644 index 0000000..8335d0e --- /dev/null +++ b/kernel/xpm/codec_utah.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_utah[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #020202", +". c #464646", +"X c #4E4E4E", +"o c #CF0008", +"O c #AAC25A", +"+ c #AEAEAE", +"@ c #B2B2B2", +"# c #CACACA", +"$ c gray87", +"% c gray95", +"& c #FEFEFE", +"* c None", +/* pixels */ +"XXXXXXXXXX@*****", +"X########X$+****", +"X#&&&&&&#.%$@***", +".#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"................", +"XOOOOOOOOOOOOOO.", +".O OO OOO O.", +"XO OO O OOO OOO.", +"XO OO OOO OO.", +"XO OO O OOO OOO.", +"XO OO O O O.", +"XOOOOOOOOOOOOOO.", +"................", +"X###########.***", +"*..........XX***" +}; diff --git a/kernel/xpm/codec_wal.xpm b/kernel/xpm/codec_wal.xpm new file mode 100644 index 0000000..a7bd66b --- /dev/null +++ b/kernel/xpm/codec_wal.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_wal[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #CF0008", +"o c #C6498E", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".oooooooooooooo ", +".&ooo&oo&&oo&oo ", +".&o&o&o&oo&o&oo ", +".&o&o&o&oo&o&oo ", +".o&o&oo&&&&o&oo ", +".o&o&oo&oo&o&&& ", +".oooooooooooooo ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_wbmp.xpm b/kernel/xpm/codec_wbmp.xpm new file mode 100644 index 0000000..6b281a2 --- /dev/null +++ b/kernel/xpm/codec_wbmp.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_wbmp[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c gray27", +". c #4C4C4C", +"X c #CF0008", +"o c #B9A700", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"..........+*****", +".########.$O****", +".#&&&&&&#.%$+***", +".#&&&&&&#....***", +".#&&&&&&####.***", +". ", +".oooooooooooooo ", +".&ooo&o&&&o&oo& ", +".&o&o&o&o&o&&&& ", +".&o&o&o&&&o&oo& ", +".o&o&oo&o&o&oo& ", +".o&o&oo&&&o&oo& ", +".oooooooooooooo ", +". ", +".###########.***", +"*............***" +}; diff --git a/kernel/xpm/codec_wmf.xpm b/kernel/xpm/codec_wmf.xpm new file mode 100644 index 0000000..95cd878 --- /dev/null +++ b/kernel/xpm/codec_wmf.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_wmf[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c black", +". c gray27", +"X c #4C4C4C", +"o c #CF0008", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"XXXXXXXXXX+*****", +"X########X$O****", +"X#&&&&&&#X%$+***", +"X#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"X...............", +"X .", +"X& & & & &&&.", +"X& & & &&&& & .", +"X& & & & & && .", +"X & & & & & .", +"X & & & & & .", +"X .", +"X...............", +"X###########X***", +"*XXXXXXXXXXXX***" +}; diff --git a/kernel/xpm/codec_xbm.xpm b/kernel/xpm/codec_xbm.xpm new file mode 100644 index 0000000..d5a9f51 --- /dev/null +++ b/kernel/xpm/codec_xbm.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_xbm[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #464646", +". c #4E4E4E", +"X c #0202CA", +"o c #CF0008", +"O c #AEAEAE", +"+ c #B2B2B2", +"@ c #CACACA", +"# c gray87", +"$ c #FEFECA", +"% c gray95", +"& c #FEFEFE", +"* c None", +/* pixels */ +"..........+*****", +" @@@@@@@@ #O****", +" @&&&&&&@ %#+***", +" @&&&&&&@... ***", +" @&&&&&&@@@@.***", +". ", +" XXXXXXXXXXXXXX ", +".$X$X$$$XX$XXX$ ", +" $X$X$XX$X$$X$$ ", +".X$XX$$$XX$X$X$ ", +" $X$X$XX$X$XXX$ ", +".$X$X$$$XX$XXX$ ", +".XXXXXXXXXXXXXX ", +" ", +" @@@@@@@@@@@ ***", +"* .***" +}; diff --git a/kernel/xpm/codec_xcf.xpm b/kernel/xpm/codec_xcf.xpm new file mode 100644 index 0000000..d8288f4 --- /dev/null +++ b/kernel/xpm/codec_xcf.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char *codec_xcf[] = { +"16 16 11 1", +" c None", +". c #4E4E4E", +"+ c #B2B2B2", +"@ c #CACACA", +"# c #DEDEDE", +"$ c #AEAEAE", +"% c #FEFEFE", +"& c #F2F2F2", +"* c #464646", +"= c #FFB3E0", +"- c #000000", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".=-=-=---=---==*", +".=-=-=-===-====*", +".==-==-===---==*", +".=-=-=-===-====*", +".=-=-=---=-====*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_xcur.xpm b/kernel/xpm/codec_xcur.xpm new file mode 100644 index 0000000..dda239e --- /dev/null +++ b/kernel/xpm/codec_xcur.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_xcur[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #020202", +". c #464646", +"X c #4E4E4E", +"o c #CF0008", +"O c #FEFE02", +"+ c #AEAEAE", +"@ c #B2B2B2", +"# c #CACACA", +"$ c gray87", +"% c gray95", +"& c #FEFEFE", +"* c None", +/* pixels */ +"XXXXXXXXXX@*****", +"X########X$+****", +"X#&&&&&&#.%$@***", +".#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"................", +"XOOOOOOOOOOOOOO.", +"X O OOOOOOOOOOO.", +"X O OOOOOOOOOOO.", +"XO OOO O O O .", +"X O O OOO O O O.", +"X O OO OO O O.", +"XOOOOOOOOOOOOOO.", +"X...............", +"X###########.***", +"*X.........XX***" +}; diff --git a/kernel/xpm/codec_xim.xpm b/kernel/xpm/codec_xim.xpm new file mode 100644 index 0000000..85eafa2 --- /dev/null +++ b/kernel/xpm/codec_xim.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char * codec_xim[] = { +"16 16 11 1", +" c None", +". c #4E4E4E", +"+ c #B2B2B2", +"@ c #CACACA", +"# c #DEDEDE", +"$ c #AEAEAE", +"% c #FEFEFE", +"& c #F2F2F2", +"* c #464646", +"= c #FDFCB7", +"- c #000000", +"..........+ ", +".@@@@@@@@.#$ ", +".@%%%%%%@.&#+ ", +".@%%%%%%@.... ", +".@%%%%%%@@@@. ", +".***************", +".==============*", +".=-=-=---=-==-=*", +".=-=-==-==----=*", +".==-===-==-==-=*", +".=-=-==-==-==-=*", +".=-=-=---=-==-=*", +".==============*", +".***************", +".@@@@@@@@@@@. ", +" ............ "}; diff --git a/kernel/xpm/codec_xpm.xpm b/kernel/xpm/codec_xpm.xpm new file mode 100644 index 0000000..098cb40 --- /dev/null +++ b/kernel/xpm/codec_xpm.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #000002", +". c gray27", +"X c #4C4C4C", +"o c #5F5F5F", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"XXXXXXXXXX+*****", +"X########X$O****", +"X#&&&&&&#X%$+***", +"X#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"X...............", +"Xoooooooooooooo.", +"X&o&o&&&oo&ooo&.", +"X&o&o&oo&o&&o&&.", +"Xo&oo&&&oo&o&o&.", +"X&o&o&oooo&ooo&.", +"X&o&o&oooo&ooo&.", +"Xoooooooooooooo.", +"X...............", +"X###########X***", +"*XXXXXXXXXXXX***" +}; diff --git a/kernel/xpm/codec_xwd.xpm b/kernel/xpm/codec_xwd.xpm new file mode 100644 index 0000000..703e623 --- /dev/null +++ b/kernel/xpm/codec_xwd.xpm @@ -0,0 +1,34 @@ +/* XPM */ +static const char *codec_xwd[] = { +/* columns rows colors chars-per-pixel */ +"16 16 12 1", +" c #000028", +". c gray27", +"X c #4C4C4C", +"o c #890C53", +"O c #AEAEAE", +"+ c gray69", +"@ c #B1B1B1", +"# c #C8C8C8", +"$ c #DDDDDD", +"% c #F3F3F3", +"& c gray100", +"* c None", +/* pixels */ +"XXXXXXXXXX+*****", +"X########X$O****", +"X#&&&&&&#X%$+***", +"X#&&&&&&#XXXX***", +"X#&&&&&&####X***", +"X...............", +"Xoooooooooooooo.", +"X&o&o&ooo&o&&&o.", +"X&o&o&o&o&o&oo&.", +"Xo&oo&o&o&o&oo&.", +"X&o&oo&o&oo&oo&.", +"X&o&oo&o&oo&&&o.", +"Xoooooooooooooo.", +"X...............", +"X###########X***", +"*XXXXXXXXXXXX***" +}; -- cgit v1.2.1