diff --git a/BUILDING.txt b/BUILDING.txt index 1df57e04..70d71240 100644 --- a/BUILDING.txt +++ b/BUILDING.txt @@ -338,17 +338,17 @@ Set the following shell variables for simplicity: Xcode 5.0.x and later: IOS_GCC=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang - ARM v6 only (up to and including iPhone 3G): + ARM v6 (code will run on all iOS devices, not SIMD-accelerated): [NOTE: Requires Xcode 4.4.x or earlier] IOS_CFLAGS="-march=armv6 -mcpu=arm1176jzf-s -mfpu=vfp" - ARM v7 only (iPhone 3GS-4S, iPad 1st-3rd Generation): + ARM v7 (code will run on iPhone 3GS-4S/iPad 1st-3rd Generation and newer): Xcode 4.6.x and earlier: IOS_CFLAGS="-march=armv7 -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon" Xcode 5.0.x and later: IOS_CFLAGS="-arch armv7" - ARM v7s only (iPhone 5, iPad 4th Generation): + ARM v7s (code will run on iPhone 5/iPad 4th Generation and newer): [NOTE: Requires Xcode 4.5 or later] Xcode 4.6.x and earlier: IOS_CFLAGS="-march=armv7s -mcpu=swift -mtune=swift -mfpu=neon" diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fba917a..f0832421 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,20 @@ option(WITH_ARITH_DEC "Include arithmetic decoding support" TRUE) option(WITH_JPEG7 "Emulate libjpeg v7 API/ABI (this makes libmozjpeg backward incompatible with libjpeg v6b)" FALSE) option(WITH_JPEG8 "Emulate libjpeg v8 API/ABI (this makes libmozjpeg backward incompatible with libjpeg v6b)" FALSE) option(WITH_MEM_SRCDST "Include in-memory source/destination manager functions when emulating the libjpeg v6b or v7 API/ABI" TRUE) +option(WITH_TURBOJPEG "Include the TurboJPEG wrapper library and associated test programs" TRUE) option(WITH_JAVA "Build Java wrapper for the TurboJPEG library" FALSE) +option(WITH_12BIT "Encode/decode JPEG images with 12-bit samples (implies WITH_SIMD=0 WITH_TURBOJPEG=0 WITH_ARITH_ENC=0 WITH_ARITH_DEC=0)" FALSE) + +if(WITH_12BIT) + set(WITH_SIMD FALSE) + set(WITH_TURBOJPEG FALSE) + set(WITH_ARITH_ENC FALSE) + set(WITH_ARITH_DEC FALSE) + set(BITS_IN_JSAMPLE 12) + message(STATUS "12-bit JPEG support enabled") +else() + set(BITS_IN_JSAMPLE 8) +endif() if(WITH_ARITH_ENC) set(C_ARITH_CODING_SUPPORTED 1) @@ -66,6 +79,12 @@ else() message(STATUS "Arithmetic decoding support disabled") endif() +if(WITH_TURBOJPEG) + message(STATUS "TurboJPEG C wrapper enabled") +else() + message(STATUS "TurboJPEG C wrapper disabled") +endif() + if(WITH_JAVA) message(STATUS "TurboJPEG Java wrapper enabled") else() @@ -209,57 +228,65 @@ if(WITH_SIMD) add_dependencies(jpeg-static simd) endif() -set(TURBOJPEG_SOURCES turbojpeg.c transupp.c jdatadst-tj.c jdatasrc-tj.c) -if(WITH_JAVA) - set(TURBOJPEG_SOURCES ${TURBOJPEG_SOURCES} turbojpeg-jni.c) - include_directories(${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2}) +if(WITH_TURBOJPEG) + set(TURBOJPEG_SOURCES turbojpeg.c transupp.c jdatadst-tj.c jdatasrc-tj.c) + if(WITH_JAVA) + set(TURBOJPEG_SOURCES ${TURBOJPEG_SOURCES} turbojpeg-jni.c) + include_directories(${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2}) + endif() + + add_library(turbojpeg SHARED ${TURBOJPEG_SOURCES}) + set_target_properties(turbojpeg PROPERTIES DEFINE_SYMBOL DLLDEFINE) + if(MINGW) + set_target_properties(turbojpeg PROPERTIES LINK_FLAGS -Wl,--kill-at) + endif() + target_link_libraries(turbojpeg jpeg-static) + set_target_properties(turbojpeg PROPERTIES LINK_INTERFACE_LIBRARIES "") + + add_library(turbojpeg-static STATIC ${JPEG_SOURCES} ${SIMD_OBJS} + turbojpeg.c transupp.c jdatadst-tj.c jdatasrc-tj.c) + if(NOT MSVC) + set_target_properties(turbojpeg-static PROPERTIES OUTPUT_NAME turbojpeg) + endif() + if(WITH_SIMD) + add_dependencies(turbojpeg-static simd) + endif() + + add_executable(tjunittest tjunittest.c tjutil.c) + target_link_libraries(tjunittest turbojpeg) + + add_executable(tjunittest-static tjunittest.c tjutil.c) + target_link_libraries(tjunittest-static turbojpeg-static) + + add_executable(tjbench tjbench.c bmp.c tjutil.c rdbmp.c rdppm.c wrbmp.c + wrppm.c) + target_link_libraries(tjbench turbojpeg jpeg-static) + set_property(TARGET tjbench PROPERTY COMPILE_FLAGS + "-DBMP_SUPPORTED -DPPM_SUPPORTED") + + add_executable(tjbench-static tjbench.c bmp.c tjutil.c rdbmp.c rdppm.c wrbmp.c + wrppm.c) + target_link_libraries(tjbench-static turbojpeg-static jpeg-static) + set_property(TARGET tjbench-static PROPERTY COMPILE_FLAGS + "-DBMP_SUPPORTED -DPPM_SUPPORTED") endif() -add_library(turbojpeg SHARED ${TURBOJPEG_SOURCES}) -set_target_properties(turbojpeg PROPERTIES DEFINE_SYMBOL DLLDEFINE) -if(MINGW) - set_target_properties(turbojpeg PROPERTIES LINK_FLAGS -Wl,--kill-at) -endif() -target_link_libraries(turbojpeg jpeg-static) -set_target_properties(turbojpeg PROPERTIES LINK_INTERFACE_LIBRARIES "") - -add_library(turbojpeg-static STATIC ${JPEG_SOURCES} ${SIMD_OBJS} - turbojpeg.c transupp.c jdatadst-tj.c jdatasrc-tj.c) -if(NOT MSVC) - set_target_properties(turbojpeg-static PROPERTIES OUTPUT_NAME turbojpeg) -endif() -if(WITH_SIMD) - add_dependencies(turbojpeg-static simd) +if(WITH_12BIT) + set(COMPILE_FLAGS "-DGIF_SUPPORTED -DPPM_SUPPORTED -DUSE_SETMODE") +else() + set(COMPILE_FLAGS "-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED -DUSE_SETMODE") + set(CJPEG_BMP_SOURCES rdbmp.c rdtarga.c) + set(DJPEG_BMP_SOURCES wrbmp.c wrtarga.c) endif() -add_executable(tjunittest tjunittest.c tjutil.c) -target_link_libraries(tjunittest turbojpeg) - -add_executable(tjunittest-static tjunittest.c tjutil.c) -target_link_libraries(tjunittest-static turbojpeg-static) - -add_executable(tjbench tjbench.c bmp.c tjutil.c rdbmp.c rdppm.c wrbmp.c - wrppm.c) -target_link_libraries(tjbench turbojpeg jpeg-static) -set_property(TARGET tjbench PROPERTY COMPILE_FLAGS - "-DBMP_SUPPORTED -DPPM_SUPPORTED") - -add_executable(tjbench-static tjbench.c bmp.c tjutil.c rdbmp.c rdppm.c wrbmp.c - wrppm.c) -target_link_libraries(tjbench-static turbojpeg-static jpeg-static) -set_property(TARGET tjbench-static PROPERTY COMPILE_FLAGS - "-DBMP_SUPPORTED -DPPM_SUPPORTED") - -add_executable(cjpeg-static cjpeg.c cdjpeg.c rdbmp.c rdgif.c rdppm.c rdswitch.c - rdtarga.c rdjpeg.c) -set_property(TARGET cjpeg-static PROPERTY COMPILE_FLAGS - "-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED -DUSE_SETMODE") +add_executable(cjpeg-static cjpeg.c cdjpeg.c rdgif.c rdppm.c rdswitch.c rdjpeg.c + ${CJPEG_BMP_SOURCES}) +set_property(TARGET cjpeg-static PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS}) target_link_libraries(cjpeg-static jpeg-static) -add_executable(djpeg-static djpeg.c cdjpeg.c rdcolmap.c rdswitch.c wrbmp.c wrgif.c - wrppm.c wrtarga.c) -set_property(TARGET djpeg-static PROPERTY COMPILE_FLAGS - "-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED -DUSE_SETMODE") +add_executable(djpeg-static djpeg.c cdjpeg.c rdcolmap.c rdswitch.c wrgif.c + wrppm.c ${DJPEG_BMP_SOURCES}) +set_property(TARGET djpeg-static PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS}) target_link_libraries(djpeg-static jpeg-static) add_executable(jpegtran-static jpegtran.c cdjpeg.c rdswitch.c transupp.c) @@ -283,53 +310,85 @@ endif() enable_testing() -set(MD5_JPEG_RGB_ISLOW 768e970dd57b340ff1b83c9d3d47c77b) -set(MD5_PPM_RGB_ISLOW 00a257f5393fef8821f2b88ac7421291) -set(MD5_BMP_RGB_ISLOW_565 f07d2e75073e4bb10f6c6f4d36e2e3be) -set(MD5_BMP_RGB_ISLOW_565D 4cfa0928ef3e6bb626d7728c924cfda4) -set(MD5_JPEG_422_IFAST_OPT 2540287b79d913f91665e660303ab2c8) -set(MD5_PPM_422_IFAST 35bd6b3f833bad23de82acea847129fa) -set(MD5_PPM_422M_IFAST 8dbc65323d62cca7c91ba02dd1cfa81d) -set(MD5_BMP_422M_IFAST_565 3294bd4d9a1f2b3d08ea6020d0db7065) -set(MD5_BMP_422M_IFAST_565D da98c9c7b6039511be4a79a878a9abc1) -set(MD5_JPEG_420_IFAST_Q100_PROG 990cbe0329c882420a2094da7e5adade) -set(MD5_PPM_420_Q100_IFAST 5a732542015c278ff43635e473a8a294) -set(MD5_PPM_420M_Q100_IFAST ff692ee9323a3b424894862557c092f1) -set(MD5_JPEG_GRAY_ISLOW 72b51f894b8f4a10b3ee3066770aa38d) -set(MD5_PPM_GRAY_ISLOW 8d3596c56eace32f205deccc229aa5ed) -set(MD5_PPM_GRAY_ISLOW_RGB 116424ac07b79e5e801f00508eab48ec) -set(MD5_BMP_GRAY_ISLOW_565 12f78118e56a2f48b966f792fedf23cc) -set(MD5_BMP_GRAY_ISLOW_565D bdbbd616441a24354c98553df5dc82db) -set(MD5_JPEG_420S_IFAST_OPT 388708217ac46273ca33086b22827ed8) -if(WITH_SIMD) -set(MD5_JPEG_3x2_FLOAT_PROG 343e3f8caf8af5986ebaf0bdc13b5c71) -set(MD5_PPM_3x2_FLOAT 1a75f36e5904d6fc3a85a43da9ad89bb) +if(WITH_12BIT) + set(TESTORIG testorig12.jpg) + set(MD5_JPEG_RGB_ISLOW 9620f424569594bb9242b48498ad801f) + set(MD5_PPM_RGB_ISLOW f3301d2219783b8b3d942b7239fa50c0) + set(MD5_JPEG_422_IFAST_OPT 7322e3bd2f127f7de4b40d4480ce60e4) + set(MD5_PPM_422_IFAST 79807fa552899e66a04708f533e16950) + set(MD5_PPM_422M_IFAST 07737bfe8a7c1c87aaa393a0098d16b0) + set(MD5_JPEG_420_IFAST_Q100_PROG a1da220b5604081863a504297ed59e55) + set(MD5_PPM_420_Q100_IFAST 1b3730122709f53d007255e8dfd3305e) + set(MD5_PPM_420M_Q100_IFAST 980a1a3c5bf9510022869d30b7d26566) + set(MD5_JPEG_GRAY_ISLOW 235c90707b16e2e069f37c888b2636d9) + set(MD5_PPM_GRAY_ISLOW 7213c10af507ad467da5578ca5ee1fca) + set(MD5_PPM_GRAY_ISLOW_RGB e96ee81c30a6ed422d466338bd3de65d) + set(MD5_JPEG_420S_IFAST_OPT 7af8e60be4d9c227ec63ac9b6630855e) + set(MD5_JPEG_3x2_FLOAT_PROG a8c17daf77b457725ec929e215b603f8) + set(MD5_PPM_3x2_FLOAT 42876ab9e5c2f76a87d08db5fbd57956) + set(MD5_PPM_420M_ISLOW_2_1 4ca6be2a6f326ff9eaab63e70a8259c0) + set(MD5_PPM_420M_ISLOW_15_8 12aa9f9534c1b3d7ba047322226365eb) + set(MD5_PPM_420M_ISLOW_13_8 f7e22817c7b25e1393e4ec101e9d4e96) + set(MD5_PPM_420M_ISLOW_11_8 800a16f9f4dc9b293197bfe11be10a82) + set(MD5_PPM_420M_ISLOW_9_8 06b7a92a9bc69f4dc36ec40f1937d55c) + set(MD5_PPM_420M_ISLOW_7_8 3ec444a14a4ab4eab88ffc49c48eca43) + set(MD5_PPM_420M_ISLOW_3_4 3e726b7ea872445b19437d1c1d4f0d93) + set(MD5_PPM_420M_ISLOW_5_8 a8a771abdc94301d20ffac119b2caccd) + set(MD5_PPM_420M_ISLOW_1_2 b419124dd5568b085787234866102866) + set(MD5_PPM_420M_ISLOW_3_8 343d19015531b7bbe746124127244fa8) + set(MD5_PPM_420M_ISLOW_1_4 35fd59d866e44659edfa3c18db2a3edb) + set(MD5_PPM_420M_ISLOW_1_8 ccaed48ac0aedefda5d4abe4013f4ad7) + set(MD5_JPEG_CROP cdb35ff4b4519392690ea040c56ea99c) else() -set(MD5_JPEG_3x2_FLOAT_PROG 9bca803d2042bd1eb03819e2bf92b3e5) -set(MD5_PPM_3x2_FLOAT f6bfab038438ed8f5522fbd33595dcdc) + set(TESTORIG testorig.jpg) + set(MD5_JPEG_RGB_ISLOW 768e970dd57b340ff1b83c9d3d47c77b) + set(MD5_PPM_RGB_ISLOW 00a257f5393fef8821f2b88ac7421291) + set(MD5_BMP_RGB_ISLOW_565 f07d2e75073e4bb10f6c6f4d36e2e3be) + set(MD5_BMP_RGB_ISLOW_565D 4cfa0928ef3e6bb626d7728c924cfda4) + set(MD5_JPEG_422_IFAST_OPT 2540287b79d913f91665e660303ab2c8) + set(MD5_PPM_422_IFAST 35bd6b3f833bad23de82acea847129fa) + set(MD5_PPM_422M_IFAST 8dbc65323d62cca7c91ba02dd1cfa81d) + set(MD5_BMP_422M_IFAST_565 3294bd4d9a1f2b3d08ea6020d0db7065) + set(MD5_BMP_422M_IFAST_565D da98c9c7b6039511be4a79a878a9abc1) + set(MD5_JPEG_420_IFAST_Q100_PROG 990cbe0329c882420a2094da7e5adade) + set(MD5_PPM_420_Q100_IFAST 5a732542015c278ff43635e473a8a294) + set(MD5_PPM_420M_Q100_IFAST ff692ee9323a3b424894862557c092f1) + set(MD5_JPEG_GRAY_ISLOW 72b51f894b8f4a10b3ee3066770aa38d) + set(MD5_PPM_GRAY_ISLOW 8d3596c56eace32f205deccc229aa5ed) + set(MD5_PPM_GRAY_ISLOW_RGB 116424ac07b79e5e801f00508eab48ec) + set(MD5_BMP_GRAY_ISLOW_565 12f78118e56a2f48b966f792fedf23cc) + set(MD5_BMP_GRAY_ISLOW_565D bdbbd616441a24354c98553df5dc82db) + set(MD5_JPEG_420S_IFAST_OPT 388708217ac46273ca33086b22827ed8) + if(WITH_SIMD) + set(MD5_JPEG_3x2_FLOAT_PROG 343e3f8caf8af5986ebaf0bdc13b5c71) + set(MD5_PPM_3x2_FLOAT 1a75f36e5904d6fc3a85a43da9ad89bb) + else() + set(MD5_JPEG_3x2_FLOAT_PROG 9bca803d2042bd1eb03819e2bf92b3e5) + set(MD5_PPM_3x2_FLOAT f6bfab038438ed8f5522fbd33595dcdc) + endif() + set(MD5_JPEG_420_ISLOW_ARI e986fb0a637a8d833d96e8a6d6d84ea1) + set(MD5_JPEG_444_ISLOW_PROGARI 0a8f1c8f66e113c3cf635df0a475a617) + set(MD5_PPM_420M_IFAST_ARI 72b59a99bcf1de24c5b27d151bde2437) + set(MD5_JPEG_420_ISLOW 9a68f56bc76e466aa7e52f415d0f4a5f) + set(MD5_PPM_420M_ISLOW_2_1 9f9de8c0612f8d06869b960b05abf9c9) + set(MD5_PPM_420M_ISLOW_15_8 b6875bc070720b899566cc06459b63b7) + set(MD5_PPM_420M_ISLOW_13_8 bc3452573c8152f6ae552939ee19f82f) + set(MD5_PPM_420M_ISLOW_11_8 d8cc73c0aaacd4556569b59437ba00a5) + set(MD5_PPM_420M_ISLOW_9_8 d25e61bc7eac0002f5b393aa223747b6) + set(MD5_PPM_420M_ISLOW_7_8 ddb564b7c74a09494016d6cd7502a946) + set(MD5_PPM_420M_ISLOW_3_4 8ed8e68808c3fbc4ea764fc9d2968646) + set(MD5_PPM_420M_ISLOW_5_8 a3363274999da2366a024efae6d16c9b) + set(MD5_PPM_420M_ISLOW_1_2 e692a315cea26b988c8e8b29a5dbcd81) + set(MD5_PPM_420M_ISLOW_3_8 79eca9175652ced755155c90e785a996) + set(MD5_PPM_420M_ISLOW_1_4 79cd778f8bf1a117690052cacdd54eca) + set(MD5_PPM_420M_ISLOW_1_8 391b3d4aca640c8567d6f8745eb2142f) + set(MD5_BMP_420_ISLOW_256 4980185e3776e89bd931736e1cddeee6) + set(MD5_BMP_420_ISLOW_565 bf9d13e16c4923b92e1faa604d7922cb) + set(MD5_BMP_420_ISLOW_565D 6bde71526acc44bcff76f696df8638d2) + set(MD5_BMP_420M_ISLOW_565 8dc0185245353cfa32ad97027342216f) + set(MD5_BMP_420M_ISLOW_565D d1be3a3339166255e76fa50a0d70d73e) + set(MD5_JPEG_CROP b4197f377e621c4e9b1d20471432610d) endif() -set(MD5_JPEG_420_ISLOW_ARI e986fb0a637a8d833d96e8a6d6d84ea1) -set(MD5_JPEG_444_ISLOW_PROGARI 0a8f1c8f66e113c3cf635df0a475a617) -set(MD5_PPM_420M_IFAST_ARI 72b59a99bcf1de24c5b27d151bde2437) -set(MD5_JPEG_420_ISLOW 9a68f56bc76e466aa7e52f415d0f4a5f) -set(MD5_PPM_420M_ISLOW_2_1 9f9de8c0612f8d06869b960b05abf9c9) -set(MD5_PPM_420M_ISLOW_15_8 b6875bc070720b899566cc06459b63b7) -set(MD5_PPM_420M_ISLOW_13_8 bc3452573c8152f6ae552939ee19f82f) -set(MD5_PPM_420M_ISLOW_11_8 d8cc73c0aaacd4556569b59437ba00a5) -set(MD5_PPM_420M_ISLOW_9_8 d25e61bc7eac0002f5b393aa223747b6) -set(MD5_PPM_420M_ISLOW_7_8 ddb564b7c74a09494016d6cd7502a946) -set(MD5_PPM_420M_ISLOW_3_4 8ed8e68808c3fbc4ea764fc9d2968646) -set(MD5_PPM_420M_ISLOW_5_8 a3363274999da2366a024efae6d16c9b) -set(MD5_PPM_420M_ISLOW_1_2 e692a315cea26b988c8e8b29a5dbcd81) -set(MD5_PPM_420M_ISLOW_3_8 79eca9175652ced755155c90e785a996) -set(MD5_PPM_420M_ISLOW_1_4 79cd778f8bf1a117690052cacdd54eca) -set(MD5_PPM_420M_ISLOW_1_8 391b3d4aca640c8567d6f8745eb2142f) -set(MD5_BMP_420_ISLOW_256 4980185e3776e89bd931736e1cddeee6) -set(MD5_BMP_420_ISLOW_565 bf9d13e16c4923b92e1faa604d7922cb) -set(MD5_BMP_420_ISLOW_565D 6bde71526acc44bcff76f696df8638d2) -set(MD5_BMP_420M_ISLOW_565 8dc0185245353cfa32ad97027342216f) -set(MD5_BMP_420M_ISLOW_565D d1be3a3339166255e76fa50a0d70d73e) -set(MD5_JPEG_CROP b4197f377e621c4e9b1d20471432610d) if(WITH_JAVA) add_test(TJUnitTest @@ -365,11 +424,13 @@ foreach(libtype shared static) set(dir "") set(suffix -static) endif() - add_test(tjunittest${suffix} tjunittest${suffix}) - add_test(tjunittest${suffix}-alloc tjunittest${suffix} -alloc) - add_test(tjunittest${suffix}-yuv tjunittest${suffix} -yuv) - add_test(tjunittest${suffix}-yuv-alloc tjunittest${suffix} -yuv -alloc) - add_test(tjunittest${suffix}-yuv-nopad tjunittest${suffix} -yuv -noyuvpad) + if(WITH_TURBOJPEG) + add_test(tjunittest${suffix} tjunittest${suffix}) + add_test(tjunittest${suffix}-alloc tjunittest${suffix} -alloc) + add_test(tjunittest${suffix}-yuv tjunittest${suffix} -yuv) + add_test(tjunittest${suffix}-yuv-alloc tjunittest${suffix} -yuv -alloc) + add_test(tjunittest${suffix}-yuv-nopad tjunittest${suffix} -yuv -noyuvpad) + endif() # These tests are carefully chosen to provide full coverage of as many of the # underlying algorithms as possible (including all of the SIMD-accelerated @@ -389,22 +450,24 @@ foreach(libtype shared static) add_test(djpeg${suffix}-rgb-islow-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_RGB_ISLOW} -DFILE=testout_rgb_islow.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) - # CC: RGB->RGB565 SAMP: fullsize IDCT: islow ENT: huff - add_test(djpeg${suffix}-rgb-islow-565 - ${dir}djpeg${suffix} -dct int -rgb565 -dither none -bmp - -outfile testout_rgb_islow_565.bmp testout_rgb_islow.jpg) - add_test(djpeg${suffix}-rgb-islow-565-cmp - ${CMAKE_COMMAND} -DMD5=${MD5_BMP_RGB_ISLOW_565} - -DFILE=testout_rgb_islow_565.bmp - -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) - # CC: RGB->RGB565 (dithered) SAMP: fullsize IDCT: islow ENT: huff - add_test(djpeg${suffix}-rgb-islow-565D - ${dir}djpeg${suffix} -dct int -rgb565 -bmp - -outfile testout_rgb_islow_565D.bmp testout_rgb_islow.jpg) - add_test(djpeg${suffix}-rgb-islow-565D-cmp - ${CMAKE_COMMAND} -DMD5=${MD5_BMP_RGB_ISLOW_565D} - -DFILE=testout_rgb_islow_565D.bmp - -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) + if(NOT WITH_12BIT) + # CC: RGB->RGB565 SAMP: fullsize IDCT: islow ENT: huff + add_test(djpeg${suffix}-rgb-islow-565 + ${dir}djpeg${suffix} -dct int -rgb565 -dither none -bmp + -outfile testout_rgb_islow_565.bmp testout_rgb_islow.jpg) + add_test(djpeg${suffix}-rgb-islow-565-cmp + ${CMAKE_COMMAND} -DMD5=${MD5_BMP_RGB_ISLOW_565} + -DFILE=testout_rgb_islow_565.bmp + -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) + # CC: RGB->RGB565 (dithered) SAMP: fullsize IDCT: islow ENT: huff + add_test(djpeg${suffix}-rgb-islow-565D + ${dir}djpeg${suffix} -dct int -rgb565 -bmp + -outfile testout_rgb_islow_565D.bmp testout_rgb_islow.jpg) + add_test(djpeg${suffix}-rgb-islow-565D-cmp + ${CMAKE_COMMAND} -DMD5=${MD5_BMP_RGB_ISLOW_565D} + -DFILE=testout_rgb_islow_565D.bmp + -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) + endif() # CC: RGB->YCC SAMP: fullsize/h2v1 FDCT: ifast ENT: 2-pass huff add_test(cjpeg${suffix}-422-ifast-opt @@ -429,22 +492,24 @@ foreach(libtype shared static) add_test(djpeg${suffix}-422m-ifast-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_422M_IFAST} -DFILE=testout_422m_ifast.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) - # CC: YCC->RGB565 SAMP: h2v1 merged IDCT: ifast ENT: huff - add_test(djpeg${suffix}-422m-ifast-565 - ${dir}djpeg${suffix} -dct int -nosmooth -rgb565 -dither none -bmp - -outfile testout_422m_ifast_565.bmp testout_422_ifast_opt.jpg) - add_test(djpeg${suffix}-422m-ifast-565-cmp - ${CMAKE_COMMAND} -DMD5=${MD5_BMP_422M_IFAST_565} - -DFILE=testout_422m_ifast_565.bmp - -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) - # CC: YCC->RGB565 (dithered) SAMP: h2v1 merged IDCT: ifast ENT: huff - add_test(djpeg${suffix}-422m-ifast-565D - ${dir}djpeg${suffix} -dct int -nosmooth -rgb565 -bmp - -outfile testout_422m_ifast_565D.bmp testout_422_ifast_opt.jpg) - add_test(djpeg${suffix}-422m-ifast-565D-cmp - ${CMAKE_COMMAND} -DMD5=${MD5_BMP_422M_IFAST_565D} - -DFILE=testout_422m_ifast_565D.bmp - -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) + if(NOT WITH_12BIT) + # CC: YCC->RGB565 SAMP: h2v1 merged IDCT: ifast ENT: huff + add_test(djpeg${suffix}-422m-ifast-565 + ${dir}djpeg${suffix} -dct int -nosmooth -rgb565 -dither none -bmp + -outfile testout_422m_ifast_565.bmp testout_422_ifast_opt.jpg) + add_test(djpeg${suffix}-422m-ifast-565-cmp + ${CMAKE_COMMAND} -DMD5=${MD5_BMP_422M_IFAST_565} + -DFILE=testout_422m_ifast_565.bmp + -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) + # CC: YCC->RGB565 (dithered) SAMP: h2v1 merged IDCT: ifast ENT: huff + add_test(djpeg${suffix}-422m-ifast-565D + ${dir}djpeg${suffix} -dct int -nosmooth -rgb565 -bmp + -outfile testout_422m_ifast_565D.bmp testout_422_ifast_opt.jpg) + add_test(djpeg${suffix}-422m-ifast-565D-cmp + ${CMAKE_COMMAND} -DMD5=${MD5_BMP_422M_IFAST_565D} + -DFILE=testout_422m_ifast_565D.bmp + -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) + endif() # CC: RGB->YCC SAMP: fullsize/h2v2 FDCT: ifast ENT: prog huff add_test(cjpeg${suffix}-420-q100-ifast-prog @@ -496,22 +561,24 @@ foreach(libtype shared static) ${CMAKE_COMMAND} -DMD5=${MD5_PPM_GRAY_ISLOW_RGB} -DFILE=testout_gray_islow_rgb.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) - # CC: Gray->RGB565 SAMP: fullsize IDCT: islow ENT: huff - add_test(djpeg${suffix}-gray-islow-565 - ${dir}djpeg${suffix} -dct int -rgb565 -dither none -bmp - -outfile testout_gray_islow_565.bmp testout_gray_islow.jpg) - add_test(djpeg${suffix}-gray-islow-565-cmp - ${CMAKE_COMMAND} -DMD5=${MD5_BMP_GRAY_ISLOW_565} - -DFILE=testout_gray_islow_565.bmp - -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) - # CC: Gray->RGB565 (dithered) SAMP: fullsize IDCT: islow ENT: huff - add_test(djpeg${suffix}-gray-islow-565D - ${dir}djpeg${suffix} -dct int -rgb565 -bmp - -outfile testout_gray_islow_565D.bmp testout_gray_islow.jpg) - add_test(djpeg${suffix}-gray-islow-565D-cmp - ${CMAKE_COMMAND} -DMD5=${MD5_BMP_GRAY_ISLOW_565D} - -DFILE=testout_gray_islow_565D.bmp - -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) + if(NOT WITH_12BIT) + # CC: Gray->RGB565 SAMP: fullsize IDCT: islow ENT: huff + add_test(djpeg${suffix}-gray-islow-565 + ${dir}djpeg${suffix} -dct int -rgb565 -dither none -bmp + -outfile testout_gray_islow_565.bmp testout_gray_islow.jpg) + add_test(djpeg${suffix}-gray-islow-565-cmp + ${CMAKE_COMMAND} -DMD5=${MD5_BMP_GRAY_ISLOW_565} + -DFILE=testout_gray_islow_565.bmp + -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) + # CC: Gray->RGB565 (dithered) SAMP: fullsize IDCT: islow ENT: huff + add_test(djpeg${suffix}-gray-islow-565D + ${dir}djpeg${suffix} -dct int -rgb565 -bmp + -outfile testout_gray_islow_565D.bmp testout_gray_islow.jpg) + add_test(djpeg${suffix}-gray-islow-565D-cmp + ${CMAKE_COMMAND} -DMD5=${MD5_BMP_GRAY_ISLOW_565D} + -DFILE=testout_gray_islow_565D.bmp + -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) + endif() # CC: RGB->YCC SAMP: fullsize smooth/h2v2 smooth FDCT: islow # ENT: 2-pass huff @@ -610,62 +677,63 @@ foreach(libtype shared static) add_test(djpeg${suffix}-420m-islow-${scale} ${dir}djpeg${suffix} -dct int -scale ${scalearg} -nosmooth -ppm -outfile testout_420m_islow_${scale}.ppm - ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg) + ${CMAKE_SOURCE_DIR}/testimages/${TESTORIG}) add_test(djpeg${suffix}-420m-islow-${scale}-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_420M_ISLOW_${scale}} -DFILE=testout_420m_islow_${scale}.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) endforeach() - # CC: YCC->RGB (dithered) SAMP: h2v2 fancy IDCT: islow ENT: huff - add_test(djpeg${suffix}-420-islow-256 - ${dir}djpeg${suffix} -dct int -colors 256 -bmp - -outfile testout_420_islow_256.bmp - ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg) - add_test(djpeg${suffix}-420-islow-256-cmp - ${CMAKE_COMMAND} -DMD5=${MD5_BMP_420_ISLOW_256} - -DFILE=testout_420_islow_256.bmp - -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) - # CC: YCC->RGB565 SAMP: h2v2 fancy IDCT: islow ENT: huff - add_test(djpeg${suffix}-420-islow-565 - ${dir}djpeg${suffix} -dct int -rgb565 -dither none -bmp - -outfile testout_420_islow_565.bmp - ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg) - add_test(djpeg${suffix}-420-islow-565-cmp - ${CMAKE_COMMAND} -DMD5=${MD5_BMP_420_ISLOW_565} - -DFILE=testout_420_islow_565.bmp - -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) - # CC: YCC->RGB565 (dithered) SAMP: h2v2 fancy IDCT: islow ENT: huff - add_test(djpeg${suffix}-420-islow-565D - ${dir}djpeg${suffix} -dct int -rgb565 -bmp - -outfile testout_420_islow_565D.bmp - ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg) - add_test(djpeg${suffix}-420-islow-565D-cmp - ${CMAKE_COMMAND} -DMD5=${MD5_BMP_420_ISLOW_565D} - -DFILE=testout_420_islow_565D.bmp - -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) - # CC: YCC->RGB565 SAMP: h2v2 merged IDCT: islow ENT: huff - add_test(djpeg${suffix}-420m-islow-565 - ${dir}djpeg${suffix} -dct int -nosmooth -rgb565 -dither none -bmp - -outfile testout_420m_islow_565.bmp - ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg) - add_test(djpeg${suffix}-420m-islow-565-cmp - ${CMAKE_COMMAND} -DMD5=${MD5_BMP_420M_ISLOW_565} - -DFILE=testout_420m_islow_565.bmp - -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) - # CC: YCC->RGB565 (dithered) SAMP: h2v2 merged IDCT: islow ENT: huff - add_test(djpeg${suffix}-420m-islow-565D - ${dir}djpeg${suffix} -dct int -nosmooth -rgb565 -bmp - -outfile testout_420m_islow_565D.bmp - ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg) - add_test(djpeg${suffix}-420m-islow-565D-cmp - ${CMAKE_COMMAND} -DMD5=${MD5_BMP_420M_ISLOW_565D} - -DFILE=testout_420m_islow_565D.bmp - -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) - + if(NOT WITH_12BIT) + # CC: YCC->RGB (dithered) SAMP: h2v2 fancy IDCT: islow ENT: huff + add_test(djpeg${suffix}-420-islow-256 + ${dir}djpeg${suffix} -dct int -colors 256 -bmp + -outfile testout_420_islow_256.bmp + ${CMAKE_SOURCE_DIR}/testimages/${TESTORIG}) + add_test(djpeg${suffix}-420-islow-256-cmp + ${CMAKE_COMMAND} -DMD5=${MD5_BMP_420_ISLOW_256} + -DFILE=testout_420_islow_256.bmp + -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) + # CC: YCC->RGB565 SAMP: h2v2 fancy IDCT: islow ENT: huff + add_test(djpeg${suffix}-420-islow-565 + ${dir}djpeg${suffix} -dct int -rgb565 -dither none -bmp + -outfile testout_420_islow_565.bmp + ${CMAKE_SOURCE_DIR}/testimages/${TESTORIG}) + add_test(djpeg${suffix}-420-islow-565-cmp + ${CMAKE_COMMAND} -DMD5=${MD5_BMP_420_ISLOW_565} + -DFILE=testout_420_islow_565.bmp + -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) + # CC: YCC->RGB565 (dithered) SAMP: h2v2 fancy IDCT: islow ENT: huff + add_test(djpeg${suffix}-420-islow-565D + ${dir}djpeg${suffix} -dct int -rgb565 -bmp + -outfile testout_420_islow_565D.bmp + ${CMAKE_SOURCE_DIR}/testimages/${TESTORIG}) + add_test(djpeg${suffix}-420-islow-565D-cmp + ${CMAKE_COMMAND} -DMD5=${MD5_BMP_420_ISLOW_565D} + -DFILE=testout_420_islow_565D.bmp + -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) + # CC: YCC->RGB565 SAMP: h2v2 merged IDCT: islow ENT: huff + add_test(djpeg${suffix}-420m-islow-565 + ${dir}djpeg${suffix} -dct int -nosmooth -rgb565 -dither none -bmp + -outfile testout_420m_islow_565.bmp + ${CMAKE_SOURCE_DIR}/testimages/${TESTORIG}) + add_test(djpeg${suffix}-420m-islow-565-cmp + ${CMAKE_COMMAND} -DMD5=${MD5_BMP_420M_ISLOW_565} + -DFILE=testout_420m_islow_565.bmp + -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) + # CC: YCC->RGB565 (dithered) SAMP: h2v2 merged IDCT: islow ENT: huff + add_test(djpeg${suffix}-420m-islow-565D + ${dir}djpeg${suffix} -dct int -nosmooth -rgb565 -bmp + -outfile testout_420m_islow_565D.bmp + ${CMAKE_SOURCE_DIR}/testimages/${TESTORIG}) + add_test(djpeg${suffix}-420m-islow-565D-cmp + ${CMAKE_COMMAND} -DMD5=${MD5_BMP_420M_ISLOW_565D} + -DFILE=testout_420m_islow_565D.bmp + -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) + endif() add_test(jpegtran${suffix}-crop ${dir}jpegtran${suffix} -crop 120x90+20+50 -transpose -perfect - -outfile testout_crop.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg) + -outfile testout_crop.jpg ${CMAKE_SOURCE_DIR}/testimages/${TESTORIG}) add_test(jpegtran${suffix}-crop-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_CROP} -DFILE=testout_crop.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake) @@ -721,7 +789,10 @@ add_custom_target(installer cjpeg djpeg jpegtran tjbench ${JAVA_DEPEND} SOURCES libmozjpeg.nsi) -install(TARGETS jpeg-static turbojpeg turbojpeg-static rdjpgcom wrjpgcom tjbench +if(WITH_TURBOJPEG) + set(TURBOJPEG_TARGETS turbojpeg turbojpeg-static tjbench) +endif() +install(TARGETS jpeg-static rdjpgcom wrjpgcom ${TURBOJPEG_TARGETS} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin diff --git a/ChangeLog.txt b/ChangeLog.txt index 09d88fd8..b158dc4d 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -13,13 +13,18 @@ compatibility, since 4:1:1 is not fully accelerated in libjpeg-turbo and has no significant advantages relative to 4:2:0. -- CMYK images are now supported. This feature allows CMYK source images to be compressed to YCCK JPEGs and YCCK or CMYK JPEGs to be decompressed to CMYK -destination images. Conversion between CMYK and RGB or YUV images is not -supported. Such conversion requires a color management system and is out of -scope for a codec library. +destination images. Conversion between CMYK/YCCK and RGB or YUV images is not +supported. Such conversion requires a color management system and is thus out +of scope for a codec library. -- The handling of YUV images in the Java API has been significantly refactored and should now be much more intuitive. -- The Java API now supports encoding a YUV image from an arbitrary position in a large image buffer. +-- All of the YUV functions now have a corresponding function that operates on +separate image planes instead of a unified image buffer. This allows for +compressing/decoding from or decompressing/encoding to a subregion of a larger +YUV image. It also allows for handling YUV formats that swap the order of the +U and V planes. [2] Added SIMD acceleration for DSPr2-capable MIPS platforms. This speeds up the compression of full-color JPEGs by 70-80% on such platforms and @@ -46,7 +51,7 @@ Android devices that were tested, two demonstrated a small overall performance loss (~3-4% on average) with ARMv6 code and a small gain (also ~3-4%) with ARMv7 code when enabling this new feature, but the other two devices demonstrated a significant overall performance gain with both ARMv6 and ARMv7 -code (~10-20%.) Actual mileage may vary. +code (~10-20%) when enabling the feature. Actual mileage may vary. [6] Worked around an issue with Visual C++ 2010 and later that caused incorrect pixels to be generated when decompressing a JPEG image to a 256-color bitmap, @@ -63,12 +68,12 @@ accuracy than the slow integer DCT/IDCT algorithms, and they are quite a bit slower. [8] Added a new output colorspace (JCS_RGB565) to the libjpeg API that allows -for decompressing JPEG images into RGB565 (16-bit) pixels. +for decompressing JPEG images into RGB565 (16-bit) pixels. If dithering is not +used, then this code path is SIMD-accelerated on ARM platforms. -[9] Numerous obsolete features, such as support for compilers that can't -handle prototypes and support for the MS-DOS memory model, were removed from -the libjpeg code, greatly improving its readability and making it easier to -maintain and extend. +[9] Numerous obsolete features, such as support for non-ANSI compilers and +support for the MS-DOS memory model, were removed from the libjpeg code, +greatly improving its readability and making it easier to maintain and extend. [10] Fixed a segfault that occurred when calling output_message() with msg_code set to JMSG_COPYRIGHT. @@ -78,7 +83,38 @@ characters to be passed on the command line, which was causing it to generate incorrect JPEG files. [12] Fixed a bug in the build system that was causing the Windows version of -wrjpgcom to be built using the rdjpgcom code. +wrjpgcom to be built using the rdjpgcom source code. + +[13] Restored 12-bit-per-component JPEG support. A 12-bit version of +libjpeg-turbo can now be built by passing an argument of --with-12bit to +configure (Unix) or -DWITH_12BIT=1 to cmake (Windows.) 12-bit JPEG support is +included only for convenience. Enabling this feature disables all of the +performance features in libjpeg-turbo, as well as arithmetic coding and the +TurboJPEG API. The resulting library still contains the other libjpeg-turbo +features (such as the colorspace extensions), but in general, it performs no +faster than libjpeg v6b. + +[14] Added ARM 64-bit SIMD acceleration for the YCC-to-RGB color conversion +and IDCT algorithms (both are used during JPEG decompression.) For unknown +reasons (probably related to clang), this code cannot currently be compiled for +iOS. + +[15] Fixed an extremely rare bug that could cause the Huffman encoder's local +buffer to overrun when a very high-frequency MCU is compressed using quality +100 and no subsampling, and when the JPEG output buffer is being dynamically +resized by the destination manager. This issue was so rare that, even with a +test program specifically designed to make the bug occur (by injecting random +high-frequency YUV data into the compressor), it was reproducible only once in +about every 25 million iterations. + +[16] Fixed an oversight in the TurboJPEG C wrapper: if any of the JPEG +compression functions was called repeatedly with the same +automatically-allocated destination buffer, then TurboJPEG would erroneously +assume that the jpegSize parameter was equal to the size of the buffer, when in +fact that parameter was probably equal to the size of the most recently +compressed JPEG image. If the size of the previous JPEG image was not as large +as the current JPEG image, then TurboJPEG would unnecessarily reallocate the +destination buffer. [7] Improved the accuracy and performance of the non-SIMD implementation of the floating point inverse DCT (using code borrowed from libjpeg v8a and later.) diff --git a/Makefile.am b/Makefile.am index 979c96c6..cc5435e2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -108,13 +108,19 @@ tjunittest_LDADD = libturbojpeg.la endif -cjpeg_SOURCES = cdjpeg.h cderror.h cdjpeg.c cjpeg.c rdbmp.c rdgif.c \ - rdppm.c rdswitch.c rdtarga.c rdjpeg.c +cjpeg_SOURCES = cdjpeg.h cderror.h cdjpeg.c cjpeg.c rdgif.c rdppm.c rdswitch.c rdjpeg.c +if WITH_12BIT +else +cjpeg_SOURCES += rdbmp.c rdtarga.c +endif cjpeg_LDADD = libjpeg.la -cjpeg_CFLAGS = -DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED \ - -DTARGA_SUPPORTED +cjpeg_CFLAGS = -DGIF_SUPPORTED -DPPM_SUPPORTED +if WITH_12BIT +else +cjpeg_CFLAGS += -DBMP_SUPPORTED -DTARGA_SUPPORTED +endif if HAVE_LIBPNG cjpeg_CFLAGS += -DPNG_SUPPORTED $(libpng_CFLAGS) @@ -123,12 +129,19 @@ cjpeg_SOURCES += rdpng.c endif djpeg_SOURCES = cdjpeg.h cderror.h cdjpeg.c djpeg.c rdcolmap.c rdswitch.c \ - wrbmp.c wrgif.c wrppm.c wrtarga.c + wrgif.c wrppm.c +if WITH_12BIT +else +djpeg_SOURCES += wrbmp.c wrtarga.c +endif djpeg_LDADD = libjpeg.la -djpeg_CFLAGS = -DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED \ - -DTARGA_SUPPORTED +djpeg_CFLAGS = -DGIF_SUPPORTED -DPPM_SUPPORTED +if WITH_12BIT +else +djpeg_CFLAGS += -DBMP_SUPPORTED -DTARGA_SUPPORTED +endif jpegtran_SOURCES = jpegtran.c rdswitch.c cdjpeg.c transupp.c transupp.h @@ -169,7 +182,7 @@ dist_example_DATA = example.c EXTRA_DIST = win release $(DOCS) testimages CMakeLists.txt \ sharedlib/CMakeLists.txt cmakescripts libjpeg.map.in doc doxygen.config \ - jccolext.c jdcolext.c jdcol565.c jdmrgext.c jstdhuff.c + doxygen-extra.css jccolext.c jdcolext.c jdcol565.c jdmrgext.c jstdhuff.c dist-hook: rm -rf `find $(distdir) -name .svn` @@ -177,6 +190,40 @@ dist-hook: SUBDIRS += md5 +if WITH_12BIT + +TESTORIG = testorig12.jpg +MD5_JPEG_RGB_ISLOW = 9620f424569594bb9242b48498ad801f +MD5_PPM_RGB_ISLOW = f3301d2219783b8b3d942b7239fa50c0 +MD5_JPEG_422_IFAST_OPT = 7322e3bd2f127f7de4b40d4480ce60e4 +MD5_PPM_422_IFAST = 79807fa552899e66a04708f533e16950 +MD5_PPM_422M_IFAST = 07737bfe8a7c1c87aaa393a0098d16b0 +MD5_JPEG_420_IFAST_Q100_PROG = a1da220b5604081863a504297ed59e55 +MD5_PPM_420_Q100_IFAST = 1b3730122709f53d007255e8dfd3305e +MD5_PPM_420M_Q100_IFAST = 980a1a3c5bf9510022869d30b7d26566 +MD5_JPEG_GRAY_ISLOW = 235c90707b16e2e069f37c888b2636d9 +MD5_PPM_GRAY_ISLOW = 7213c10af507ad467da5578ca5ee1fca +MD5_PPM_GRAY_ISLOW_RGB = e96ee81c30a6ed422d466338bd3de65d +MD5_JPEG_420S_IFAST_OPT = 7af8e60be4d9c227ec63ac9b6630855e +MD5_JPEG_3x2_FLOAT_PROG = a8c17daf77b457725ec929e215b603f8 +MD5_PPM_3x2_FLOAT = 42876ab9e5c2f76a87d08db5fbd57956 +MD5_PPM_420M_ISLOW_2_1 = 4ca6be2a6f326ff9eaab63e70a8259c0 +MD5_PPM_420M_ISLOW_15_8 = 12aa9f9534c1b3d7ba047322226365eb +MD5_PPM_420M_ISLOW_13_8 = f7e22817c7b25e1393e4ec101e9d4e96 +MD5_PPM_420M_ISLOW_11_8 = 800a16f9f4dc9b293197bfe11be10a82 +MD5_PPM_420M_ISLOW_9_8 = 06b7a92a9bc69f4dc36ec40f1937d55c +MD5_PPM_420M_ISLOW_7_8 = 3ec444a14a4ab4eab88ffc49c48eca43 +MD5_PPM_420M_ISLOW_3_4 = 3e726b7ea872445b19437d1c1d4f0d93 +MD5_PPM_420M_ISLOW_5_8 = a8a771abdc94301d20ffac119b2caccd +MD5_PPM_420M_ISLOW_1_2 = b419124dd5568b085787234866102866 +MD5_PPM_420M_ISLOW_3_8 = 343d19015531b7bbe746124127244fa8 +MD5_PPM_420M_ISLOW_1_4 = 35fd59d866e44659edfa3c18db2a3edb +MD5_PPM_420M_ISLOW_1_8 = ccaed48ac0aedefda5d4abe4013f4ad7 +MD5_JPEG_CROP = cdb35ff4b4519392690ea040c56ea99c + +else + +TESTORIG = testorig.jpg MD5_JPEG_RGB_ISLOW = 768e970dd57b340ff1b83c9d3d47c77b MD5_PPM_RGB_ISLOW = 00a257f5393fef8821f2b88ac7421291 MD5_BMP_RGB_ISLOW_565 = f07d2e75073e4bb10f6c6f4d36e2e3be @@ -226,6 +273,8 @@ MD5_BMP_420M_ISLOW_565 = 8dc0185245353cfa32ad97027342216f MD5_BMP_420M_ISLOW_565D =d1be3a3339166255e76fa50a0d70d73e MD5_JPEG_CROP = b4197f377e621c4e9b1d20471432610d +endif + test: testclean all if WITH_TURBOJPEG @@ -255,6 +304,9 @@ endif ./djpeg -dct int -ppm -outfile testout_rgb_islow.ppm testout_rgb_islow.jpg md5/md5cmp $(MD5_PPM_RGB_ISLOW) testout_rgb_islow.ppm rm testout_rgb_islow.ppm +if WITH_12BIT + rm testout_rgb_islow.jpg +else # CC: RGB->RGB565 SAMP: fullsize IDCT: islow ENT: huff ./djpeg -dct int -rgb565 -dither none -bmp -outfile testout_rgb_islow_565.bmp testout_rgb_islow.jpg md5/md5cmp $(MD5_BMP_RGB_ISLOW_565) testout_rgb_islow_565.bmp @@ -263,6 +315,7 @@ endif ./djpeg -dct int -rgb565 -bmp -outfile testout_rgb_islow_565D.bmp testout_rgb_islow.jpg md5/md5cmp $(MD5_BMP_RGB_ISLOW_565D) testout_rgb_islow_565D.bmp rm testout_rgb_islow_565D.bmp testout_rgb_islow.jpg +endif # CC: RGB->YCC SAMP: fullsize/h2v1 FDCT: ifast ENT: 2-pass huff ./cjpeg -sample 2x1 -dct fast -opt -outfile testout_422_ifast_opt.jpg $(srcdir)/testimages/testorig.ppm @@ -275,6 +328,9 @@ endif ./djpeg -dct fast -nosmooth -outfile testout_422m_ifast.ppm testout_422_ifast_opt.jpg md5/md5cmp $(MD5_PPM_422M_IFAST) testout_422m_ifast.ppm rm testout_422m_ifast.ppm +if WITH_12BIT + rm testout_422_ifast_opt.jpg +else # CC: YCC->RGB565 SAMP: h2v1 merged IDCT: ifast ENT: huff ./djpeg -dct int -nosmooth -rgb565 -dither none -bmp -outfile testout_422m_ifast_565.bmp testout_422_ifast_opt.jpg md5/md5cmp $(MD5_BMP_422M_IFAST_565) testout_422m_ifast_565.bmp @@ -283,6 +339,7 @@ endif ./djpeg -dct int -nosmooth -rgb565 -bmp -outfile testout_422m_ifast_565D.bmp testout_422_ifast_opt.jpg md5/md5cmp $(MD5_BMP_422M_IFAST_565D) testout_422m_ifast_565D.bmp rm testout_422m_ifast_565D.bmp testout_422_ifast_opt.jpg +endif # CC: RGB->YCC SAMP: fullsize/h2v2 FDCT: ifast ENT: prog huff ./cjpeg -sample 2x2 -quality 100 -dct fast -prog -outfile testout_420_q100_ifast_prog.jpg $(srcdir)/testimages/testorig.ppm @@ -307,6 +364,9 @@ endif ./djpeg -dct int -rgb -outfile testout_gray_islow_rgb.ppm testout_gray_islow.jpg md5/md5cmp $(MD5_PPM_GRAY_ISLOW_RGB) testout_gray_islow_rgb.ppm rm testout_gray_islow_rgb.ppm +if WITH_12BIT + rm testout_gray_islow.jpg +else # CC: Gray->RGB565 SAMP: fullsize IDCT: islow ENT: huff ./djpeg -dct int -rgb565 -dither none -bmp -outfile testout_gray_islow_565.bmp testout_gray_islow.jpg md5/md5cmp $(MD5_BMP_GRAY_ISLOW_565) testout_gray_islow_565.bmp @@ -315,6 +375,7 @@ endif ./djpeg -dct int -rgb565 -bmp -outfile testout_gray_islow_565D.bmp testout_gray_islow.jpg md5/md5cmp $(MD5_BMP_GRAY_ISLOW_565D) testout_gray_islow_565D.bmp rm testout_gray_islow_565D.bmp testout_gray_islow.jpg +endif # CC: RGB->YCC SAMP: fullsize smooth/h2v2 smooth FDCT: islow # ENT: 2-pass huff @@ -354,75 +415,78 @@ if WITH_ARITH_DEC endif # CC: YCC->RGB SAMP: h2v2 merged IDCT: 16x16 islow ENT: huff - ./djpeg -dct int -scale 2/1 -nosmooth -ppm -outfile testout_420m_islow_2_1.ppm $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -scale 2/1 -nosmooth -ppm -outfile testout_420m_islow_2_1.ppm $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_PPM_420M_ISLOW_2_1) testout_420m_islow_2_1.ppm rm testout_420m_islow_2_1.ppm # CC: YCC->RGB SAMP: h2v2 merged IDCT: 15x15 islow ENT: huff - ./djpeg -dct int -scale 15/8 -nosmooth -ppm -outfile testout_420m_islow_15_8.ppm $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -scale 15/8 -nosmooth -ppm -outfile testout_420m_islow_15_8.ppm $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_PPM_420M_ISLOW_15_8) testout_420m_islow_15_8.ppm rm testout_420m_islow_15_8.ppm # CC: YCC->RGB SAMP: h2v2 merged IDCT: 13x13 islow ENT: huff - ./djpeg -dct int -scale 13/8 -nosmooth -ppm -outfile testout_420m_islow_13_8.ppm $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -scale 13/8 -nosmooth -ppm -outfile testout_420m_islow_13_8.ppm $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_PPM_420M_ISLOW_13_8) testout_420m_islow_13_8.ppm rm testout_420m_islow_13_8.ppm # CC: YCC->RGB SAMP: h2v2 merged IDCT: 11x11 islow ENT: huff - ./djpeg -dct int -scale 11/8 -nosmooth -ppm -outfile testout_420m_islow_11_8.ppm $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -scale 11/8 -nosmooth -ppm -outfile testout_420m_islow_11_8.ppm $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_PPM_420M_ISLOW_11_8) testout_420m_islow_11_8.ppm rm testout_420m_islow_11_8.ppm # CC: YCC->RGB SAMP: h2v2 merged IDCT: 9x9 islow ENT: huff - ./djpeg -dct int -scale 9/8 -nosmooth -ppm -outfile testout_420m_islow_9_8.ppm $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -scale 9/8 -nosmooth -ppm -outfile testout_420m_islow_9_8.ppm $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_PPM_420M_ISLOW_9_8) testout_420m_islow_9_8.ppm rm testout_420m_islow_9_8.ppm # CC: YCC->RGB SAMP: h2v2 merged IDCT: 7x7 islow/14x14 islow ENT: huff - ./djpeg -dct int -scale 7/8 -nosmooth -ppm -outfile testout_420m_islow_7_8.ppm $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -scale 7/8 -nosmooth -ppm -outfile testout_420m_islow_7_8.ppm $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_PPM_420M_ISLOW_7_8) testout_420m_islow_7_8.ppm rm testout_420m_islow_7_8.ppm # CC: YCC->RGB SAMP: h2v2 merged IDCT: 6x6 islow/12x12 islow ENT: huff - ./djpeg -dct int -scale 3/4 -nosmooth -ppm -outfile testout_420m_islow_3_4.ppm $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -scale 3/4 -nosmooth -ppm -outfile testout_420m_islow_3_4.ppm $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_PPM_420M_ISLOW_3_4) testout_420m_islow_3_4.ppm rm testout_420m_islow_3_4.ppm # CC: YCC->RGB SAMP: h2v2 merged IDCT: 5x5 islow/10x10 islow ENT: huff - ./djpeg -dct int -scale 5/8 -nosmooth -ppm -outfile testout_420m_islow_5_8.ppm $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -scale 5/8 -nosmooth -ppm -outfile testout_420m_islow_5_8.ppm $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_PPM_420M_ISLOW_5_8) testout_420m_islow_5_8.ppm rm testout_420m_islow_5_8.ppm # CC: YCC->RGB SAMP: h2v2 merged IDCT: 4x4 islow/8x8 islow ENT: huff - ./djpeg -dct int -scale 1/2 -nosmooth -ppm -outfile testout_420m_islow_1_2.ppm $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -scale 1/2 -nosmooth -ppm -outfile testout_420m_islow_1_2.ppm $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_PPM_420M_ISLOW_1_2) testout_420m_islow_1_2.ppm rm testout_420m_islow_1_2.ppm # CC: YCC->RGB SAMP: h2v2 merged IDCT: 3x3 islow/6x6 islow ENT: huff - ./djpeg -dct int -scale 3/8 -nosmooth -ppm -outfile testout_420m_islow_3_8.ppm $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -scale 3/8 -nosmooth -ppm -outfile testout_420m_islow_3_8.ppm $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_PPM_420M_ISLOW_3_8) testout_420m_islow_3_8.ppm rm testout_420m_islow_3_8.ppm # CC: YCC->RGB SAMP: h2v2 merged IDCT: 2x2 islow/4x4 islow ENT: huff - ./djpeg -dct int -scale 1/4 -nosmooth -ppm -outfile testout_420m_islow_1_4.ppm $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -scale 1/4 -nosmooth -ppm -outfile testout_420m_islow_1_4.ppm $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_PPM_420M_ISLOW_1_4) testout_420m_islow_1_4.ppm rm testout_420m_islow_1_4.ppm # CC: YCC->RGB SAMP: h2v2 merged IDCT: 1x1 islow/2x2 islow ENT: huff - ./djpeg -dct int -scale 1/8 -nosmooth -ppm -outfile testout_420m_islow_1_8.ppm $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -scale 1/8 -nosmooth -ppm -outfile testout_420m_islow_1_8.ppm $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_PPM_420M_ISLOW_1_8) testout_420m_islow_1_8.ppm rm testout_420m_islow_1_8.ppm +if WITH_12BIT +else # CC: YCC->RGB (dithered) SAMP: h2v2 fancy IDCT: islow ENT: huff - ./djpeg -dct int -colors 256 -bmp -outfile testout_420_islow_256.bmp $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -colors 256 -bmp -outfile testout_420_islow_256.bmp $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_BMP_420_ISLOW_256) testout_420_islow_256.bmp rm testout_420_islow_256.bmp # CC: YCC->RGB565 SAMP: h2v2 fancy IDCT: islow ENT: huff - ./djpeg -dct int -rgb565 -dither none -bmp -outfile testout_420_islow_565.bmp $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -rgb565 -dither none -bmp -outfile testout_420_islow_565.bmp $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_BMP_420_ISLOW_565) testout_420_islow_565.bmp rm testout_420_islow_565.bmp # CC: YCC->RGB565 (dithered) SAMP: h2v2 fancy IDCT: islow ENT: huff - ./djpeg -dct int -rgb565 -bmp -outfile testout_420_islow_565D.bmp $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -rgb565 -bmp -outfile testout_420_islow_565D.bmp $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_BMP_420_ISLOW_565D) testout_420_islow_565D.bmp rm testout_420_islow_565D.bmp # CC: YCC->RGB565 SAMP: h2v2 merged IDCT: islow ENT: huff - ./djpeg -dct int -nosmooth -rgb565 -dither none -bmp -outfile testout_420m_islow_565.bmp $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -nosmooth -rgb565 -dither none -bmp -outfile testout_420m_islow_565.bmp $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_BMP_420M_ISLOW_565) testout_420m_islow_565.bmp rm testout_420m_islow_565.bmp # CC: YCC->RGB565 (dithered) SAMP: h2v2 merged IDCT: islow ENT: huff - ./djpeg -dct int -nosmooth -rgb565 -bmp -outfile testout_420m_islow_565D.bmp $(srcdir)/testimages/testorig.jpg + ./djpeg -dct int -nosmooth -rgb565 -bmp -outfile testout_420m_islow_565D.bmp $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_BMP_420M_ISLOW_565D) testout_420m_islow_565D.bmp rm testout_420m_islow_565D.bmp +endif - ./jpegtran -crop 120x90+20+50 -transpose -perfect -outfile testout_crop.jpg $(srcdir)/testimages/testorig.jpg + ./jpegtran -crop 120x90+20+50 -transpose -perfect -outfile testout_crop.jpg $(srcdir)/testimages/$(TESTORIG) md5/md5cmp $(MD5_JPEG_CROP) testout_crop.jpg rm testout_crop.jpg @@ -463,7 +527,9 @@ testclean: tjtest: sh ./tjbenchtest + sh ./tjbenchtest -alloc sh ./tjbenchtest -yuv + sh ./tjbenchtest -yuv -alloc if WITH_JAVA sh ./tjbenchtest.java sh ./tjbenchtest.java -yuv diff --git a/acinclude.m4 b/acinclude.m4 index 8d667849..4a130825 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -219,6 +219,7 @@ AC_DEFUN([AC_CHECK_COMPATIBLE_ARM64_ASSEMBLER_IFELSE],[ CC="$CCAS" AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ .text + .arch armv8-a+fp+simd movi v0.16b, #100]])], ac_good_gnu_arm_assembler=yes) ac_use_gas_preprocessor=no @@ -226,6 +227,7 @@ AC_DEFUN([AC_CHECK_COMPATIBLE_ARM64_ASSEMBLER_IFELSE],[ CC="gas-preprocessor.pl $CCAS" AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ .text + .arch armv8-a+fp+simd movi v0.16b, #100]])], ac_use_gas_preprocessor=yes) fi CFLAGS="$ac_save_CFLAGS" diff --git a/configure.ac b/configure.ac index 0973aece..12387c6a 100644 --- a/configure.ac +++ b/configure.ac @@ -275,6 +275,9 @@ AC_MSG_CHECKING([whether to include arithmetic encoding support]) AC_ARG_WITH([arith-enc], AC_HELP_STRING([--without-arith-enc], [Do not include arithmetic encoding support])) +if test "x$with_12bit" = "xyes"; then + with_arith_enc=no +fi if test "x$with_arith_enc" = "xno"; then AC_MSG_RESULT(no) RPM_CONFIG_ARGS="$RPM_CONFIG_ARGS --without-arith-enc" @@ -288,6 +291,9 @@ AC_MSG_CHECKING([whether to include arithmetic decoding support]) AC_ARG_WITH([arith-dec], AC_HELP_STRING([--without-arith-dec], [Do not include arithmetic decoding support])) +if test "x$with_12bit" = "xyes"; then + with_arith_dec=no +fi if test "x$with_arith_dec" = "xno"; then AC_MSG_RESULT(no) RPM_CONFIG_ARGS="$RPM_CONFIG_ARGS --without-arith-dec" @@ -300,11 +306,26 @@ AM_CONDITIONAL([WITH_ARITH_DEC], [test "x$with_arith_dec" != "xno"]) AM_CONDITIONAL([WITH_ARITH], [test "x$with_arith_dec" != "xno" -o "x$with_arith_enc" != "xno"]) +# 12-bit component support +AC_MSG_CHECKING([whether to use 12-bit samples]) +AC_ARG_WITH([12bit], + AC_HELP_STRING([--with-12bit], [Encode/decode JPEG images with 12-bit samples (implies --without-simd --without-turbojpeg --without-arith-dec --without-arith-enc)])) +if test "x$with_12bit" = "xyes"; then + AC_DEFINE([BITS_IN_JSAMPLE], [12], [use 8 or 12]) + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi +AM_CONDITIONAL([WITH_12BIT], [test "x$with_12bit" = "xyes"]) + # TurboJPEG support AC_MSG_CHECKING([whether to build TurboJPEG C wrapper]) AC_ARG_WITH([turbojpeg], AC_HELP_STRING([--without-turbojpeg], [Do not include the TurboJPEG wrapper library and associated test programs])) +if test "x$with_12bit" = "xyes"; then + with_turbojpeg=no +fi if test "x$with_turbojpeg" = "xno"; then AC_MSG_RESULT(no) RPM_CONFIG_ARGS="$RPM_CONFIG_ARGS --without-turbojpeg" @@ -336,7 +357,7 @@ AC_ARG_VAR(JNI_CFLAGS, AC_MSG_CHECKING([whether to build TurboJPEG Java wrapper]) AC_ARG_WITH([java], AC_HELP_STRING([--with-java], [Build Java wrapper for the TurboJPEG library])) -if test "x$with_turbojpeg" = "xno"; then +if test "x$with_12bit" = "xyes" -o "x$with_turbojpeg" = "xno"; then with_java=no fi @@ -397,6 +418,9 @@ fi # SIMD is optional AC_ARG_WITH([simd], AC_HELP_STRING([--without-simd], [Do not include SIMD extensions])) +if test "x$with_12bit" = "xyes"; then + with_simd=no +fi if test "x${with_simd}" != "xno"; then require_simd=no if test "x${with_simd}" = "xyes"; then diff --git a/doc/html/annotated.html b/doc/html/annotated.html index f9287209..dad0fb16 100644 --- a/doc/html/annotated.html +++ b/doc/html/annotated.html @@ -14,6 +14,7 @@ $(document).ready(function() { searchBox.OnSelectItem(0); }); +
diff --git a/doc/html/classes.html b/doc/html/classes.html index ad625f12..7720c671 100644 --- a/doc/html/classes.html +++ b/doc/html/classes.html @@ -14,6 +14,7 @@ $(document).ready(function() { searchBox.OnSelectItem(0); }); +
diff --git a/doc/html/doxygen-extra.css b/doc/html/doxygen-extra.css new file mode 100644 index 00000000..5abbcc21 --- /dev/null +++ b/doc/html/doxygen-extra.css @@ -0,0 +1,3 @@ +code { + color: #4665A2; +} diff --git a/doc/html/functions.html b/doc/html/functions.html index 55ccba08..b13faed8 100644 --- a/doc/html/functions.html +++ b/doc/html/functions.html @@ -14,6 +14,7 @@ $(document).ready(function() { searchBox.OnSelectItem(0); }); +
diff --git a/doc/html/functions_vars.html b/doc/html/functions_vars.html index cdc55604..cca5603f 100644 --- a/doc/html/functions_vars.html +++ b/doc/html/functions_vars.html @@ -14,6 +14,7 @@ $(document).ready(function() { searchBox.OnSelectItem(0); }); +
diff --git a/doc/html/group___turbo_j_p_e_g.html b/doc/html/group___turbo_j_p_e_g.html index 6936e5df..7188c7d6 100644 --- a/doc/html/group___turbo_j_p_e_g.html +++ b/doc/html/group___turbo_j_p_e_g.html @@ -14,6 +14,7 @@ $(document).ready(function() { searchBox.OnSelectItem(0); }); +
@@ -231,15 +232,30 @@ Functions DLLEXPORT int DLLCALL tjCompressFromYUV (tjhandle handle, unsigned char *srcBuf, int width, int pad, int height, int subsamp, unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual, int flags)  Compress a YUV planar image into a JPEG image. More...
  +DLLEXPORT int DLLCALL tjCompressFromYUVPlanes (tjhandle handle, unsigned char **srcPlanes, int width, int *strides, int height, int subsamp, unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual, int flags) + Compress a set of Y, U (Cb), and V (Cr) image planes into a JPEG image. More...
+  DLLEXPORT unsigned long DLLCALL tjBufSize (int width, int height, int jpegSubsamp)  The maximum size of the buffer (in bytes) required to hold a JPEG image with the given parameters. More...
  DLLEXPORT unsigned long DLLCALL tjBufSizeYUV2 (int width, int pad, int height, int subsamp)  The size of the buffer (in bytes) required to hold a YUV planar image with the given parameters. More...
  +DLLEXPORT unsigned long DLLCALL tjPlaneSizeYUV (int componentID, int width, int stride, int height, int subsamp) + The size of the buffer (in bytes) required to hold a YUV image plane with the given parameters. More...
+  +DLLEXPORT int tjPlaneWidth (int componentID, int width, int subsamp) + The plane width of a YUV image plane with the given parameters. More...
+  +DLLEXPORT int tjPlaneHeight (int componentID, int height, int subsamp) + The plane height of a YUV image plane with the given parameters. More...
+  DLLEXPORT int DLLCALL tjEncodeYUV3 (tjhandle handle, unsigned char *srcBuf, int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf, int pad, int subsamp, int flags)  Encode an RGB or grayscale image into a YUV planar image. More...
  +DLLEXPORT int DLLCALL tjEncodeYUVPlanes (tjhandle handle, unsigned char *srcBuf, int width, int pitch, int height, int pixelFormat, unsigned char **dstPlanes, int *strides, int subsamp, int flags) + Encode an RGB or grayscale image into separate Y, U (Cb), and V (Cr) image planes. More...
+  DLLEXPORT tjhandle DLLCALL tjInitDecompress (void)  Create a TurboJPEG decompressor instance. More...
  @@ -255,9 +271,15 @@ Functions DLLEXPORT int DLLCALL tjDecompressToYUV2 (tjhandle handle, unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf, int width, int pad, int height, int flags)  Decompress a JPEG image to a YUV planar image. More...
  +DLLEXPORT int DLLCALL tjDecompressToYUVPlanes (tjhandle handle, unsigned char *jpegBuf, unsigned long jpegSize, unsigned char **dstPlanes, int width, int *strides, int height, int flags) + Decompress a JPEG image into separate Y, U (Cb), and V (Cr) image planes. More...
+  DLLEXPORT int DLLCALL tjDecodeYUV (tjhandle handle, unsigned char *srcBuf, int pad, int subsamp, unsigned char *dstBuf, int width, int pitch, int height, int pixelFormat, int flags)  Decode a YUV planar image into an RGB or grayscale image. More...
  +DLLEXPORT int DLLCALL tjDecodeYUVPlanes (tjhandle handle, unsigned char **srcPlanes, int *strides, int subsamp, unsigned char *dstBuf, int width, int pitch, int height, int pixelFormat, int flags) + Decode a set of Y, U (Cb), and V (Cr) image planes into an RGB or grayscale image. More...
+  DLLEXPORT tjhandle DLLCALL tjInitTransform (void)  Create a new TurboJPEG transformer instance. More...
  @@ -300,7 +322,12 @@ Variables

Detailed Description

TurboJPEG API.

-

This API provides an interface for generating, decoding, and transforming planar YUV and JPEG images in memory.

+

This API provides an interface for generating, decoding, and transforming planar YUV and JPEG images in memory.

+

+

YUV Image Format Notes

+

Technically, the JPEG format uses the YCbCr colorspace (which is technically not a colorspace but a color transform), but per the convention of the digital video community, the TurboJPEG API uses "YUV" to refer to an image format consisting of Y, Cb, and Cr image planes.

+

Each plane is simply a 2D array of bytes, each byte representing the value of one of the components (Y, Cb, or Cr) at a particular location in the image. The width and height of each plane are determined by the image width, height, and level of chrominance subsampling. The luminance plane width is the image width padded to the nearest multiple of the horizontal subsampling factor (2 in the case of 4:2:0 and 4:2:2, 4 in the case of 4:1:1, 1 in the case of 4:4:4 or grayscale.) Similarly, the luminance plane height is the image height padded to the nearest multiple of the vertical subsampling factor (2 in the case of 4:2:0 or 4:4:0, 1 in the case of 4:4:4 or grayscale.) This is irrespective of any additional padding that may be specified as an argument to the various YUV functions. The chrominance plane width is equal to the luminance plane width divided by the horizontal subsampling factor, and the chrominance plane height is equal to the luminance plane height divided by the vertical subsampling factor.

+

For example, if the source image is 35 x 35 pixels and 4:2:2 subsampling is used, then the luminance plane would be 36 x 35 bytes, and each of the chrominance planes would be 18 x 35 bytes. If you specify a line padding of 4 bytes on top of this, then the luminance plane would be 36 x 35 bytes, and each of the chrominance planes would be 20 x 35 bytes.

Macro Definition Documentation

@@ -693,7 +720,6 @@ Variables

Chrominance subsampling options.

When pixels are converted from RGB to YCbCr (see TJCS_YCbCr) or from CMYK to YCCK (see TJCS_YCCK) as part of the JPEG compression process, some of the Cb and Cr (chrominance) components can be discarded or averaged together to produce a smaller image with little perceptible loss of image clarity (the human eye is more sensitive to small changes in brightness than to small changes in color.) This is called "chrominance subsampling".

-

NOTE: Technically, the JPEG format uses the YCbCr colorspace, but per the convention of the digital video community, the TurboJPEG API uses "YUV" to refer to an image format consisting of Y, Cb, and Cr image planes.

Enumerator
TJSAMP_444 

4:4:4 chrominance subsampling (no chrominance subsampling).

@@ -713,11 +739,13 @@ Variables
TJSAMP_440 

4:4:0 chrominance subsampling.

-

The JPEG or YUV image will contain one chrominance component for every 1x2 block of pixels in the source image. Note that 4:4:0 subsampling is not fully accelerated in libjpeg-turbo.

+

The JPEG or YUV image will contain one chrominance component for every 1x2 block of pixels in the source image.

+
Note
4:4:0 subsampling is not fully accelerated in libjpeg-turbo.
TJSAMP_411 

4:1:1 chrominance subsampling.

-

The JPEG or YUV image will contain one chrominance component for every 4x1 block of pixels in the source image. JPEG images compressed with 4:1:1 subsampling will be almost exactly the same size as those compressed with 4:2:0 subsampling, and in the aggregate, both subsampling methods produce approximately the same perceptual quality. However, 4:1:1 is better able to reproduce sharp horizontal features. Note that 4:1:1 subsampling is not fully accelerated in libjpeg-turbo.

+

The JPEG or YUV image will contain one chrominance component for every 4x1 block of pixels in the source image. JPEG images compressed with 4:1:1 subsampling will be almost exactly the same size as those compressed with 4:2:0 subsampling, and in the aggregate, both subsampling methods produce approximately the same perceptual quality. However, 4:1:1 is better able to reproduce sharp horizontal features.

+
Note
4:1:1 subsampling is not fully accelerated in libjpeg-turbo.
@@ -791,7 +819,7 @@ Variables -
Returns
a pointer to a newly-allocated buffer with the specified number of bytes
+
Returns
a pointer to a newly-allocated buffer with the specified number of bytes.
See Also
tjFree()
@@ -830,8 +858,8 @@ Variables

The number of bytes returned by this function is larger than the size of the uncompressed source image. The reason for this is that the JPEG format uses 16-bit coefficients, and it is thus possible for a very high-quality JPEG image with very high-frequency content to expand rather than compress when converted to the JPEG format. Such images represent a very rare corner case, but since there is no way to predict the size of a JPEG image prior to compression, the corner case has to be handled.

Parameters
- - + +
widthwidth of the image (in pixels)
heightheight of the image (in pixels)
widthwidth (in pixels) of the image
heightheight (in pixels) of the image
jpegSubsampthe level of chrominance subsampling to be used when generating the JPEG image (see Chrominance subsampling options.)
@@ -879,9 +907,9 @@ Variables

The size of the buffer (in bytes) required to hold a YUV planar image with the given parameters.

Parameters
- - - + + +
widthwidth of the image (in pixels)
padthe width of each line in each plane of the image is padded to the nearest multiple of this number of bytes (must be a power of 2.)
heightheight of the image (in pixels)
widthwidth (in pixels) of the image
padthe width of each line in each plane of the image is padded to the nearest multiple of this number of bytes (must be a power of 2.)
heightheight (in pixels) of the image
subsamplevel of chrominance subsampling in the image (see Chrominance subsampling options.)
@@ -971,22 +999,22 @@ Variables

Compress an RGB, grayscale, or CMYK image into a JPEG image.

Parameters
- - - - - - + + + + + + - - - - +If you choose option 1, *jpegSize should be set to the size of your pre-allocated buffer. In any case, unless you have set TJFLAG_NOREALLOC, you should always check *jpegBuf upon return from this function, as it may have changed. + + + +
handlea handle to a TurboJPEG compressor or transformer instance
srcBufpointer to an image buffer containing RGB, grayscale, or CMYK pixels to be compressed
widthwidth (in pixels) of the source image
pitchbytes per line of the source image. Normally, this should be width * tjPixelSize[pixelFormat] if the image is unpadded, or TJPAD(width * tjPixelSize[pixelFormat]) if each line of the image is padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. You can also be clever and use this parameter to skip lines, etc. Setting this parameter to 0 is the equivalent of setting it to width * tjPixelSize[pixelFormat].
heightheight (in pixels) of the source image
pixelFormatpixel format of the source image (see Pixel formats.)
handlea handle to a TurboJPEG compressor or transformer instance
srcBufpointer to an image buffer containing RGB, grayscale, or CMYK pixels to be compressed
widthwidth (in pixels) of the source image
pitchbytes per line in the source image. Normally, this should be width * tjPixelSize[pixelFormat] if the image is unpadded, or TJPAD(width * tjPixelSize[pixelFormat]) if each line of the image is padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. You can also be clever and use this parameter to skip lines, etc. Setting this parameter to 0 is the equivalent of setting it to width * tjPixelSize[pixelFormat].
heightheight (in pixels) of the source image
pixelFormatpixel format of the source image (see Pixel formats.)
jpegBufaddress of a pointer to an image buffer that will receive the JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to accommodate the size of the JPEG image. Thus, you can choose to:
  1. pre-allocate the JPEG buffer with an arbitrary size using tjAlloc() and let TurboJPEG grow the buffer as needed,
  2. set *jpegBuf to NULL to tell TurboJPEG to allocate the buffer for you, or
  3. pre-allocate the buffer to a "worst case" size determined by calling tjBufSize(). This should ensure that the buffer never has to be re-allocated (setting TJFLAG_NOREALLOC guarantees this.)
-If you choose option 1, *jpegSize should be set to the size of your pre-allocated buffer. In any case, unless you have set TJFLAG_NOREALLOC, you should always check *jpegBuf upon return from this function, as it may have changed.
jpegSizepointer to an unsigned long variable that holds the size of the JPEG image buffer. If *jpegBuf points to a pre-allocated buffer, then *jpegSize should be set to the size of the buffer. Upon return, *jpegSize will contain the size of the JPEG image (in bytes.)
jpegSubsampthe level of chrominance subsampling to be used when generating the JPEG image (see Chrominance subsampling options.)
jpegQualthe image quality of the generated JPEG image (1 = worst, 100 = best)
flagsthe bitwise OR of one or more of the flags.
jpegSizepointer to an unsigned long variable that holds the size of the JPEG image buffer. If *jpegBuf points to a pre-allocated buffer, then *jpegSize should be set to the size of the buffer. Upon return, *jpegSize will contain the size of the JPEG image (in bytes.) If *jpegBuf points to a JPEG image buffer that is being reused from a previous call to one of the JPEG compression functions, then *jpegSize is ignored.
jpegSubsampthe level of chrominance subsampling to be used when generating the JPEG image (see Chrominance subsampling options.)
jpegQualthe image quality of the generated JPEG image (1 = worst, 100 = best)
flagsthe bitwise OR of one or more of the flags
@@ -1067,24 +1095,120 @@ If you choose option 1, *jpegSize should be set to the size of your

Compress a YUV planar image into a JPEG image.

-

Note that, if the width or height of the YUV image is not an even multiple of the MCU block size (see tjMCUWidth and tjMCUHeight), then an intermediate buffer copy will be performed within TurboJPEG.

Parameters
- - - - - - + + + + + + - - - +If you choose option 1, *jpegSize should be set to the size of your pre-allocated buffer. In any case, unless you have set TJFLAG_NOREALLOC, you should always check *jpegBuf upon return from this function, as it may have changed. + + + +
handlea handle to a TurboJPEG compressor or transformer instance
srcBufpointer to an image buffer containing a YUV planar image to be compressed. The Y, U (Cb), and V (Cr) image planes should be stored sequentially in the buffer, and the size of each plane is determined by the specified width, height, padding, and level of chrominance subsampling. If the chrominance components are subsampled along the horizontal dimension, then the width of the luminance plane should be padded to the nearest multiple of 2 (same goes for the height of the luminance plane, if the chrominance components are subsampled along the vertical dimension.) This is irrespective of any additional padding specified in the pad parameter.
widthwidth (in pixels) of the source image
padthe line padding used in the source image. For instance, if each line in each plane of the YUV image is padded to the nearest multiple of 4 bytes, then pad should be set to 4.
heightheight (in pixels) of the source image
subsampthe level of chrominance subsampling used in the source image (see Chrominance subsampling options.)
handlea handle to a TurboJPEG compressor or transformer instance
srcBufpointer to an image buffer containing a YUV planar image to be compressed. The size of this buffer should match the value returned by tjBufSizeYUV2() for the given image width, height, padding, and level of chrominance subsampling. The Y, U (Cb), and V (Cr) image planes should be stored sequentially in the source buffer (refer to YUV Image Format Notes.)
widthwidth (in pixels) of the source image. If the width is not an even multiple of the MCU block width (see tjMCUWidth), then an intermediate buffer copy will be performed within TurboJPEG.
padthe line padding used in the source image. For instance, if each line in each plane of the YUV image is padded to the nearest multiple of 4 bytes, then pad should be set to 4.
heightheight (in pixels) of the source image. If the height is not an even multiple of the MCU block height (see tjMCUHeight), then an intermediate buffer copy will be performed within TurboJPEG.
subsampthe level of chrominance subsampling used in the source image (see Chrominance subsampling options.)
jpegBufaddress of a pointer to an image buffer that will receive the JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to accommodate the size of the JPEG image. Thus, you can choose to:
  1. pre-allocate the JPEG buffer with an arbitrary size using tjAlloc() and let TurboJPEG grow the buffer as needed,
  2. set *jpegBuf to NULL to tell TurboJPEG to allocate the buffer for you, or
  3. pre-allocate the buffer to a "worst case" size determined by calling tjBufSize(). This should ensure that the buffer never has to be re-allocated (setting TJFLAG_NOREALLOC guarantees this.)
-If you choose option 1, *jpegSize should be set to the size of your pre-allocated buffer. In any case, unless you have set TJFLAG_NOREALLOC, you should always check *jpegBuf upon return from this function, as it may have changed.
jpegSizepointer to an unsigned long variable that holds the size of the JPEG image buffer. If *jpegBuf points to a pre-allocated buffer, then *jpegSize should be set to the size of the buffer. Upon return, *jpegSize will contain the size of the JPEG image (in bytes.)
jpegQualthe image quality of the generated JPEG image (1 = worst, 100 = best)
flagsthe bitwise OR of one or more of the flags.
jpegSizepointer to an unsigned long variable that holds the size of the JPEG image buffer. If *jpegBuf points to a pre-allocated buffer, then *jpegSize should be set to the size of the buffer. Upon return, *jpegSize will contain the size of the JPEG image (in bytes.) If *jpegBuf points to a JPEG image buffer that is being reused from a previous call to one of the JPEG compression functions, then *jpegSize is ignored.
jpegQualthe image quality of the generated JPEG image (1 = worst, 100 = best)
flagsthe bitwise OR of one or more of the flags
+
+
+
Returns
0 if successful, or -1 if an error occurred (see tjGetErrorStr().)
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DLLEXPORT int DLLCALL tjCompressFromYUVPlanes (tjhandle handle,
unsigned char ** srcPlanes,
int width,
int * strides,
int height,
int subsamp,
unsigned char ** jpegBuf,
unsigned long * jpegSize,
int jpegQual,
int flags 
)
+
+ +

Compress a set of Y, U (Cb), and V (Cr) image planes into a JPEG image.

+
Parameters
+ + + + + + + + + + +
handlea handle to a TurboJPEG compressor or transformer instance
srcPlanesan array of pointers to Y, U (Cb), and V (Cr) image planes (or just a Y plane, if compressing a grayscale image) that contain a YUV image to be compressed. These planes can be contiguous or non-contiguous in memory. The size of each plane should match the value returned by tjPlaneSizeYUV() for the given image width, height, strides, and level of chrominance subsampling. Refer to YUV Image Format Notes for more details.
widthwidth (in pixels) of the source image. If the width is not an even multiple of the MCU block width (see tjMCUWidth), then an intermediate buffer copy will be performed within TurboJPEG.
stridesan array of integers, each specifying the number of bytes per line in the corresponding plane of the YUV source image. Setting the stride for any plane to 0 is the same as setting it to the plane width (see YUV Image Format Notes.) If strides is NULL, then the strides for all planes will be set to their respective plane widths. You can adjust the strides in order to specify an arbitrary amount of line padding in each plane or to create a JPEG image from a subregion of a larger YUV planar image.
heightheight (in pixels) of the source image. If the height is not an even multiple of the MCU block height (see tjMCUHeight), then an intermediate buffer copy will be performed within TurboJPEG.
subsampthe level of chrominance subsampling used in the source image (see Chrominance subsampling options.)
jpegBufaddress of a pointer to an image buffer that will receive the JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to accommodate the size of the JPEG image. Thus, you can choose to:
    +
  1. pre-allocate the JPEG buffer with an arbitrary size using tjAlloc() and let TurboJPEG grow the buffer as needed,
  2. +
  3. set *jpegBuf to NULL to tell TurboJPEG to allocate the buffer for you, or
  4. +
  5. pre-allocate the buffer to a "worst case" size determined by calling tjBufSize(). This should ensure that the buffer never has to be re-allocated (setting TJFLAG_NOREALLOC guarantees this.)
  6. +
+If you choose option 1, *jpegSize should be set to the size of your pre-allocated buffer. In any case, unless you have set TJFLAG_NOREALLOC, you should always check *jpegBuf upon return from this function, as it may have changed.
jpegSizepointer to an unsigned long variable that holds the size of the JPEG image buffer. If *jpegBuf points to a pre-allocated buffer, then *jpegSize should be set to the size of the buffer. Upon return, *jpegSize will contain the size of the JPEG image (in bytes.) If *jpegBuf points to a JPEG image buffer that is being reused from a previous call to one of the JPEG compression functions, then *jpegSize is ignored.
jpegQualthe image quality of the generated JPEG image (1 = worst, 100 = best)
flagsthe bitwise OR of one or more of the flags
@@ -1165,20 +1289,112 @@ If you choose option 1, *jpegSize should be set to the size of your

Decode a YUV planar image into an RGB or grayscale image.

-

This function uses the accelerated color conversion routines in the underlying codec but does not execute any of the other steps in the JPEG decompression process. The Y, U (Cb), and V (Cr) image planes should be stored sequentially in the source buffer, and the size of each plane is determined by the width and height of the source image, as well as the specified padding and level of chrominance subsampling. If the chrominance components are subsampled along the horizontal dimension, then the width of the luminance plane should be padded to the nearest multiple of 2 in the input image (same goes for the height of the luminance plane, if the chrominance components are subsampled along the vertical dimension.)

-

NOTE: Technically, the JPEG format uses the YCbCr colorspace, but per the convention of the digital video community, the TurboJPEG API uses "YUV" to refer to an image format consisting of Y, Cb, and Cr image planes.

+

This function uses the accelerated color conversion routines in the underlying codec but does not execute any of the other steps in the JPEG decompression process.

Parameters
- - - - - - - - - - + + + + + + + + + + +
handlea handle to a TurboJPEG decompressor or transformer instance
srcBufpointer to an image buffer containing a YUV planar image to be decoded. The size of this buffer should match the value returned by tjBufSizeYUV2() for the given image width, height, padding, and level of chrominance subsampling.
padUse this parameter to specify that the width of each line in each plane of the YUV source image is padded to the nearest multiple of this number of bytes (must be a power of 2.)
subsampthe level of chrominance subsampling used in the YUV source image (see Chrominance subsampling options.)
dstBufpointer to an image buffer that will receive the decoded image. This buffer should normally be pitch * height bytes in size, but the dstBuf pointer can also be used to decode into a specific region of a larger buffer.
widthwidth (in pixels) of the source and destination images
pitchbytes per line of the destination image. Normally, this should be width * tjPixelSize[pixelFormat] if the destination image is unpadded, or TJPAD(width * tjPixelSize[pixelFormat]) if each line of the destination image should be padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. You can also be clever and use the pitch parameter to skip lines, etc. Setting this parameter to 0 is the equivalent of setting it to width * tjPixelSize[pixelFormat].
heightheight (in pixels) of the source and destination images
pixelFormatpixel format of the destination image (see Pixel formats.)
flagsthe bitwise OR of one or more of the flags.
handlea handle to a TurboJPEG decompressor or transformer instance
srcBufpointer to an image buffer containing a YUV planar image to be decoded. The size of this buffer should match the value returned by tjBufSizeYUV2() for the given image width, height, padding, and level of chrominance subsampling. The Y, U (Cb), and V (Cr) image planes should be stored sequentially in the source buffer (refer to YUV Image Format Notes.)
padUse this parameter to specify that the width of each line in each plane of the YUV source image is padded to the nearest multiple of this number of bytes (must be a power of 2.)
subsampthe level of chrominance subsampling used in the YUV source image (see Chrominance subsampling options.)
dstBufpointer to an image buffer that will receive the decoded image. This buffer should normally be pitch * height bytes in size, but the dstBuf pointer can also be used to decode into a specific region of a larger buffer.
widthwidth (in pixels) of the source and destination images
pitchbytes per line in the destination image. Normally, this should be width * tjPixelSize[pixelFormat] if the destination image is unpadded, or TJPAD(width * tjPixelSize[pixelFormat]) if each line of the destination image should be padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. You can also be clever and use the pitch parameter to skip lines, etc. Setting this parameter to 0 is the equivalent of setting it to width * tjPixelSize[pixelFormat].
heightheight (in pixels) of the source and destination images
pixelFormatpixel format of the destination image (see Pixel formats.)
flagsthe bitwise OR of one or more of the flags
+
+
+
Returns
0 if successful, or -1 if an error occurred (see tjGetErrorStr().)
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DLLEXPORT int DLLCALL tjDecodeYUVPlanes (tjhandle handle,
unsigned char ** srcPlanes,
int * strides,
int subsamp,
unsigned char * dstBuf,
int width,
int pitch,
int height,
int pixelFormat,
int flags 
)
+
+ +

Decode a set of Y, U (Cb), and V (Cr) image planes into an RGB or grayscale image.

+

This function uses the accelerated color conversion routines in the underlying codec but does not execute any of the other steps in the JPEG decompression process.

+
Parameters
+ + + + + + + + + + +
handlea handle to a TurboJPEG decompressor or transformer instance
srcPlanesan array of pointers to Y, U (Cb), and V (Cr) image planes (or just a Y plane, if decoding a grayscale image) that contain a YUV image to be decoded. These planes can be contiguous or non-contiguous in memory. The size of each plane should match the value returned by tjPlaneSizeYUV() for the given image width, height, strides, and level of chrominance subsampling. Refer to YUV Image Format Notes for more details.
stridesan array of integers, each specifying the number of bytes per line in the corresponding plane of the YUV source image. Setting the stride for any plane to 0 is the same as setting it to the plane width (see YUV Image Format Notes.) If strides is NULL, then the strides for all planes will be set to their respective plane widths. You can adjust the strides in order to specify an arbitrary amount of line padding in each plane or to decode a subregion of a larger YUV planar image.
subsampthe level of chrominance subsampling used in the YUV source image (see Chrominance subsampling options.)
dstBufpointer to an image buffer that will receive the decoded image. This buffer should normally be pitch * height bytes in size, but the dstBuf pointer can also be used to decode into a specific region of a larger buffer.
widthwidth (in pixels) of the source and destination images
pitchbytes per line in the destination image. Normally, this should be width * tjPixelSize[pixelFormat] if the destination image is unpadded, or TJPAD(width * tjPixelSize[pixelFormat]) if each line of the destination image should be padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. You can also be clever and use the pitch parameter to skip lines, etc. Setting this parameter to 0 is the equivalent of setting it to width * tjPixelSize[pixelFormat].
heightheight (in pixels) of the source and destination images
pixelFormatpixel format of the destination image (see Pixel formats.)
flagsthe bitwise OR of one or more of the flags
@@ -1255,15 +1471,15 @@ If you choose option 1, *jpegSize should be set to the size of your

Decompress a JPEG image to an RGB, grayscale, or CMYK image.

Parameters
- - - - - - - - - + + + + + + + + +
handlea handle to a TurboJPEG decompressor or transformer instance
jpegBufpointer to a buffer containing the JPEG image to decompress
jpegSizesize of the JPEG image (in bytes)
dstBufpointer to an image buffer that will receive the decompressed image. This buffer should normally be pitch * scaledHeight bytes in size, where scaledHeight can be determined by calling TJSCALED() with the JPEG image height and one of the scaling factors returned by tjGetScalingFactors(). The dstBuf pointer may also be used to decompress into a specific region of a larger buffer.
widthdesired width (in pixels) of the destination image. If this is different than the width of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG decompressor to generate the largest possible image that will fit within the desired width. If width is set to 0, then only the height will be considered when determining the scaled image size.
pitchbytes per line of the destination image. Normally, this is scaledWidth * tjPixelSize[pixelFormat] if the decompressed image is unpadded, else TJPAD(scaledWidth * tjPixelSize[pixelFormat]) if each line of the decompressed image is padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. (NOTE: scaledWidth can be determined by calling TJSCALED() with the JPEG image width and one of the scaling factors returned by tjGetScalingFactors().) You can also be clever and use the pitch parameter to skip lines, etc. Setting this parameter to 0 is the equivalent of setting it to scaledWidth * tjPixelSize[pixelFormat].
heightdesired height (in pixels) of the destination image. If this is different than the height of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG decompressor to generate the largest possible image that will fit within the desired height. If height is set to 0, then only the width will be considered when determining the scaled image size.
pixelFormatpixel format of the destination image (see Pixel formats.)
flagsthe bitwise OR of one or more of the flags.
handlea handle to a TurboJPEG decompressor or transformer instance
jpegBufpointer to a buffer containing the JPEG image to decompress
jpegSizesize of the JPEG image (in bytes)
dstBufpointer to an image buffer that will receive the decompressed image. This buffer should normally be pitch * scaledHeight bytes in size, where scaledHeight can be determined by calling TJSCALED() with the JPEG image height and one of the scaling factors returned by tjGetScalingFactors(). The dstBuf pointer may also be used to decompress into a specific region of a larger buffer.
widthdesired width (in pixels) of the destination image. If this is different than the width of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG decompressor to generate the largest possible image that will fit within the desired width. If width is set to 0, then only the height will be considered when determining the scaled image size.
pitchbytes per line in the destination image. Normally, this is scaledWidth * tjPixelSize[pixelFormat] if the decompressed image is unpadded, else TJPAD(scaledWidth * tjPixelSize[pixelFormat]) if each line of the decompressed image is padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. (NOTE: scaledWidth can be determined by calling TJSCALED() with the JPEG image width and one of the scaling factors returned by tjGetScalingFactors().) You can also be clever and use the pitch parameter to skip lines, etc. Setting this parameter to 0 is the equivalent of setting it to scaledWidth * tjPixelSize[pixelFormat].
heightdesired height (in pixels) of the destination image. If this is different than the height of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG decompressor to generate the largest possible image that will fit within the desired height. If height is set to 0, then only the width will be considered when determining the scaled image size.
pixelFormatpixel format of the destination image (see Pixel formats.)
flagsthe bitwise OR of one or more of the flags
@@ -1328,12 +1544,12 @@ If you choose option 1, *jpegSize should be set to the size of your

Retrieve information about a JPEG image without decompressing it.

Parameters
- - - - - - + + + + + +
handlea handle to a TurboJPEG decompressor or transformer instance
jpegBufpointer to a buffer containing a JPEG image
jpegSizesize of the JPEG image (in bytes)
widthpointer to an integer variable that will receive the width (in pixels) of the JPEG image
heightpointer to an integer variable that will receive the height (in pixels) of the JPEG image
jpegSubsamppointer to an integer variable that will receive the level of chrominance subsampling used when compressing the JPEG image (see Chrominance subsampling options.)
handlea handle to a TurboJPEG decompressor or transformer instance
jpegBufpointer to a buffer containing a JPEG image
jpegSizesize of the JPEG image (in bytes)
widthpointer to an integer variable that will receive the width (in pixels) of the JPEG image
heightpointer to an integer variable that will receive the height (in pixels) of the JPEG image
jpegSubsamppointer to an integer variable that will receive the level of chrominance subsampling used when the JPEG image was compressed (see Chrominance subsampling options.)
jpegColorspacepointer to an integer variable that will receive one of the JPEG colorspace constants, indicating the colorspace of the JPEG image (see JPEG colorspaces.)
@@ -1403,18 +1619,96 @@ If you choose option 1, *jpegSize should be set to the size of your

Decompress a JPEG image to a YUV planar image.

-

This function performs JPEG decompression but leaves out the color conversion step, so a planar YUV image is generated instead of an RGB image. The structure of the planes in this image is the same as in the images generated by tjEncodeYUV3(). Note that, if the width or height of the JPEG image is not an even multiple of the MCU block size (see tjMCUWidth and tjMCUHeight), then an intermediate buffer copy will be performed within TurboJPEG.

-

NOTE: Technically, the JPEG format uses the YCbCr colorspace, but per the convention of the digital video community, the TurboJPEG API uses "YUV" to refer to an image format consisting of Y, Cb, and Cr image planes.

+

This function performs JPEG decompression but leaves out the color conversion step, so a planar YUV image is generated instead of an RGB image.

Parameters
- - - - - - - - + + + + + + + + +
handlea handle to a TurboJPEG decompressor or transformer instance
jpegBufpointer to a buffer containing the JPEG image to decompress
jpegSizesize of the JPEG image (in bytes)
dstBufpointer to an image buffer that will receive the YUV image. Use tjBufSizeYUV2() to determine the appropriate size for this buffer based on the image width, height, padding, and level of subsampling.
widthdesired width (in pixels) of the YUV image. If this is different than the width of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG decompressor to generate the largest possible image that will fit within the desired width. If width is set to 0, then only the height will be considered when determining the scaled image size.
padthe width of each line in each plane of the YUV image will be padded to the nearest multiple of this number of bytes (must be a power of 2.) To generate images suitable for X Video, pad should be set to 4.
heightdesired height (in pixels) of the YUV image. If this is different than the height of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG decompressor to generate the largest possible image that will fit within the desired height. If height is set to 0, then only the width will be considered when determining the scaled image size.
flagsthe bitwise OR of one or more of the flags.
handlea handle to a TurboJPEG decompressor or transformer instance
jpegBufpointer to a buffer containing the JPEG image to decompress
jpegSizesize of the JPEG image (in bytes)
dstBufpointer to an image buffer that will receive the YUV image. Use tjBufSizeYUV2() to determine the appropriate size for this buffer based on the image width, height, padding, and level of subsampling. The Y, U (Cb), and V (Cr) image planes will be stored sequentially in the buffer (refer to YUV Image Format Notes.)
widthdesired width (in pixels) of the YUV image. If this is different than the width of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG decompressor to generate the largest possible image that will fit within the desired width. If width is set to 0, then only the height will be considered when determining the scaled image size. If the scaled width is not an even multiple of the MCU block width (see tjMCUWidth), then an intermediate buffer copy will be performed within TurboJPEG.
padthe width of each line in each plane of the YUV image will be padded to the nearest multiple of this number of bytes (must be a power of 2.) To generate images suitable for X Video, pad should be set to 4.
heightdesired height (in pixels) of the YUV image. If this is different than the height of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG decompressor to generate the largest possible image that will fit within the desired height. If height is set to 0, then only the width will be considered when determining the scaled image size. If the scaled height is not an even multiple of the MCU block height (see tjMCUHeight), then an intermediate buffer copy will be performed within TurboJPEG.
flagsthe bitwise OR of one or more of the flags
+
+
+
Returns
0 if successful, or -1 if an error occurred (see tjGetErrorStr().)
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DLLEXPORT int DLLCALL tjDecompressToYUVPlanes (tjhandle handle,
unsigned char * jpegBuf,
unsigned long jpegSize,
unsigned char ** dstPlanes,
int width,
int * strides,
int height,
int flags 
)
+
+ +

Decompress a JPEG image into separate Y, U (Cb), and V (Cr) image planes.

+

This function performs JPEG decompression but leaves out the color conversion step, so a planar YUV image is generated instead of an RGB image.

+
Parameters
+ + + + + + + + +
handlea handle to a TurboJPEG decompressor or transformer instance
jpegBufpointer to a buffer containing the JPEG image to decompress
jpegSizesize of the JPEG image (in bytes)
dstPlanesan array of pointers to Y, U (Cb), and V (Cr) image planes (or just a Y plane, if decompressing a grayscale image) that will receive the YUV image. These planes can be contiguous or non-contiguous in memory. Use tjPlaneSizeYUV() to determine the appropriate size for each plane based on the scaled image width, scaled image height, strides, and level of chrominance subsampling. Refer to YUV Image Format Notes for more details.
widthdesired width (in pixels) of the YUV image. If this is different than the width of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG decompressor to generate the largest possible image that will fit within the desired width. If width is set to 0, then only the height will be considered when determining the scaled image size. If the scaled width is not an even multiple of the MCU block width (see tjMCUWidth), then an intermediate buffer copy will be performed within TurboJPEG.
stridesan array of integers, each specifying the number of bytes per line in the corresponding plane of the output image. Setting the stride for any plane to 0 is the same as setting it to the scaled plane width (see YUV Image Format Notes.) If strides is NULL, then the strides for all planes will be set to their respective scaled plane widths. You can adjust the strides in order to add an arbitrary amount of line padding to each plane or to decompress the JPEG image into a subregion of a larger YUV planar image.
heightdesired height (in pixels) of the YUV image. If this is different than the height of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG decompressor to generate the largest possible image that will fit within the desired height. If height is set to 0, then only the width will be considered when determining the scaled image size. If the scaled height is not an even multiple of the MCU block height (see tjMCUHeight), then an intermediate buffer copy will be performed within TurboJPEG.
flagsthe bitwise OR of one or more of the flags
@@ -1520,20 +1814,112 @@ If you choose option 1, *jpegSize should be set to the size of your

Encode an RGB or grayscale image into a YUV planar image.

-

This function uses the accelerated color conversion routines in the underlying codec but does not execute any of the other steps in the JPEG compression process. The Y, U (Cb), and V (Cr) image planes are stored sequentially into the destination buffer, and the size of each plane is determined by the width and height of the source image, as well as the specified padding and level of chrominance subsampling. If the chrominance components are subsampled along the horizontal dimension, then the width of the luminance plane is padded to the nearest multiple of 2 in the output image (same goes for the height of the luminance plane, if the chrominance components are subsampled along the vertical dimension.)

-

NOTE: Technically, the JPEG format uses the YCbCr colorspace, but per the convention of the digital video community, the TurboJPEG API uses "YUV" to refer to an image format consisting of Y, Cb, and Cr image planes.

+

This function uses the accelerated color conversion routines in the underlying codec but does not execute any of the other steps in the JPEG compression process.

Parameters
- - - - - - - - - - + + + + + + + + + + +
handlea handle to a TurboJPEG compressor or transformer instance
srcBufpointer to an image buffer containing RGB or grayscale pixels to be encoded
widthwidth (in pixels) of the source image
pitchbytes per line of the source image. Normally, this should be width * tjPixelSize[pixelFormat] if the image is unpadded, or TJPAD(width * tjPixelSize[pixelFormat]) if each line of the image is padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. You can also be clever and use this parameter to skip lines, etc. Setting this parameter to 0 is the equivalent of setting it to width * tjPixelSize[pixelFormat].
heightheight (in pixels) of the source image
pixelFormatpixel format of the source image (see Pixel formats.)
dstBufpointer to an image buffer that will receive the YUV image. Use tjBufSizeYUV2() to determine the appropriate size for this buffer based on the image width, height, padding, and level of chrominance subsampling.
padthe width of each line in each plane of the YUV image will be padded to the nearest multiple of this number of bytes (must be a power of 2.) To generate images suitable for X Video, pad should be set to 4.
subsampthe level of chrominance subsampling to be used when generating the YUV image (see Chrominance subsampling options.) To generate images suitable for X Video, subsamp should be set to TJSAMP_420. This produces an image compatible with the I420 (AKA "YUV420P") format.
flagsthe bitwise OR of one or more of the flags.
handlea handle to a TurboJPEG compressor or transformer instance
srcBufpointer to an image buffer containing RGB or grayscale pixels to be encoded
widthwidth (in pixels) of the source image
pitchbytes per line in the source image. Normally, this should be width * tjPixelSize[pixelFormat] if the image is unpadded, or TJPAD(width * tjPixelSize[pixelFormat]) if each line of the image is padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. You can also be clever and use this parameter to skip lines, etc. Setting this parameter to 0 is the equivalent of setting it to width * tjPixelSize[pixelFormat].
heightheight (in pixels) of the source image
pixelFormatpixel format of the source image (see Pixel formats.)
dstBufpointer to an image buffer that will receive the YUV image. Use tjBufSizeYUV2() to determine the appropriate size for this buffer based on the image width, height, padding, and level of chrominance subsampling. The Y, U (Cb), and V (Cr) image planes will be stored sequentially in the buffer (refer to YUV Image Format Notes.)
padthe width of each line in each plane of the YUV image will be padded to the nearest multiple of this number of bytes (must be a power of 2.) To generate images suitable for X Video, pad should be set to 4.
subsampthe level of chrominance subsampling to be used when generating the YUV image (see Chrominance subsampling options.) To generate images suitable for X Video, subsamp should be set to TJSAMP_420. This produces an image compatible with the I420 (AKA "YUV420P") format.
flagsthe bitwise OR of one or more of the flags
+
+
+
Returns
0 if successful, or -1 if an error occurred (see tjGetErrorStr().)
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DLLEXPORT int DLLCALL tjEncodeYUVPlanes (tjhandle handle,
unsigned char * srcBuf,
int width,
int pitch,
int height,
int pixelFormat,
unsigned char ** dstPlanes,
int * strides,
int subsamp,
int flags 
)
+
+ +

Encode an RGB or grayscale image into separate Y, U (Cb), and V (Cr) image planes.

+

This function uses the accelerated color conversion routines in the underlying codec but does not execute any of the other steps in the JPEG compression process.

+
Parameters
+ + + + + + + + + + +
handlea handle to a TurboJPEG compressor or transformer instance
srcBufpointer to an image buffer containing RGB or grayscale pixels to be encoded
widthwidth (in pixels) of the source image
pitchbytes per line in the source image. Normally, this should be width * tjPixelSize[pixelFormat] if the image is unpadded, or TJPAD(width * tjPixelSize[pixelFormat]) if each line of the image is padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. You can also be clever and use this parameter to skip lines, etc. Setting this parameter to 0 is the equivalent of setting it to width * tjPixelSize[pixelFormat].
heightheight (in pixels) of the source image
pixelFormatpixel format of the source image (see Pixel formats.)
dstPlanesan array of pointers to Y, U (Cb), and V (Cr) image planes (or just a Y plane, if generating a grayscale image) that will receive the encoded image. These planes can be contiguous or non-contiguous in memory. Use tjPlaneSizeYUV() to determine the appropriate size for each plane based on the image width, height, strides, and level of chrominance subsampling. Refer to YUV Image Format Notes for more details.
stridesan array of integers, each specifying the number of bytes per line in the corresponding plane of the output image. Setting the stride for any plane to 0 is the same as setting it to the plane width (see YUV Image Format Notes.) If strides is NULL, then the strides for all planes will be set to their respective plane widths. You can adjust the strides in order to add an arbitrary amount of line padding to each plane or to encode an RGB or grayscale image into a subregion of a larger YUV planar image.
subsampthe level of chrominance subsampling to be used when generating the YUV image (see Chrominance subsampling options.) To generate images suitable for X Video, subsamp should be set to TJSAMP_420. This produces an image compatible with the I420 (AKA "YUV420P") format.
flagsthe bitwise OR of one or more of the flags
@@ -1666,6 +2052,151 @@ If you choose option 1, *jpegSize should be set to the size of your

Create a new TurboJPEG transformer instance.

Returns
a handle to the newly-created instance, or NULL if an error occurred (see tjGetErrorStr().)
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
DLLEXPORT int tjPlaneHeight (int componentID,
int height,
int subsamp 
)
+
+ +

The plane height of a YUV image plane with the given parameters.

+

Refer to YUV Image Format Notes for a description of plane height.

+
Parameters
+ + + + +
componentIDID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr)
heightheight (in pixels) of the YUV image
subsamplevel of chrominance subsampling in the image (see Chrominance subsampling options.)
+
+
+
Returns
the plane height of a YUV image plane with the given parameters, or -1 if the arguments are out of bounds.
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DLLEXPORT unsigned long DLLCALL tjPlaneSizeYUV (int componentID,
int width,
int stride,
int height,
int subsamp 
)
+
+ +

The size of the buffer (in bytes) required to hold a YUV image plane with the given parameters.

+
Parameters
+ + + + + + +
componentIDID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr)
widthwidth (in pixels) of the YUV image. NOTE: this is the width of the whole image, not the plane width.
stridebytes per line in the image plane. Setting this to 0 is the equivalent of setting it to the plane width.
heightheight (in pixels) of the YUV image. NOTE: this is the height of the whole image, not the plane height.
subsamplevel of chrominance subsampling in the image (see Chrominance subsampling options.)
+
+
+
Returns
the size of the buffer (in bytes) required to hold the YUV image plane, or -1 if the arguments are out of bounds.
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
DLLEXPORT int tjPlaneWidth (int componentID,
int width,
int subsamp 
)
+
+ +

The plane width of a YUV image plane with the given parameters.

+

Refer to YUV Image Format Notes for a description of plane width.

+
Parameters
+ + + + +
componentIDID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr)
widthwidth (in pixels) of the YUV image
subsamplevel of chrominance subsampling in the image (see Chrominance subsampling options.)
+
+
+
Returns
the plane width of a YUV image plane with the given parameters, or -1 if the arguments are out of bounds.
+
@@ -1729,22 +2260,22 @@ If you choose option 1, *jpegSize should be set to the size of your

Losslessly transform a JPEG image into another JPEG image.

-

Lossless transforms work by moving the raw coefficients from one JPEG image structure to another without altering the values of the coefficients. While this is typically faster than decompressing the image, transforming it, and re-compressing it, lossless transforms are not free. Each lossless transform requires reading and performing Huffman decoding on all of the coefficients in the source image, regardless of the size of the destination image. Thus, this function provides a means of generating multiple transformed images from the same source or applying multiple transformations simultaneously, in order to eliminate the need to read the source coefficients multiple times.

+

Lossless transforms work by moving the raw DCT coefficients from one JPEG image structure to another without altering the values of the coefficients. While this is typically faster than decompressing the image, transforming it, and re-compressing it, lossless transforms are not free. Each lossless transform requires reading and performing Huffman decoding on all of the coefficients in the source image, regardless of the size of the destination image. Thus, this function provides a means of generating multiple transformed images from the same source or applying multiple transformations simultaneously, in order to eliminate the need to read the source coefficients multiple times.

Parameters
- - - - + + + + - - - +If you choose option 1, dstSizes[i] should be set to the size of your pre-allocated buffer. In any case, unless you have set TJFLAG_NOREALLOC, you should always check dstBufs[i] upon return from this function, as it may have changed. + + +
handlea handle to a TurboJPEG transformer instance
jpegBufpointer to a buffer containing the JPEG image to transform
jpegSizesize of the JPEG image (in bytes)
nthe number of transformed JPEG images to generate
handlea handle to a TurboJPEG transformer instance
jpegBufpointer to a buffer containing the JPEG source image to transform
jpegSizesize of the JPEG source image (in bytes)
nthe number of transformed JPEG images to generate
dstBufspointer to an array of n image buffers. dstBufs[i] will receive a JPEG image that has been transformed using the parameters in transforms[i]. TurboJPEG has the ability to reallocate the JPEG buffer to accommodate the size of the JPEG image. Thus, you can choose to:
  1. pre-allocate the JPEG buffer with an arbitrary size using tjAlloc() and let TurboJPEG grow the buffer as needed,
  2. set dstBufs[i] to NULL to tell TurboJPEG to allocate the buffer for you, or
  3. pre-allocate the buffer to a "worst case" size determined by calling tjBufSize() with the transformed or cropped width and height. This should ensure that the buffer never has to be re-allocated (setting TJFLAG_NOREALLOC guarantees this.)
-If you choose option 1, dstSizes[i] should be set to the size of your pre-allocated buffer. In any case, unless you have set TJFLAG_NOREALLOC, you should always check dstBufs[i] upon return from this function, as it may have changed.
dstSizespointer to an array of n unsigned long variables that will receive the actual sizes (in bytes) of each transformed JPEG image. If dstBufs[i] points to a pre-allocated buffer, then dstSizes[i] should be set to the size of the buffer. Upon return, dstSizes[i] will contain the size of the JPEG image (in bytes.)
transformspointer to an array of n tjtransform structures, each of which specifies the transform parameters and/or cropping region for the corresponding transformed output image.
flagsthe bitwise OR of one or more of the flags.
dstSizespointer to an array of n unsigned long variables that will receive the actual sizes (in bytes) of each transformed JPEG image. If dstBufs[i] points to a pre-allocated buffer, then dstSizes[i] should be set to the size of the buffer. Upon return, dstSizes[i] will contain the size of the JPEG image (in bytes.)
transformspointer to an array of n tjtransform structures, each of which specifies the transform parameters and/or cropping region for the corresponding transformed output image.
flagsthe bitwise OR of one or more of the flags
diff --git a/doc/html/index.html b/doc/html/index.html index 139b84c4..ccaa12e4 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -14,6 +14,7 @@ $(document).ready(function() { searchBox.OnSelectItem(0); }); +
diff --git a/doc/html/modules.html b/doc/html/modules.html index 6b769e40..9b41adbd 100644 --- a/doc/html/modules.html +++ b/doc/html/modules.html @@ -14,6 +14,7 @@ $(document).ready(function() { searchBox.OnSelectItem(0); }); +
diff --git a/doc/html/search/all_74.js b/doc/html/search/all_74.js index 435cec4d..5b46106f 100644 --- a/doc/html/search/all_74.js +++ b/doc/html/search/all_74.js @@ -10,6 +10,7 @@ var searchData= ['tjbufsizeyuv2',['tjBufSizeYUV2',['../group___turbo_j_p_e_g.html#gaf451664a62c1f6c7cc5a6401f32908c9',1,'turbojpeg.h']]], ['tjcompress2',['tjCompress2',['../group___turbo_j_p_e_g.html#gaba62b7a98f960839b588579898495cf2',1,'turbojpeg.h']]], ['tjcompressfromyuv',['tjCompressFromYUV',['../group___turbo_j_p_e_g.html#ga0b931126c7a615ddc3bbd0cca6698d67',1,'turbojpeg.h']]], + ['tjcompressfromyuvplanes',['tjCompressFromYUVPlanes',['../group___turbo_j_p_e_g.html#gaa89a1982cb4556b12ae7af4439991af6',1,'turbojpeg.h']]], ['tjcs',['TJCS',['../group___turbo_j_p_e_g.html#ga4f83ad3368e0e29d1957be0efa7c3720',1,'turbojpeg.h']]], ['tjcs_5fcmyk',['TJCS_CMYK',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a6c8b636152ac8195b869587db315ee53',1,'turbojpeg.h']]], ['tjcs_5fgray',['TJCS_GRAY',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720ab3e7d6a87f695e45b81c1b5262b5a50a',1,'turbojpeg.h']]], @@ -17,11 +18,14 @@ var searchData= ['tjcs_5fycbcr',['TJCS_YCbCr',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a7389b8f65bb387ffedce3efd0d78ec75',1,'turbojpeg.h']]], ['tjcs_5fycck',['TJCS_YCCK',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a53839e0fe867b76b58d16b0a1a7c598e',1,'turbojpeg.h']]], ['tjdecodeyuv',['tjDecodeYUV',['../group___turbo_j_p_e_g.html#ga132ae2c2cadcf64c8bb0f3bdf69da3ed',1,'turbojpeg.h']]], + ['tjdecodeyuvplanes',['tjDecodeYUVPlanes',['../group___turbo_j_p_e_g.html#ga6cb5b0e1101a2b20edea576e11faf93d',1,'turbojpeg.h']]], ['tjdecompress2',['tjDecompress2',['../group___turbo_j_p_e_g.html#gada69cc6443d1bb493b40f1626259e5e9',1,'turbojpeg.h']]], ['tjdecompressheader3',['tjDecompressHeader3',['../group___turbo_j_p_e_g.html#gacd0fac3af74b3511d39b4781b7103086',1,'turbojpeg.h']]], ['tjdecompresstoyuv2',['tjDecompressToYUV2',['../group___turbo_j_p_e_g.html#ga7c08b340ad7f8e85d407bd9e81d44d07',1,'turbojpeg.h']]], + ['tjdecompresstoyuvplanes',['tjDecompressToYUVPlanes',['../group___turbo_j_p_e_g.html#ga0828a38ae29631ac28b6857cefb0eebf',1,'turbojpeg.h']]], ['tjdestroy',['tjDestroy',['../group___turbo_j_p_e_g.html#ga674adee917b95ad4a896f1ba39e12540',1,'turbojpeg.h']]], ['tjencodeyuv3',['tjEncodeYUV3',['../group___turbo_j_p_e_g.html#ga0a5ffbf7cb58a5b6a8201114fe889360',1,'turbojpeg.h']]], + ['tjencodeyuvplanes',['tjEncodeYUVPlanes',['../group___turbo_j_p_e_g.html#gaa791db8598853ddcad24e42897ef1269',1,'turbojpeg.h']]], ['tjflag_5faccuratedct',['TJFLAG_ACCURATEDCT',['../group___turbo_j_p_e_g.html#gacb233cfd722d66d1ccbf48a7de81f0e0',1,'turbojpeg.h']]], ['tjflag_5fbottomup',['TJFLAG_BOTTOMUP',['../group___turbo_j_p_e_g.html#ga72ecf4ebe6eb702d3c6f5ca27455e1ec',1,'turbojpeg.h']]], ['tjflag_5ffastdct',['TJFLAG_FASTDCT',['../group___turbo_j_p_e_g.html#gaabce235db80d3f698b27f36cbd453da2',1,'turbojpeg.h']]], @@ -52,6 +56,9 @@ var searchData= ['tjpf_5fxbgr',['TJPF_XBGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aaf6603b27147de47e212e75dac027b2af',1,'turbojpeg.h']]], ['tjpf_5fxrgb',['TJPF_XRGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aadae996905efcfa3b42a0bb3bea7f9d84',1,'turbojpeg.h']]], ['tjpixelsize',['tjPixelSize',['../group___turbo_j_p_e_g.html#gad77cf8fe5b2bfd3cb3f53098146abb4c',1,'turbojpeg.h']]], + ['tjplaneheight',['tjPlaneHeight',['../group___turbo_j_p_e_g.html#ga1a209696c6a80748f20e134b3c64789f',1,'turbojpeg.h']]], + ['tjplanesizeyuv',['tjPlaneSizeYUV',['../group___turbo_j_p_e_g.html#ga6f98d977bfa9d167c97172e876ba61e2',1,'turbojpeg.h']]], + ['tjplanewidth',['tjPlaneWidth',['../group___turbo_j_p_e_g.html#ga63fb66bb1e36c74008c4634360becbb1',1,'turbojpeg.h']]], ['tjredoffset',['tjRedOffset',['../group___turbo_j_p_e_g.html#gadd9b446742ac8a3923f7992c7988fea8',1,'turbojpeg.h']]], ['tjregion',['tjregion',['../structtjregion.html',1,'']]], ['tjsamp',['TJSAMP',['../group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074',1,'turbojpeg.h']]], diff --git a/doc/html/search/functions_74.js b/doc/html/search/functions_74.js index 0a0e6cdc..73b7ee98 100644 --- a/doc/html/search/functions_74.js +++ b/doc/html/search/functions_74.js @@ -5,17 +5,24 @@ var searchData= ['tjbufsizeyuv2',['tjBufSizeYUV2',['../group___turbo_j_p_e_g.html#gaf451664a62c1f6c7cc5a6401f32908c9',1,'turbojpeg.h']]], ['tjcompress2',['tjCompress2',['../group___turbo_j_p_e_g.html#gaba62b7a98f960839b588579898495cf2',1,'turbojpeg.h']]], ['tjcompressfromyuv',['tjCompressFromYUV',['../group___turbo_j_p_e_g.html#ga0b931126c7a615ddc3bbd0cca6698d67',1,'turbojpeg.h']]], + ['tjcompressfromyuvplanes',['tjCompressFromYUVPlanes',['../group___turbo_j_p_e_g.html#gaa89a1982cb4556b12ae7af4439991af6',1,'turbojpeg.h']]], ['tjdecodeyuv',['tjDecodeYUV',['../group___turbo_j_p_e_g.html#ga132ae2c2cadcf64c8bb0f3bdf69da3ed',1,'turbojpeg.h']]], + ['tjdecodeyuvplanes',['tjDecodeYUVPlanes',['../group___turbo_j_p_e_g.html#ga6cb5b0e1101a2b20edea576e11faf93d',1,'turbojpeg.h']]], ['tjdecompress2',['tjDecompress2',['../group___turbo_j_p_e_g.html#gada69cc6443d1bb493b40f1626259e5e9',1,'turbojpeg.h']]], ['tjdecompressheader3',['tjDecompressHeader3',['../group___turbo_j_p_e_g.html#gacd0fac3af74b3511d39b4781b7103086',1,'turbojpeg.h']]], ['tjdecompresstoyuv2',['tjDecompressToYUV2',['../group___turbo_j_p_e_g.html#ga7c08b340ad7f8e85d407bd9e81d44d07',1,'turbojpeg.h']]], + ['tjdecompresstoyuvplanes',['tjDecompressToYUVPlanes',['../group___turbo_j_p_e_g.html#ga0828a38ae29631ac28b6857cefb0eebf',1,'turbojpeg.h']]], ['tjdestroy',['tjDestroy',['../group___turbo_j_p_e_g.html#ga674adee917b95ad4a896f1ba39e12540',1,'turbojpeg.h']]], ['tjencodeyuv3',['tjEncodeYUV3',['../group___turbo_j_p_e_g.html#ga0a5ffbf7cb58a5b6a8201114fe889360',1,'turbojpeg.h']]], + ['tjencodeyuvplanes',['tjEncodeYUVPlanes',['../group___turbo_j_p_e_g.html#gaa791db8598853ddcad24e42897ef1269',1,'turbojpeg.h']]], ['tjfree',['tjFree',['../group___turbo_j_p_e_g.html#ga8c4a1231dc06a450514c835f6471f137',1,'turbojpeg.h']]], ['tjgeterrorstr',['tjGetErrorStr',['../group___turbo_j_p_e_g.html#ga9af79c908ec131b1ae8d52fe40375abf',1,'turbojpeg.h']]], ['tjgetscalingfactors',['tjGetScalingFactors',['../group___turbo_j_p_e_g.html#ga6449044b9af402999ccf52f401333be8',1,'turbojpeg.h']]], ['tjinitcompress',['tjInitCompress',['../group___turbo_j_p_e_g.html#ga3d10c47fbe4a2489a2b30c931551d01a',1,'turbojpeg.h']]], ['tjinitdecompress',['tjInitDecompress',['../group___turbo_j_p_e_g.html#gae5408179d041e2a2f7199c8283cf649e',1,'turbojpeg.h']]], ['tjinittransform',['tjInitTransform',['../group___turbo_j_p_e_g.html#ga3155b775bfbac9dbba869b95a0367902',1,'turbojpeg.h']]], + ['tjplaneheight',['tjPlaneHeight',['../group___turbo_j_p_e_g.html#ga1a209696c6a80748f20e134b3c64789f',1,'turbojpeg.h']]], + ['tjplanesizeyuv',['tjPlaneSizeYUV',['../group___turbo_j_p_e_g.html#ga6f98d977bfa9d167c97172e876ba61e2',1,'turbojpeg.h']]], + ['tjplanewidth',['tjPlaneWidth',['../group___turbo_j_p_e_g.html#ga63fb66bb1e36c74008c4634360becbb1',1,'turbojpeg.h']]], ['tjtransform',['tjTransform',['../group___turbo_j_p_e_g.html#gae403193ceb4aafb7e0f56ab587b48616',1,'turbojpeg.h']]] ]; diff --git a/doc/html/structtjregion.html b/doc/html/structtjregion.html index 515686c6..d22c09ed 100644 --- a/doc/html/structtjregion.html +++ b/doc/html/structtjregion.html @@ -14,6 +14,7 @@ $(document).ready(function() { searchBox.OnSelectItem(0); }); +
diff --git a/doc/html/structtjscalingfactor.html b/doc/html/structtjscalingfactor.html index f34e1503..f7b7c84f 100644 --- a/doc/html/structtjscalingfactor.html +++ b/doc/html/structtjscalingfactor.html @@ -14,6 +14,7 @@ $(document).ready(function() { searchBox.OnSelectItem(0); }); +
diff --git a/doc/html/structtjtransform.html b/doc/html/structtjtransform.html index ef2c8d59..7a07c2aa 100644 --- a/doc/html/structtjtransform.html +++ b/doc/html/structtjtransform.html @@ -14,6 +14,7 @@ $(document).ready(function() { searchBox.OnSelectItem(0); }); +
@@ -128,11 +129,11 @@ Data Fields

This allows for custom filters or other transformations to be applied in the frequency domain.

Parameters
- - - - - + + + + +
coeffspointer to an array of transformed DCT coefficients. (NOTE: this pointer is not guaranteed to be valid once the callback returns, so applications wishing to hand off the DCT coefficients to another function or library should make a copy of them within the body of the callback.)
arrayRegiontjregion structure containing the width and height of the array pointed to by coeffs as well as its offset relative to the component plane. TurboJPEG implementations may choose to split each component plane into multiple DCT coefficient arrays and call the callback function once for each array.
planeRegiontjregion structure containing the width and height of the component plane to which coeffs belongs
componentIDID number of the component plane to which coeffs belongs (Y, Cb, and Cr have, respectively, ID's of 0, 1, and 2 in typical JPEG images.)
transformIDID number of the transformed image to which coeffs belongs. This is the same as the index of the transform in the transforms array that was passed to tjTransform().
coeffspointer to an array of transformed DCT coefficients. (NOTE: this pointer is not guaranteed to be valid once the callback returns, so applications wishing to hand off the DCT coefficients to another function or library should make a copy of them within the body of the callback.)
arrayRegiontjregion structure containing the width and height of the array pointed to by coeffs as well as its offset relative to the component plane. TurboJPEG implementations may choose to split each component plane into multiple DCT coefficient arrays and call the callback function once for each array.
planeRegiontjregion structure containing the width and height of the component plane to which coeffs belongs
componentIDID number of the component plane to which coeffs belongs (Y, Cb, and Cr have, respectively, ID's of 0, 1, and 2 in typical JPEG images.)
transformIDID number of the transformed image to which coeffs belongs. This is the same as the index of the transform in the transforms array that was passed to tjTransform().
transforma pointer to a tjtransform structure that specifies the parameters and/or cropping region for this transform
diff --git a/doxygen-extra.css b/doxygen-extra.css new file mode 100644 index 00000000..5abbcc21 --- /dev/null +++ b/doxygen-extra.css @@ -0,0 +1,3 @@ +code { + color: #4665A2; +} diff --git a/doxygen.config b/doxygen.config index 96801753..4ffba681 100644 --- a/doxygen.config +++ b/doxygen.config @@ -13,3 +13,4 @@ JAVADOC_AUTOBRIEF = YES MAX_INITIALIZER_LINES = 0 ALWAYS_DETAILED_SEC = YES HTML_TIMESTAMP = NO +HTML_EXTRA_STYLESHEET = doxygen-extra.css diff --git a/java/TJBench.java b/java/TJBench.java index 617d312d..c9d110c3 100644 --- a/java/TJBench.java +++ b/java/TJBench.java @@ -236,7 +236,7 @@ class TJBench { "_" + sizeStr + ".bmp"); saveImage(tempStr, dstBuf, scaledw, scaledh, pf); - int ndx = tempStr.indexOf('.'); + int ndx = tempStr.lastIndexOf('.'); tempStr = new String(tempStr.substring(0, ndx) + "-err.bmp"); if (srcBuf != null && sf.getNum() == 1 && sf.getDenom() == 1) { if (quiet == 0) @@ -432,7 +432,7 @@ class TJBench { fis.read(srcBuf, 0, srcSize); fis.close(); - int index = fileName.indexOf('.'); + int index = fileName.lastIndexOf('.'); if (index >= 0) fileName = new String(fileName.substring(0, index)); @@ -846,7 +846,7 @@ class TJBench { srcBuf = loadImage(argv[0], width, height, pf); w = width[0]; h = height[0]; int index = -1; - if ((index = argv[0].indexOf('.')) >= 0) + if ((index = argv[0].lastIndexOf('.')) >= 0) argv[0] = argv[0].substring(0, index); } diff --git a/java/TJExample.java b/java/TJExample.java index 2c6324dc..75621143 100644 --- a/java/TJExample.java +++ b/java/TJExample.java @@ -277,7 +277,7 @@ public class TJExample implements TJCustomFilter { scaleFactor.isOne()) { file = new File(argv[1]); FileOutputStream fos = new FileOutputStream(file); - fos.write(tjd.getSourceBuf(), 0, tjd.getSourceSize()); + fos.write(tjd.getJPEGBuf(), 0, tjd.getJPEGSize()); fos.close(); System.exit(0); } diff --git a/java/doc/deprecated-list.html b/java/doc/deprecated-list.html index 79fd7ed9..e47ffb13 100644 --- a/java/doc/deprecated-list.html +++ b/java/doc/deprecated-list.html @@ -106,83 +106,73 @@ -org.libjpegturbo.turbojpeg.TJ.bufSizeYUV(int, int, int) - +org.libjpegturbo.turbojpeg.TJ.bufSizeYUV(int, int, int) + -org.libjpegturbo.turbojpeg.TJCompressor.compress(BufferedImage, byte[], int) +org.libjpegturbo.turbojpeg.TJCompressor.compress(BufferedImage, byte[], int) + TJCompressor.setSourceImage(BufferedImage, int, int, int, int) and + TJCompressor.compress(byte[], int) instead.
-org.libjpegturbo.turbojpeg.TJCompressor.compress(BufferedImage, int) +org.libjpegturbo.turbojpeg.TJCompressor.compress(BufferedImage, int) -org.libjpegturbo.turbojpeg.TJDecompressor.decompress(byte[], int, int, int, int, int) +org.libjpegturbo.turbojpeg.TJDecompressor.decompress(byte[], int, int, int, int, int) + TJDecompressor.decompress(byte[], int, int, int, int, int, int, int) instead.
-org.libjpegturbo.turbojpeg.TJDecompressor.decompressToYUV(byte[], int) - +org.libjpegturbo.turbojpeg.TJDecompressor.decompressToYUV(byte[], int) + org.libjpegturbo.turbojpeg.TJDecompressor.decompressToYUV(int) - + -org.libjpegturbo.turbojpeg.TJCompressor.encodeYUV(BufferedImage, byte[], int) +org.libjpegturbo.turbojpeg.TJCompressor.encodeYUV(BufferedImage, byte[], int) + TJCompressor.setSourceImage(BufferedImage, int, int, int, int) and + TJCompressor.encodeYUV(byte[], int) instead.
-org.libjpegturbo.turbojpeg.TJCompressor.encodeYUV(BufferedImage, int) +org.libjpegturbo.turbojpeg.TJCompressor.encodeYUV(BufferedImage, int) + TJCompressor.setSourceImage(BufferedImage, int, int, int, int) and + TJCompressor.encodeYUV(int, int) instead.
-org.libjpegturbo.turbojpeg.TJCompressor.encodeYUV(byte[], int) - +org.libjpegturbo.turbojpeg.TJCompressor.encodeYUV(byte[], int) + org.libjpegturbo.turbojpeg.TJCompressor.encodeYUV(int) - + -org.libjpegturbo.turbojpeg.TJDecompressor.getJPEGBuf() - +org.libjpegturbo.turbojpeg.TJDecompressor.setJPEGImage(byte[], int) + -org.libjpegturbo.turbojpeg.TJDecompressor.getJPEGSize() - - - - -org.libjpegturbo.turbojpeg.TJDecompressor.setJPEGImage(byte[], int) - - - - -org.libjpegturbo.turbojpeg.TJCompressor.setSourceImage(byte[], int, int, int, int) +org.libjpegturbo.turbojpeg.TJCompressor.setSourceImage(byte[], int, int, int, int) + TJCompressor.setSourceImage(byte[], int, int, int, int, int, int) instead.
@@ -201,9 +191,9 @@ -org.libjpegturbo.turbojpeg.TJCompressor(byte[], int, int, int, int) +org.libjpegturbo.turbojpeg.TJCompressor(byte[], int, int, int, int) + TJCompressor.TJCompressor(byte[], int, int, int, int, int, int) instead.
diff --git a/java/doc/index-all.html b/java/doc/index-all.html index fa92e3c9..1af78bed 100644 --- a/java/doc/index-all.html +++ b/java/doc/index-all.html @@ -63,20 +63,20 @@

B

-
bufSize(int, int, int) - Static method in class org.libjpegturbo.turbojpeg.TJ
+
bufSize(int, int, int) - Static method in class org.libjpegturbo.turbojpeg.TJ
Returns the maximum size of the buffer (in bytes) required to hold a JPEG image with the given width, height, and level of chrominance subsampling.
-
bufSizeYUV(int, int, int, int) - Static method in class org.libjpegturbo.turbojpeg.TJ
+
bufSizeYUV(int, int, int, int) - Static method in class org.libjpegturbo.turbojpeg.TJ
Returns the size of the buffer (in bytes) required to hold a YUV planar image with the given width, height, and level of chrominance subsampling.
-
bufSizeYUV(int, int, int) - Static method in class org.libjpegturbo.turbojpeg.TJ
+
bufSizeYUV(int, int, int) - Static method in class org.libjpegturbo.turbojpeg.TJ
@@ -97,7 +97,7 @@
Free the native structures associated with this decompressor instance.
-
compress(byte[], int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
+
compress(byte[], int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
Compress the uncompressed source image associated with this compressor instance and output a JPEG image to the given destination buffer.
@@ -107,19 +107,19 @@
Compress the uncompressed source image associated with this compressor instance and return a buffer containing a JPEG image.
-
compress(BufferedImage, byte[], int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
+
compress(BufferedImage, byte[], int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
-
compress(BufferedImage, int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
+
compress(BufferedImage, int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
@@ -143,7 +143,7 @@
YCCK colorspace.
-
customFilter(ShortBuffer, Rectangle, Rectangle, int, int, TJTransform) - Method in interface org.libjpegturbo.turbojpeg.TJCustomFilter
+
customFilter(ShortBuffer, Rectangle, Rectangle, int, int, TJTransform) - Method in interface org.libjpegturbo.turbojpeg.TJCustomFilter
A callback function that can be used to modify the DCT coefficients after they are losslessly transformed but before they are transcoded to a new @@ -155,64 +155,70 @@

D

-
decompress(byte[], int, int, int, int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
+
decompress(byte[], int, int, int, int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
Decompress the JPEG source image or decode the YUV source image associated with this decompressor instance and output a grayscale, RGB, or CMYK image to the given destination buffer.
-
decompress(byte[], int, int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
+
decompress(byte[], int, int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
-
decompress(int, int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
+
decompress(int, int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
Decompress the JPEG source image associated with this decompressor instance and return a buffer containing the decompressed image.
-
decompress(int[], int, int, int, int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
+
decompress(int[], int, int, int, int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
Decompress the JPEG source image or decode the YUV source image associated with this decompressor instance and output a grayscale, RGB, or CMYK image to the given destination buffer.
-
decompress(BufferedImage, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
+
decompress(BufferedImage, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
Decompress the JPEG source image or decode the YUV source image associated with this decompressor instance and output a decompressed/decoded image to the given BufferedImage instance.
-
decompress(int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
+
decompress(int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
Decompress the JPEG source image or decode the YUV source image associated with this decompressor instance and return a BufferedImage instance containing the decompressed/decoded image.
-
decompressToYUV(YUVImage, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
+
decompressToYUV(YUVImage, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
Decompress the JPEG source image associated with this decompressor instance into a YUV planar image and store it in the given YUVImage instance.
-
decompressToYUV(byte[], int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
+
decompressToYUV(byte[], int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
-
decompressToYUV(int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
+
decompressToYUV(int, int[], int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
Decompress the JPEG source image associated with this decompressor - instance into a YUV planar image and return a YUVImage - instance containing the decompressed image.
+ instance into a set of Y, U (Cb), and V (Cr) image planes and return a + YUVImage instance containing the decompressed image planes.
+ +
decompressToYUV(int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
+
+
Decompress the JPEG source image associated with this decompressor + instance into a unified YUV planar image buffer and return a + YUVImage instance containing the decompressed image.
decompressToYUV(int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
Deprecated. - +
@@ -221,44 +227,50 @@

E

-
encodeYUV(YUVImage, int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
+
encodeYUV(YUVImage, int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
Encode the uncompressed source image associated with this compressor instance into a YUV planar image and store it in the given YUVImage instance.
-
encodeYUV(byte[], int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
+
encodeYUV(byte[], int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
-
encodeYUV(int, int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
+
encodeYUV(int, int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
Encode the uncompressed source image associated with this compressor - instance into a YUV planar image and return a YUVImage - instance containing the encoded image.
+ instance into a unified YUV planar image buffer and return a + YUVImage instance containing the encoded image. +
+
encodeYUV(int[], int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
+
+
Encode the uncompressed source image associated with this compressor + instance into separate Y, U (Cb), and V (Cr) image planes and return a + YUVImage instance containing the encoded image planes.
encodeYUV(int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
-
encodeYUV(BufferedImage, byte[], int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
+
encodeYUV(BufferedImage, byte[], int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
-
encodeYUV(BufferedImage, int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
+
encodeYUV(BufferedImage, int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
equals(TJScalingFactor) - Method in class org.libjpegturbo.turbojpeg.TJScalingFactor
@@ -325,7 +337,8 @@
getBuf() - Method in class org.libjpegturbo.turbojpeg.YUVImage
-
Returns the YUV image buffer
+
Returns the YUV image buffer (if this image is stored in a unified + buffer rather than separate image planes.)
getColorspace() - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
@@ -335,7 +348,7 @@
getCompressedSize() - Method in class org.libjpegturbo.turbojpeg.TJCompressor
Returns the size of the image (in bytes) generated by the most recent - compress/encode operation.
+ compress operation.
getDenom() - Method in class org.libjpegturbo.turbojpeg.TJScalingFactor
@@ -353,19 +366,16 @@
getHeight() - Method in class org.libjpegturbo.turbojpeg.YUVImage
-
Returns the height of the YUV image.
+
Returns the height of the YUV image (or subregion.)
getJPEGBuf() - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
-
Deprecated. - -
+
Returns the JPEG image buffer associated with this decompressor instance.
getJPEGSize() - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
-
Deprecated. - -
+
Returns the size of the JPEG image (in bytes) associated with this + decompressor instance.
getMCUHeight(int) - Static method in class org.libjpegturbo.turbojpeg.TJ
@@ -381,14 +391,24 @@
Returns numerator
+
getOffsets() - Method in class org.libjpegturbo.turbojpeg.YUVImage
+
+
Returns the offsets (in bytes) of each plane within the planes of a larger + YUV image.
+
getPad() - Method in class org.libjpegturbo.turbojpeg.YUVImage
-
Returns the line padding used in the YUV image buffer.
+
Returns the line padding used in the YUV image buffer (if this image is + stored in a unified buffer rather than separate image planes.)
getPixelSize(int) - Static method in class org.libjpegturbo.turbojpeg.TJ
Returns the pixel size (in bytes) for the given pixel format.
+
getPlanes() - Method in class org.libjpegturbo.turbojpeg.YUVImage
+
+
Returns the YUV image planes.
+
getRedOffset(int) - Static method in class org.libjpegturbo.turbojpeg.TJ
For the given pixel format, returns the number of bytes that the red @@ -398,13 +418,13 @@
Returns the scaled value of dimension.
-
getScaledHeight(int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
+
getScaledHeight(int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
Returns the height of the largest scaled-down image that the TurboJPEG decompressor can generate without exceeding the desired image width and height.
-
getScaledWidth(int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
+
getScaledWidth(int, int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
Returns the width of the largest scaled-down image that the TurboJPEG decompressor can generate without exceeding the desired image width and @@ -417,17 +437,12 @@
getSize() - Method in class org.libjpegturbo.turbojpeg.YUVImage
-
Returns the size (in bytes) of the YUV image buffer
+
Returns the size (in bytes) of the YUV image buffer (if this image is + stored in a unified buffer rather than separate image planes.)
-
getSourceBuf() - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
+
getStrides() - Method in class org.libjpegturbo.turbojpeg.YUVImage
-
Returns the source image buffer associated with this decompressor - instance.
-
-
getSourceSize() - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
-
-
Returns the size of the source image (in bytes) associated with this - decompressor instance.
+
Returns the number of bytes per line of each plane in the YUV image.
getSubsamp() - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
@@ -450,7 +465,7 @@
getWidth() - Method in class org.libjpegturbo.turbojpeg.YUVImage
-
Returns the width of the YUV image.
+
Returns the width of the YUV image (or subregion.)
@@ -483,6 +498,14 @@
 
jpegBufSize - Variable in class org.libjpegturbo.turbojpeg.TJDecompressor
 
+
jpegColorspace - Variable in class org.libjpegturbo.turbojpeg.TJDecompressor
+
 
+
jpegHeight - Variable in class org.libjpegturbo.turbojpeg.TJDecompressor
+
 
+
jpegSubsamp - Variable in class org.libjpegturbo.turbojpeg.TJDecompressor
+
 
+
jpegWidth - Variable in class org.libjpegturbo.turbojpeg.TJDecompressor
+
 
@@ -559,12 +582,12 @@
OPT_NOOUTPUT - Static variable in class org.libjpegturbo.turbojpeg.TJTransform
-
This option will prevent TJTransformer.transform() from outputting a JPEG image for this +
This option will prevent TJTransformer.transform() from outputting a JPEG image for this particular transform.
OPT_PERFECT - Static variable in class org.libjpegturbo.turbojpeg.TJTransform
-
This option will cause TJTransformer.transform() to throw an exception if the transform is not +
This option will cause TJTransformer.transform() to throw an exception if the transform is not perfect.
OPT_TRIM - Static variable in class org.libjpegturbo.turbojpeg.TJTransform
@@ -632,6 +655,19 @@
XRGB pixel format.
+
planeHeight(int, int, int) - Static method in class org.libjpegturbo.turbojpeg.TJ
+
+
Returns the plane height of a YUV image plane with the given parameters.
+
+
planeSizeYUV(int, int, int, int, int) - Static method in class org.libjpegturbo.turbojpeg.TJ
+
+
Returns the size of the buffer (in bytes) required to hold a YUV image + plane with the given parameters.
+
+
planeWidth(int, int, int) - Static method in class org.libjpegturbo.turbojpeg.TJ
+
+
Returns the plane width of a YUV image plane with the given parameters.
+
@@ -662,34 +698,37 @@
Grayscale.
-
setBuf(byte[], int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.YUVImage
+
setBuf(byte[][], int[], int, int[], int, int) - Method in class org.libjpegturbo.turbojpeg.YUVImage
-
Assign an existing YUV planar image buffer to this YUVImage - instance.
+
Assign a set of image planes to this YUVImage instance.
-
setJPEGImage(byte[], int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
+
setBuf(byte[], int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.YUVImage
+
+
Assign a unified image buffer to this YUVImage instance.
+
+
setJPEGImage(byte[], int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
Deprecated. - +
setJPEGQuality(int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
Set the JPEG image quality level for subsequent compress operations.
-
setSourceImage(byte[], int, int, int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
+
setSourceImage(byte[], int, int, int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
Associate an uncompressed RGB, grayscale, or CMYK source image with this compressor instance.
-
setSourceImage(byte[], int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
+
setSourceImage(byte[], int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
Deprecated. + TJCompressor.setSourceImage(byte[], int, int, int, int, int, int) instead.
-
setSourceImage(BufferedImage, int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
+
setSourceImage(BufferedImage, int, int, int, int) - Method in class org.libjpegturbo.turbojpeg.TJCompressor
Associate an uncompressed RGB or grayscale source image with this compressor instance.
@@ -699,10 +738,10 @@
Associate an uncompressed YUV planar source image with this compressor instance.
-
setSourceImage(byte[], int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
+
setSourceImage(byte[], int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
Associate the JPEG image of length imageSize bytes stored in - srcImage with this decompressor instance.
+ jpegImage with this decompressor instance.
setSourceImage(YUVImage) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
@@ -714,14 +753,6 @@
Set the level of chrominance subsampling for subsequent compress/encode operations.
-
srcColorspace - Variable in class org.libjpegturbo.turbojpeg.TJDecompressor
-
 
-
srcHeight - Variable in class org.libjpegturbo.turbojpeg.TJDecompressor
-
 
-
srcSubsamp - Variable in class org.libjpegturbo.turbojpeg.TJDecompressor
-
 
-
srcWidth - Variable in class org.libjpegturbo.turbojpeg.TJDecompressor
-
 
@@ -742,20 +773,20 @@
Create a TurboJPEG compressor instance.
-
TJCompressor(byte[], int, int, int, int, int, int) - Constructor for class org.libjpegturbo.turbojpeg.TJCompressor
+
TJCompressor(byte[], int, int, int, int, int, int) - Constructor for class org.libjpegturbo.turbojpeg.TJCompressor
Create a TurboJPEG compressor instance and associate the uncompressed source image stored in srcImage with the newly created instance.
-
TJCompressor(byte[], int, int, int, int) - Constructor for class org.libjpegturbo.turbojpeg.TJCompressor
+
TJCompressor(byte[], int, int, int, int) - Constructor for class org.libjpegturbo.turbojpeg.TJCompressor
Deprecated. + TJCompressor.TJCompressor(byte[], int, int, int, int, int, int) instead.
-
TJCompressor(BufferedImage, int, int, int, int) - Constructor for class org.libjpegturbo.turbojpeg.TJCompressor
+
TJCompressor(BufferedImage, int, int, int, int) - Constructor for class org.libjpegturbo.turbojpeg.TJCompressor
Create a TurboJPEG compressor instance and associate the uncompressed source image stored in srcImage with the newly created @@ -778,7 +809,7 @@
Create a TurboJPEG decompressor instance and associate the JPEG source image stored in jpegImage with the newly created instance.
-
TJDecompressor(byte[], int) - Constructor for class org.libjpegturbo.turbojpeg.TJDecompressor
+
TJDecompressor(byte[], int) - Constructor for class org.libjpegturbo.turbojpeg.TJDecompressor
Create a TurboJPEG decompressor instance and associate the JPEG source image of length imageSize bytes stored in @@ -794,7 +825,7 @@
Fractional scaling factor
-
TJScalingFactor(int, int) - Constructor for class org.libjpegturbo.turbojpeg.TJScalingFactor
+
TJScalingFactor(int, int) - Constructor for class org.libjpegturbo.turbojpeg.TJScalingFactor
 
TJTransform - Class in org.libjpegturbo.turbojpeg
@@ -804,11 +835,11 @@
Create a new lossless transform instance.
-
TJTransform(int, int, int, int, int, int, TJCustomFilter) - Constructor for class org.libjpegturbo.turbojpeg.TJTransform
+
TJTransform(int, int, int, int, int, int, TJCustomFilter) - Constructor for class org.libjpegturbo.turbojpeg.TJTransform
Create a new lossless transform instance with the given parameters.
-
TJTransform(Rectangle, int, int, TJCustomFilter) - Constructor for class org.libjpegturbo.turbojpeg.TJTransform
+
TJTransform(Rectangle, int, int, TJCustomFilter) - Constructor for class org.libjpegturbo.turbojpeg.TJTransform
Create a new lossless transform instance with the given parameters.
@@ -825,19 +856,19 @@
Create a TurboJPEG lossless transformer instance and associate the JPEG image stored in jpegImage with the newly created instance.
-
TJTransformer(byte[], int) - Constructor for class org.libjpegturbo.turbojpeg.TJTransformer
+
TJTransformer(byte[], int) - Constructor for class org.libjpegturbo.turbojpeg.TJTransformer
Create a TurboJPEG lossless transformer instance and associate the JPEG image of length imageSize bytes stored in jpegImage with the newly created instance.
-
transform(byte[][], TJTransform[], int) - Method in class org.libjpegturbo.turbojpeg.TJTransformer
+
transform(byte[][], TJTransform[], int) - Method in class org.libjpegturbo.turbojpeg.TJTransformer
Losslessly transform the JPEG image associated with this transformer instance into one or more JPEG images stored in the given destination buffers.
-
transform(TJTransform[], int) - Method in class org.libjpegturbo.turbojpeg.TJTransformer
+
transform(TJTransform[], int) - Method in class org.libjpegturbo.turbojpeg.TJTransformer
Losslessly transform the JPEG image associated with this transformer instance and return an array of TJDecompressor instances, each of @@ -849,28 +880,43 @@

Y

-
yuvBuf - Variable in class org.libjpegturbo.turbojpeg.YUVImage
-
 
yuvHeight - Variable in class org.libjpegturbo.turbojpeg.YUVImage
 
yuvImage - Variable in class org.libjpegturbo.turbojpeg.TJDecompressor
 
YUVImage - Class in org.libjpegturbo.turbojpeg
-
This class encapsulates a YUV planar image buffer and the metadata +
This class encapsulates a YUV planar image and the metadata associated with it.
-
YUVImage(int, int, int, int) - Constructor for class org.libjpegturbo.turbojpeg.YUVImage
+
YUVImage(int, int[], int, int) - Constructor for class org.libjpegturbo.turbojpeg.YUVImage
-
Create a YUVImage instance with a new image buffer.
+
Create a new YUVImage instance backed by separate image + planes, and allocate memory for the image planes.
-
YUVImage(byte[], int, int, int, int) - Constructor for class org.libjpegturbo.turbojpeg.YUVImage
+
YUVImage(int, int, int, int) - Constructor for class org.libjpegturbo.turbojpeg.YUVImage
-
Create a YUVImage instance from an existing YUV planar image +
Create a new YUVImage instance backed by a unified image + buffer, and allocate memory for the image buffer.
+
+
YUVImage(byte[][], int[], int, int[], int, int) - Constructor for class org.libjpegturbo.turbojpeg.YUVImage
+
+
Create a new YUVImage instance from a set of existing image + planes.
+
+
YUVImage(byte[], int, int, int, int) - Constructor for class org.libjpegturbo.turbojpeg.YUVImage
+
+
Create a new YUVImage instance from an existing unified image buffer.
+
yuvOffsets - Variable in class org.libjpegturbo.turbojpeg.YUVImage
+
 
yuvPad - Variable in class org.libjpegturbo.turbojpeg.YUVImage
 
+
yuvPlanes - Variable in class org.libjpegturbo.turbojpeg.YUVImage
+
 
+
yuvStrides - Variable in class org.libjpegturbo.turbojpeg.YUVImage
+
 
yuvSubsamp - Variable in class org.libjpegturbo.turbojpeg.YUVImage
 
yuvWidth - Variable in class org.libjpegturbo.turbojpeg.YUVImage
diff --git a/java/doc/index.html b/java/doc/index.html index 25a639d4..b9839573 100644 --- a/java/doc/index.html +++ b/java/doc/index.html @@ -10,6 +10,12 @@ if (targetPage.indexOf(":") != -1 || (targetPage != "" && !validURL(targetPage))) targetPage = "undefined"; function validURL(url) { + try { + url = decodeURIComponent(url); + } + catch (error) { + return false; + } var pos = url.indexOf(".html"); if (pos == -1 || pos != url.length - 5) return false; @@ -21,7 +27,8 @@ if ('a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '$' || - ch == '_') { + ch == '_' || + ch.charCodeAt(0) > 127) { allowNumber = true; allowSep = true; } else if ('0' <= ch && ch <= '9' diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJ.html b/java/doc/org/libjpegturbo/turbojpeg/TJ.html index ee22e763..f8342f24 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/TJ.html +++ b/java/doc/org/libjpegturbo/turbojpeg/TJ.html @@ -355,7 +355,7 @@ extends java.lang.Object static int -bufSize(int width, +bufSize(int width, int height, int jpegSubsamp)
Returns the maximum size of the buffer (in bytes) required to hold a JPEG @@ -364,17 +364,17 @@ extends java.lang.Object static int -bufSizeYUV(int width, +bufSizeYUV(int width, int height, int subsamp)
Deprecated.  - +
static int -bufSizeYUV(int width, +bufSizeYUV(int width, int pad, int height, int subsamp) @@ -430,6 +430,33 @@ extends java.lang.Object this implementation of TurboJPEG supports.
+ +static int +planeHeight(int componentID, + int height, + int subsamp) +
Returns the plane height of a YUV image plane with the given parameters.
+ + + +static int +planeSizeYUV(int componentID, + int width, + int stride, + int height, + int subsamp) +
Returns the size of the buffer (in bytes) required to hold a YUV image + plane with the given parameters.
+ + + +static int +planeWidth(int componentID, + int width, + int subsamp) +
Returns the plane width of a YUV image plane with the given parameters.
+ +
Parameters:
subsamp - the level of chrominance subsampling (one of SAMP_*)
-
Returns:
the MCU block width for the given level of chrominance subsampling
+
Returns:
the MCU block width for the given level of chrominance + subsampling.
Throws:
java.lang.Exception
@@ -980,7 +1008,7 @@ public static final int FLAG_FORCESSE3
Parameters:
subsamp - the level of chrominance subsampling (one of SAMP_*)
Returns:
the MCU block height for the given level of chrominance - subsampling
+ subsampling.
Throws:
java.lang.Exception
@@ -995,7 +1023,7 @@ public static final int FLAG_FORCESSE3 throws java.lang.Exception
Returns the pixel size (in bytes) for the given pixel format.
Parameters:
pixelFormat - the pixel format (one of PF_*)
-
Returns:
the pixel size (in bytes) for the given pixel format
+
Returns:
the pixel size (in bytes) for the given pixel format.
Throws:
java.lang.Exception
@@ -1014,7 +1042,7 @@ public static final int FLAG_FORCESSE3 then the red component will be pixel[TJ.getRedOffset(TJ.PF_BGRX)].
Parameters:
pixelFormat - the pixel format (one of PF_*)
-
Returns:
the red offset for the given pixel format
+
Returns:
the red offset for the given pixel format.
Throws:
java.lang.Exception
@@ -1033,7 +1061,7 @@ public static final int FLAG_FORCESSE3 then the green component will be pixel[TJ.getGreenOffset(TJ.PF_BGRX)].
Parameters:
pixelFormat - the pixel format (one of PF_*)
-
Returns:
the green offset for the given pixel format
+
Returns:
the green offset for the given pixel format.
Throws:
java.lang.Exception
@@ -1052,7 +1080,7 @@ public static final int FLAG_FORCESSE3 then the blue component will be pixel[TJ.getBlueOffset(TJ.PF_BGRX)].
Parameters:
pixelFormat - the pixel format (one of PF_*)
-
Returns:
the blue offset for the given pixel format
+
Returns:
the blue offset for the given pixel format.
Throws:
java.lang.Exception
@@ -1072,7 +1100,7 @@ public static final int FLAG_FORCESSE3
Parameters:
width - the width (in pixels) of the JPEG image
height - the height (in pixels) of the JPEG image
jpegSubsamp - the level of chrominance subsampling to be used when generating the JPEG image (one of TJ.SAMP_*)
Returns:
the maximum size of the buffer (in bytes) required to hold a JPEG - image with the given width, height, and level of chrominance subsampling
+ image with the given width, height, and level of chrominance subsampling.
Throws:
java.lang.Exception
@@ -1091,11 +1119,10 @@ public static final int FLAG_FORCESSE3
Returns the size of the buffer (in bytes) required to hold a YUV planar image with the given width, height, and level of chrominance subsampling.
Parameters:
width - the width (in pixels) of the YUV image
pad - the width of each line in each plane of the image is padded to - the nearest multiple of this number of bytes (must be a power of - 2.)
height - the height (in pixels) of the YUV image
subsamp - the level of chrominance subsampling used in the YUV + the nearest multiple of this number of bytes (must be a power of 2.)
height - the height (in pixels) of the YUV image
subsamp - the level of chrominance subsampling used in the YUV image (one of TJ.SAMP_*)
Returns:
the size of the buffer (in bytes) required to hold a YUV planar - image with the given width, height, and level of chrominance subsampling
+ image with the given width, height, and level of chrominance subsampling.
Throws:
java.lang.Exception
@@ -1111,11 +1138,76 @@ public static int bufSizeYUV(int width, int height, int subsamp) throws java.lang.Exception -
Deprecated. Use bufSizeYUV(int, int, int, int) instead.
+
Deprecated. Use bufSizeYUV(int, int, int, int) instead.
Throws:
java.lang.Exception
+ + + + + + + + + + + + @@ -1127,7 +1219,7 @@ public static int bufSizeYUV(int width,
Returns a list of fractional scaling factors that the JPEG decompressor in this implementation of TurboJPEG supports.
Returns:
a list of fractional scaling factors that the JPEG decompressor in - this implementation of TurboJPEG supports
+ this implementation of TurboJPEG supports.
Throws:
java.lang.Exception
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJCompressor.html b/java/doc/org/libjpegturbo/turbojpeg/TJCompressor.html index 6c367a70..93872531 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/TJCompressor.html +++ b/java/doc/org/libjpegturbo/turbojpeg/TJCompressor.html @@ -118,7 +118,7 @@ extends java.lang.Object -TJCompressor(java.awt.image.BufferedImage srcImage, +TJCompressor(java.awt.image.BufferedImage srcImage, int x, int y, int width, @@ -129,19 +129,19 @@ extends java.lang.Object -TJCompressor(byte[] srcImage, +TJCompressor(byte[] srcImage, int width, int pitch, int height, int pixelFormat) -TJCompressor(byte[] srcImage, +TJCompressor(byte[] srcImage, int x, int y, int width, @@ -176,30 +176,30 @@ extends java.lang.Object void -compress(java.awt.image.BufferedImage srcImage, +compress(java.awt.image.BufferedImage srcImage, byte[] dstBuf, int flags) byte[] -compress(java.awt.image.BufferedImage srcImage, +compress(java.awt.image.BufferedImage srcImage, int flags) void -compress(byte[] dstBuf, +compress(byte[] dstBuf, int flags)
Compress the uncompressed source image associated with this compressor instance and output a JPEG image to the given destination buffer.
@@ -214,33 +214,33 @@ extends java.lang.Object void -encodeYUV(java.awt.image.BufferedImage srcImage, +encodeYUV(java.awt.image.BufferedImage srcImage, byte[] dstBuf, int flags) byte[] -encodeYUV(java.awt.image.BufferedImage srcImage, +encodeYUV(java.awt.image.BufferedImage srcImage, int flags) void -encodeYUV(byte[] dstBuf, +encodeYUV(byte[] dstBuf, int flags)
Deprecated.  - +
@@ -248,48 +248,57 @@ extends java.lang.Object byte[] encodeYUV(int flags)
Deprecated.  -
Use encodeYUV(int, int) instead.
+
Use encodeYUV(int, int) instead.
YUVImage -encodeYUV(int pad, +encodeYUV(int[] strides, int flags)
Encode the uncompressed source image associated with this compressor - instance into a YUV planar image and return a YUVImage - instance containing the encoded image.
+ instance into separate Y, U (Cb), and V (Cr) image planes and return a + YUVImage instance containing the encoded image planes. +YUVImage +encodeYUV(int pad, + int flags) +
Encode the uncompressed source image associated with this compressor + instance into a unified YUV planar image buffer and return a + YUVImage instance containing the encoded image.
+ + + void -encodeYUV(YUVImage dstImage, +encodeYUV(YUVImage dstImage, int flags)
Encode the uncompressed source image associated with this compressor instance into a YUV planar image and store it in the given YUVImage instance.
- + protected void finalize()  - + int getCompressedSize()
Returns the size of the image (in bytes) generated by the most recent - compress/encode operation.
+ compress operation. - + void setJPEGQuality(int quality)
Set the JPEG image quality level for subsequent compress operations.
- + void -setSourceImage(java.awt.image.BufferedImage srcImage, +setSourceImage(java.awt.image.BufferedImage srcImage, int x, int y, int width, @@ -298,22 +307,22 @@ extends java.lang.Object compressor instance. - + void -setSourceImage(byte[] srcImage, +setSourceImage(byte[] srcImage, int width, int pitch, int height, int pixelFormat) - + void -setSourceImage(byte[] srcImage, +setSourceImage(byte[] srcImage, int x, int y, int width, @@ -324,14 +333,14 @@ extends java.lang.Object compressor instance. - + void setSourceImage(YUVImage srcImage)
Associate an uncompressed YUV planar source image with this compressor instance.
- + void setSubsamp(int newSubsamp)
Set the level of chrominance subsampling for subsequent compress/encode @@ -390,7 +399,7 @@ extends java.lang.Object
Create a TurboJPEG compressor instance and associate the uncompressed source image stored in srcImage with the newly created instance.
-
Parameters:
srcImage - see setSourceImage(byte[], int, int, int, int, int, int) for description
x - see setSourceImage(byte[], int, int, int, int, int, int) for description
y - see setSourceImage(byte[], int, int, int, int, int, int) for description
width - see setSourceImage(byte[], int, int, int, int, int, int) for description
pitch - see setSourceImage(byte[], int, int, int, int, int, int) for description
height - see setSourceImage(byte[], int, int, int, int, int, int) for description
pixelFormat - pixel format of the source image (one of +
Parameters:
srcImage - see setSourceImage(byte[], int, int, int, int, int, int) for description
x - see setSourceImage(byte[], int, int, int, int, int, int) for description
y - see setSourceImage(byte[], int, int, int, int, int, int) for description
width - see setSourceImage(byte[], int, int, int, int, int, int) for description
pitch - see setSourceImage(byte[], int, int, int, int, int, int) for description
height - see setSourceImage(byte[], int, int, int, int, int, int) for description
pixelFormat - pixel format of the source image (one of TJ.PF_*)
Throws:
java.lang.Exception
@@ -410,7 +419,7 @@ public TJCompressor(byte[] srcImage, int pixelFormat) throws java.lang.Exception + TJCompressor(byte[], int, int, int, int, int, int) instead.
Throws:
java.lang.Exception
@@ -431,11 +440,11 @@ public TJCompressor(byte[] srcImage, source image stored in srcImage with the newly created instance.
Parameters:
srcImage - see - setSourceImage(BufferedImage, int, int, int, int) for description
x - see - setSourceImage(BufferedImage, int, int, int, int) for description
y - see - setSourceImage(BufferedImage, int, int, int, int) for description
width - see - setSourceImage(BufferedImage, int, int, int, int) for description
height - see - setSourceImage(BufferedImage, int, int, int, int) for description
+ setSourceImage(BufferedImage, int, int, int, int) for description
x - see + setSourceImage(BufferedImage, int, int, int, int) for description
y - see + setSourceImage(BufferedImage, int, int, int, int) for description
width - see + setSourceImage(BufferedImage, int, int, int, int) for description
height - see + setSourceImage(BufferedImage, int, int, int, int) for description
Throws:
java.lang.Exception
@@ -496,7 +505,7 @@ public void setSourceImage(byte[] srcImage, int pixelFormat) throws java.lang.Exception + setSourceImage(byte[], int, int, int, int, int, int) instead.
Throws:
java.lang.Exception
@@ -599,7 +608,7 @@ public void setSourceImage(byte[] srcImage,
Compress the uncompressed source image associated with this compressor instance and output a JPEG image to the given destination buffer.
Parameters:
dstBuf - buffer that will receive the JPEG image. Use - TJ.bufSize(int, int, int) to determine the maximum size for this buffer based on + TJ.bufSize(int, int, int) to determine the maximum size for this buffer based on the source image's width and height and the desired level of chrominance subsampling.
flags - the bitwise OR of one or more of TJ.FLAG_*
@@ -637,8 +646,8 @@ public void compress(java.awt.image.BufferedImage srcImage, int flags) throws java.lang.Exception + setSourceImage(BufferedImage, int, int, int, int) and + compress(byte[], int) instead.
Throws:
java.lang.Exception
@@ -654,7 +663,7 @@ public byte[] compress(java.awt.image.BufferedImage srcImage, int flags) throws java.lang.Exception
Throws:
java.lang.Exception
@@ -692,7 +701,7 @@ public byte[] compress(java.awt.image.BufferedImage srcImage, public void encodeYUV(byte[] dstBuf, int flags) throws java.lang.Exception -
Deprecated. Use encodeYUV(YUVImage, int) instead.
+
Deprecated. Use encodeYUV(YUVImage, int) instead.
Throws:
java.lang.Exception
@@ -707,16 +716,44 @@ public void encodeYUV(byte[] dstBuf, int flags) throws java.lang.Exception
Encode the uncompressed source image associated with this compressor - instance into a YUV planar image and return a YUVImage - instance containing the encoded image. This method uses the accelerated - color conversion routines in TurboJPEG's underlying codec but does not - execute any of the other steps in the JPEG compression process. Encoding - CMYK source images to YUV is not supported.
+ instance into a unified YUV planar image buffer and return a + YUVImage instance containing the encoded image. This method + uses the accelerated color conversion routines in TurboJPEG's underlying + codec but does not execute any of the other steps in the JPEG compression + process. Encoding CMYK source images to YUV is not supported.
Parameters:
pad - the width of each line in each plane of the YUV image will be padded to the nearest multiple of this number of bytes (must be a power of 2.)
flags - the bitwise OR of one or more of TJ.FLAG_*
-
Returns:
a YUV planar image
+
Returns:
a YUV planar image.
+
Throws:
+
java.lang.Exception
+ + + + + +
    +
  • +

    encodeYUV

    +
    public YUVImage encodeYUV(int[] strides,
    +                 int flags)
    +                   throws java.lang.Exception
    +
    Encode the uncompressed source image associated with this compressor + instance into separate Y, U (Cb), and V (Cr) image planes and return a + YUVImage instance containing the encoded image planes. This + method uses the accelerated color conversion routines in TurboJPEG's + underlying codec but does not execute any of the other steps in the JPEG + compression process. Encoding CMYK source images to YUV is not supported.
    +
    Parameters:
    strides - an array of integers, each specifying the number of bytes + per line in the corresponding plane of the output image. Setting the + stride for any plane to 0 is the same as setting it to the component width + of the plane. If strides is null, then the strides for all + planes will be set to their respective component widths. You can adjust + the strides in order to add an arbitrary amount of line padding to each + plane.
    flags - the bitwise OR of one or more of + TJ.FLAG_*
    +
    Returns:
    a YUV planar image.
    Throws:
    java.lang.Exception
  • @@ -730,7 +767,7 @@ public void encodeYUV(byte[] dstBuf,
    @Deprecated
     public byte[] encodeYUV(int flags)
                      throws java.lang.Exception
    -
    Deprecated. Use encodeYUV(int, int) instead.
    +
    Deprecated. Use encodeYUV(int, int) instead.
    Throws:
    java.lang.Exception
    @@ -747,8 +784,8 @@ public void encodeYUV(java.awt.image.BufferedImage srcImage, int flags) throws java.lang.Exception + setSourceImage(BufferedImage, int, int, int, int) and + encodeYUV(byte[], int) instead.
    Throws:
    java.lang.Exception
    @@ -764,8 +801,8 @@ public byte[] encodeYUV(java.awt.image.BufferedImage srcImage, int flags) throws java.lang.Exception + setSourceImage(BufferedImage, int, int, int, int) and + encodeYUV(int, int) instead.
    Throws:
    java.lang.Exception
    @@ -778,9 +815,9 @@ public byte[] encodeYUV(java.awt.image.BufferedImage srcImage,

    getCompressedSize

    public int getCompressedSize()
    Returns the size of the image (in bytes) generated by the most recent - compress/encode operation.
    + compress operation.
    Returns:
    the size of the image (in bytes) generated by the most recent - compress/encode operation
    + compress operation.
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJCustomFilter.html b/java/doc/org/libjpegturbo/turbojpeg/TJCustomFilter.html index bac519b9..c2b6e613 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/TJCustomFilter.html +++ b/java/doc/org/libjpegturbo/turbojpeg/TJCustomFilter.html @@ -106,7 +106,7 @@ void -customFilter(java.nio.ShortBuffer coeffBuffer, +customFilter(java.nio.ShortBuffer coeffBuffer, java.awt.Rectangle bufferRegion, java.awt.Rectangle planeRegion, int componentID, @@ -162,7 +162,7 @@ coeffBuffer belongs (Y, Cb, and Cr have, respectively, ID's of 0, 1, and 2 in typical JPEG images.)
transformID - ID number of the transformed image to which coeffBuffer belongs. This is the same as the index of the - transform in the transforms array that was passed to TJTransformer.transform().
transform - a TJTransform instance that specifies the + transform in the transforms array that was passed to TJTransformer.transform().
transform - a TJTransform instance that specifies the parameters and/or cropping region for this transform
Throws:
java.lang.Exception
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html b/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html index af6a9020..faf9b6e9 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html +++ b/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html @@ -131,19 +131,19 @@ extends java.lang.Object protected int -srcColorspace  +jpegColorspace  protected int -srcHeight  +jpegHeight  protected int -srcSubsamp  +jpegSubsamp  protected int -srcWidth  +jpegWidth  protected YUVImage @@ -175,7 +175,7 @@ extends java.lang.Object -TJDecompressor(byte[] jpegImage, +TJDecompressor(byte[] jpegImage, int imageSize)
Create a TurboJPEG decompressor instance and associate the JPEG source image of length imageSize bytes stored in @@ -212,7 +212,7 @@ extends java.lang.Object void -decompress(java.awt.image.BufferedImage dstImage, +decompress(java.awt.image.BufferedImage dstImage, int flags)
Decompress the JPEG source image or decode the YUV source image associated with this decompressor instance and output a decompressed/decoded image to @@ -221,7 +221,7 @@ extends java.lang.Object void -decompress(byte[] dstBuf, +decompress(byte[] dstBuf, int desiredWidth, int pitch, int desiredHeight, @@ -229,13 +229,13 @@ extends java.lang.Object int flags)
void -decompress(byte[] dstBuf, +decompress(byte[] dstBuf, int x, int y, int desiredWidth, @@ -250,7 +250,7 @@ extends java.lang.Object void -decompress(int[] dstBuf, +decompress(int[] dstBuf, int x, int y, int desiredWidth, @@ -265,7 +265,7 @@ extends java.lang.Object java.awt.image.BufferedImage -decompress(int desiredWidth, +decompress(int desiredWidth, int desiredHeight, int bufferedImageType, int flags) @@ -276,7 +276,7 @@ extends java.lang.Object byte[] -decompress(int desiredWidth, +decompress(int desiredWidth, int pitch, int desiredHeight, int pixelFormat, @@ -287,10 +287,10 @@ extends java.lang.Object void -decompressToYUV(byte[] dstBuf, +decompressToYUV(byte[] dstBuf, int flags)
Deprecated.  - +
@@ -298,128 +298,122 @@ extends java.lang.Object byte[] decompressToYUV(int flags) YUVImage -decompressToYUV(int desiredWidth, +decompressToYUV(int desiredWidth, + int[] strides, + int desiredHeight, + int flags) +
Decompress the JPEG source image associated with this decompressor + instance into a set of Y, U (Cb), and V (Cr) image planes and return a + YUVImage instance containing the decompressed image planes.
+ + + +YUVImage +decompressToYUV(int desiredWidth, int pad, int desiredHeight, int flags)
Decompress the JPEG source image associated with this decompressor - instance into a YUV planar image and return a YUVImage - instance containing the decompressed image.
+ instance into a unified YUV planar image buffer and return a + YUVImage instance containing the decompressed image.
- + void -decompressToYUV(YUVImage dstImage, +decompressToYUV(YUVImage dstImage, int flags)
Decompress the JPEG source image associated with this decompressor instance into a YUV planar image and store it in the given YUVImage instance.
- + protected void finalize()  - + int getColorspace()
Returns the colorspace used in the source image (JPEG or YUV) associated with this decompressor instance.
- + int getHeight()
Returns the height of the source image (JPEG or YUV) associated with this decompressor instance.
- + byte[] getJPEGBuf() -
Deprecated.  -
Use getSourceBuf() instead.
-
+
Returns the JPEG image buffer associated with this decompressor instance.
+ + + +int +getJPEGSize() +
Returns the size of the JPEG image (in bytes) associated with this + decompressor instance.
int -getJPEGSize() -
Deprecated.  -
Use getSourceSize() instead.
-
- - - -int -getScaledHeight(int desiredWidth, +getScaledHeight(int desiredWidth, int desiredHeight)
Returns the height of the largest scaled-down image that the TurboJPEG decompressor can generate without exceeding the desired image width and height.
- + int -getScaledWidth(int desiredWidth, +getScaledWidth(int desiredWidth, int desiredHeight)
Returns the width of the largest scaled-down image that the TurboJPEG decompressor can generate without exceeding the desired image width and height.
- -byte[] -getSourceBuf() -
Returns the source image buffer associated with this decompressor - instance.
- - int -getSourceSize() -
Returns the size of the source image (in bytes) associated with this - decompressor instance.
- - - -int getSubsamp()
Returns the level of chrominance subsampling used in the source image (JPEG or YUV) associated with this decompressor instance.
- + int getWidth()
Returns the width of the source image (JPEG or YUV) associated with this decompressor instance.
- + void -setJPEGImage(byte[] jpegImage, +setJPEGImage(byte[] jpegImage, int imageSize)
Deprecated.  - +
- + void -setSourceImage(byte[] srcImage, +setSourceImage(byte[] jpegImage, int imageSize)
Associate the JPEG image of length imageSize bytes stored in - srcImage with this decompressor instance.
+ jpegImage with this decompressor instance. - + void setSourceImage(YUVImage srcImage)
Associate the specified YUV planar source image with this decompressor @@ -484,40 +478,40 @@ extends java.lang.Object
protected YUVImage yuvImage
- +
  • -

    srcWidth

    -
    protected int srcWidth
    +

    jpegWidth

    +
    protected int jpegWidth
- +
  • -

    srcHeight

    -
    protected int srcHeight
    +

    jpegHeight

    +
    protected int jpegHeight
- +
  • -

    srcSubsamp

    -
    protected int srcSubsamp
    +

    jpegSubsamp

    +
    protected int jpegSubsamp
- +
  • -

    srcColorspace

    -
    protected int srcColorspace
    +

    jpegColorspace

    +
    protected int jpegColorspace
@@ -605,13 +599,13 @@ extends java.lang.Object
  • setSourceImage

    -
    public void setSourceImage(byte[] srcImage,
    +
    public void setSourceImage(byte[] jpegImage,
                       int imageSize)
                         throws java.lang.Exception
    Associate the JPEG image of length imageSize bytes stored in - srcImage with this decompressor instance. This image will + jpegImage with this decompressor instance. This image will be used as the source image for subsequent decompress operations.
    -
    Parameters:
    srcImage - JPEG image buffer
    imageSize - size of the JPEG image (in bytes)
    +
    Parameters:
    jpegImage - JPEG image buffer
    imageSize - size of the JPEG image (in bytes)
    Throws:
    java.lang.Exception
  • @@ -626,7 +620,7 @@ extends java.lang.Object public void setJPEGImage(byte[] jpegImage, int imageSize) throws java.lang.Exception -
    Deprecated. Use setSourceImage(byte[], int) instead.
    +
    Deprecated. Use setSourceImage(byte[], int) instead.
    Throws:
    java.lang.Exception
    @@ -659,7 +653,7 @@ public void setJPEGImage(byte[] jpegImage,
    Returns the width of the source image (JPEG or YUV) associated with this decompressor instance.
    Returns:
    the width of the source image (JPEG or YUV) associated with this - decompressor instance
    + decompressor instance.
    Throws:
    java.lang.Exception
    @@ -675,7 +669,7 @@ public void setJPEGImage(byte[] jpegImage,
    Returns the height of the source image (JPEG or YUV) associated with this decompressor instance.
    Returns:
    the height of the source image (JPEG or YUV) associated with this - decompressor instance
    + decompressor instance.
    Throws:
    java.lang.Exception
    @@ -692,7 +686,7 @@ public void setJPEGImage(byte[] jpegImage, (JPEG or YUV) associated with this decompressor instance. See TJ.SAMP_*.
Returns:
the level of chrominance subsampling used in the source image - (JPEG or YUV) associated with this decompressor instance
+ (JPEG or YUV) associated with this decompressor instance.
Throws:
java.lang.Exception
@@ -709,22 +703,7 @@ public void setJPEGImage(byte[] jpegImage, with this decompressor instance. See TJ.CS_*. If the source image is YUV, then this always returns TJ.CS_YCbCr.
Returns:
the colorspace used in the source image (JPEG or YUV) associated - with this decompressor instance
-
Throws:
-
java.lang.Exception
- - - - - -
    -
  • -

    getSourceBuf

    -
    public byte[] getSourceBuf()
    -                    throws java.lang.Exception
    -
    Returns the source image buffer associated with this decompressor - instance.
    -
    Returns:
    the source image buffer associated with this decompressor instance
    + with this decompressor instance.
    Throws:
    java.lang.Exception
  • @@ -735,26 +714,10 @@ public void setJPEGImage(byte[] jpegImage,
    • getJPEGBuf

      -
      @Deprecated
      -public byte[] getJPEGBuf()
      +
      public byte[] getJPEGBuf()
                         throws java.lang.Exception
      -
      Deprecated. Use getSourceBuf() instead.
      -
      Throws:
      -
      java.lang.Exception
      -
    • -
    - - - -
      -
    • -

      getSourceSize

      -
      public int getSourceSize()
      -                  throws java.lang.Exception
      -
      Returns the size of the source image (in bytes) associated with this - decompressor instance.
      -
      Returns:
      the size of the source image (in bytes) associated with this - decompressor instance
      +
      Returns the JPEG image buffer associated with this decompressor instance.
      +
      Returns:
      the JPEG image buffer associated with this decompressor instance.
      Throws:
      java.lang.Exception
    • @@ -765,11 +728,13 @@ public byte[] getJPEGBuf()
      • getJPEGSize

        -
        @Deprecated
        -public int getJPEGSize()
        +
        public int getJPEGSize()
                         throws java.lang.Exception
        -
        Deprecated. Use getSourceSize() instead.
        -
        Throws:
        +
        Returns the size of the JPEG image (in bytes) associated with this + decompressor instance.
        +
        Returns:
        the size of the JPEG image (in bytes) associated with this + decompressor instance.
        +
        Throws:
        java.lang.Exception
      @@ -794,7 +759,7 @@ public int getJPEGSize() the scaled image size.)
      Returns:
      the width of the largest scaled-down image that the TurboJPEG decompressor can generate without exceeding the desired image width and - height
      + height.
      Throws:
      java.lang.Exception
      @@ -820,7 +785,7 @@ public int getJPEGSize() the scaled image size.)
      Returns:
      the height of the largest scaled-down image that the TurboJPEG decompressor can generate without exceeding the desired image width and - height
      + height.
      Throws:
      java.lang.Exception
      @@ -848,7 +813,7 @@ public int getJPEGSize() pitch * scaledHeight bytes in size, where scaledHeight can be determined by calling scalingFactor.getScaled(jpegHeight) - with one of the scaling factors returned from TJ.getScalingFactors() or by calling getScaledHeight(int, int). If the +
      with one of the scaling factors returned from TJ.getScalingFactors() or by calling getScaledHeight(int, int). If the source image is a YUV image, then this buffer should normally be pitch * height bytes in size, where height is the height of the YUV image. However, the buffer may also be larger than @@ -872,7 +837,7 @@ public int getJPEGSize() if the source image is a JPEG image, then scaledWidth can be determined by calling scalingFactor.getScaled(jpegWidth) - or by calling getScaledWidth(int, int). If the source image is a + or by calling getScaledWidth(int, int). If the source image is a YUV image, then scaledWidth is the width of the YUV image. Setting this parameter to 0 is the equivalent of setting it to scaledWidth * TJ.pixelSize(pixelFormat).
      desiredHeight - If the source image is a JPEG image, then this @@ -905,7 +870,7 @@ public void decompress(byte[] dstBuf, int flags) throws java.lang.Exception + decompress(byte[], int, int, int, int, int, int, int) instead.
      Throws:
      java.lang.Exception
      @@ -925,15 +890,15 @@ public void decompress(byte[] dstBuf,
      Decompress the JPEG source image associated with this decompressor instance and return a buffer containing the decompressed image.
      Parameters:
      desiredWidth - see - decompress(byte[], int, int, int, int, int, int, int) + decompress(byte[], int, int, int, int, int, int, int) for description
      pitch - see - decompress(byte[], int, int, int, int, int, int, int) + decompress(byte[], int, int, int, int, int, int, int) for description
      desiredHeight - see - decompress(byte[], int, int, int, int, int, int, int) + decompress(byte[], int, int, int, int, int, int, int) for description
      pixelFormat - pixel format of the decompressed image (one of TJ.PF_*)
      flags - the bitwise OR of one or more of TJ.FLAG_*
      -
      Returns:
      a buffer containing the decompressed image
      +
      Returns:
      a buffer containing the decompressed image.
      Throws:
      java.lang.Exception
      @@ -974,11 +939,54 @@ public void decompress(byte[] dstBuf, public void decompressToYUV(byte[] dstBuf, int flags) throws java.lang.Exception -
      Deprecated. Use decompressToYUV(YUVImage, int) instead.
      +
      Deprecated. Use decompressToYUV(YUVImage, int) instead.
      Throws:
      java.lang.Exception
    + + + +
      +
    • +

      decompressToYUV

      +
      public YUVImage decompressToYUV(int desiredWidth,
      +                       int[] strides,
      +                       int desiredHeight,
      +                       int flags)
      +                         throws java.lang.Exception
      +
      Decompress the JPEG source image associated with this decompressor + instance into a set of Y, U (Cb), and V (Cr) image planes and return a + YUVImage instance containing the decompressed image planes. + This method performs JPEG decompression but leaves out the color + conversion step, so a planar YUV image is generated instead of an RGB or + grayscale image. This method cannot be used to decompress JPEG source + images with the CMYK or YCCK colorspace.
      +
      Parameters:
      desiredWidth - desired width (in pixels) of the YUV image. If the + desired image dimensions are different than the dimensions of the JPEG + image being decompressed, then TurboJPEG will use scaling in the JPEG + decompressor to generate the largest possible image that will fit within + the desired dimensions. Setting this to 0 is the same as setting it to + the width of the JPEG image (in other words, the width will not be + considered when determining the scaled image size.)
      strides - an array of integers, each specifying the number of bytes + per line in the corresponding plane of the output image. Setting the + stride for any plane to 0 is the same as setting it to the scaled + component width of the plane. If strides is NULL, then the + strides for all planes will be set to their respective scaled component + widths. You can adjust the strides in order to add an arbitrary amount of + line padding to each plane.
      desiredHeight - desired height (in pixels) of the YUV image. If the + desired image dimensions are different than the dimensions of the JPEG + image being decompressed, then TurboJPEG will use scaling in the JPEG + decompressor to generate the largest possible image that will fit within + the desired dimensions. Setting this to 0 is the same as setting it to + the height of the JPEG image (in other words, the height will not be + considered when determining the scaled image size.)
      flags - the bitwise OR of one or more of + TJ.FLAG_*
      +
      Returns:
      a YUV planar image.
      +
      Throws:
      +
      java.lang.Exception
      +
    • +
    @@ -991,12 +999,12 @@ public void decompressToYUV(byte[] dstBuf, int flags) throws java.lang.Exception
    Decompress the JPEG source image associated with this decompressor - instance into a YUV planar image and return a YUVImage - instance containing the decompressed image. This method performs JPEG - decompression but leaves out the color conversion step, so a planar YUV - image is generated instead of an RGB or grayscale image. This method - cannot be used to decompress JPEG source images with the CMYK or YCCK - colorspace.
    + instance into a unified YUV planar image buffer and return a + YUVImage instance containing the decompressed image. This + method performs JPEG decompression but leaves out the color conversion + step, so a planar YUV image is generated instead of an RGB or grayscale + image. This method cannot be used to decompress JPEG source images with + the CMYK or YCCK colorspace.
    Parameters:
    desiredWidth - desired width (in pixels) of the YUV image. If the desired image dimensions are different than the dimensions of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG @@ -1013,7 +1021,7 @@ public void decompressToYUV(byte[] dstBuf, the height of the JPEG image (in other words, the height will not be considered when determining the scaled image size.)
    flags - the bitwise OR of one or more of TJ.FLAG_*
    -
    Returns:
    a YUV planar image
    +
    Returns:
    a YUV planar image.
    Throws:
    java.lang.Exception
    @@ -1027,7 +1035,7 @@ public void decompressToYUV(byte[] dstBuf,
    @Deprecated
     public byte[] decompressToYUV(int flags)
                            throws java.lang.Exception
    -
    Deprecated. Use decompressToYUV(int, int, int, int) instead.
    +
    Deprecated. Use decompressToYUV(int, int, int, int) instead.
    Throws:
    java.lang.Exception
    @@ -1055,7 +1063,7 @@ public byte[] decompressToYUV(int flags) stride * scaledHeight pixels in size, where scaledHeight can be determined by calling scalingFactor.getScaled(jpegHeight) - with one of the scaling factors returned from TJ.getScalingFactors() or by calling getScaledHeight(int, int). If the + with one of the scaling factors returned from TJ.getScalingFactors() or by calling getScaledHeight(int, int). If the source image is a YUV image, then this buffer should normally be stride * height pixels in size, where height is the height of the YUV image. However, the buffer may also be larger than @@ -1077,7 +1085,7 @@ public byte[] decompressToYUV(int flags) NOTE: if the source image is a JPEG image, then scaledWidth can be determined by calling scalingFactor.getScaled(jpegWidth) - or by calling getScaledWidth(int, int). If the source image is a + or by calling getScaledWidth(int, int). If the source image is a YUV image, then scaledWidth is the width of the YUV image. Setting this parameter to 0 is the equivalent of setting it to scaledWidth.
    desiredHeight - If the source image is a JPEG image, then this @@ -1134,15 +1142,15 @@ public byte[] decompressToYUV(int flags) with this decompressor instance and return a BufferedImage instance containing the decompressed/decoded image.
    Parameters:
    desiredWidth - see - decompress(byte[], int, int, int, int, int, int, int) for + decompress(byte[], int, int, int, int, int, int, int) for description
    desiredHeight - see - decompress(byte[], int, int, int, int, int, int, int) for + decompress(byte[], int, int, int, int, int, int, int) for description
    bufferedImageType - the image type of the BufferedImage instance that will be created (for instance, BufferedImage.TYPE_INT_RGB)
    flags - the bitwise OR of one or more of TJ.FLAG_*
    Returns:
    a BufferedImage instance containing the - decompressed/decoded image
    + decompressed/decoded image.
    Throws:
    java.lang.Exception
    diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJScalingFactor.html b/java/doc/org/libjpegturbo/turbojpeg/TJScalingFactor.html index 1b901477..c28c00c0 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/TJScalingFactor.html +++ b/java/doc/org/libjpegturbo/turbojpeg/TJScalingFactor.html @@ -113,7 +113,7 @@ extends java.lang.Object Constructor and Description -TJScalingFactor(int num, +TJScalingFactor(int num, int denom)  @@ -238,7 +238,7 @@ extends java.lang.Object
    Returns the scaled value of dimension. This function performs the integer equivalent of ceil(dimension * scalingFactor).
    -
    Returns:
    the scaled value of dimension
    +
    Returns:
    the scaled value of dimension.
@@ -251,7 +251,7 @@ extends java.lang.Object
Returns true or false, depending on whether this instance and other have the same numerator and denominator.
Returns:
true or false, depending on whether this instance and - other have the same numerator and denominator
+ other have the same numerator and denominator.
@@ -264,7 +264,7 @@ extends java.lang.Object
Returns true or false, depending on whether this instance is equal to 1/1.
Returns:
true or false, depending on whether this instance is equal to - 1/1
+ 1/1. diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJTransform.html b/java/doc/org/libjpegturbo/turbojpeg/TJTransform.html index b4bd5cc7..daabfb3f 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/TJTransform.html +++ b/java/doc/org/libjpegturbo/turbojpeg/TJTransform.html @@ -231,14 +231,14 @@ extends java.awt.Rectangle static int
OPT_NOOUTPUT -
This option will prevent TJTransformer.transform() from outputting a JPEG image for this +
This option will prevent TJTransformer.transform() from outputting a JPEG image for this particular transform.
static int OPT_PERFECT -
This option will cause TJTransformer.transform() to throw an exception if the transform is not +
This option will cause TJTransformer.transform() to throw an exception if the transform is not perfect.
@@ -289,7 +289,7 @@ extends java.awt.Rectangle -TJTransform(int x, +TJTransform(int x, int y, int w, int h, @@ -300,7 +300,7 @@ extends java.awt.Rectangle -TJTransform(java.awt.Rectangle r, +TJTransform(java.awt.Rectangle r, int op, int options, TJCustomFilter cf) @@ -486,7 +486,7 @@ extends java.awt.Rectangle
  • OPT_PERFECT

    public static final int OPT_PERFECT
    -
    This option will cause TJTransformer.transform() to throw an exception if the transform is not +
    This option will cause TJTransformer.transform() to throw an exception if the transform is not perfect. Lossless transforms operate on MCU blocks, whose size depends on the level of chrominance subsampling used. If the image's width or height is not evenly divisible by the MCU block size (see TJ.getMCUWidth(int) @@ -541,7 +541,7 @@ extends java.awt.Rectangle
  • OPT_NOOUTPUT

    public static final int OPT_NOOUTPUT
    -
    This option will prevent TJTransformer.transform() from outputting a JPEG image for this +
    This option will prevent TJTransformer.transform() from outputting a JPEG image for this particular transform. This can be used in conjunction with a custom filter to capture the transformed DCT coefficients without transcoding them.
    @@ -636,7 +636,7 @@ extends java.awt.Rectangle throws java.lang.Exception
    Create a new lossless transform instance with the given parameters.
    Parameters:
    r - a Rectangle instance that specifies the cropping - region. See TJTransform(int, int, int, int, int, int, TJCustomFilter) for more + region. See TJTransform(int, int, int, int, int, int, TJCustomFilter) for more detail.
    op - one of the transform operations (OP_*)
    options - the bitwise OR of one or more of the transform options (OPT_*)
    cf - an instance of an object that implements the TJCustomFilter interface, or null if no custom filter is needed
    Throws:
    diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJTransformer.html b/java/doc/org/libjpegturbo/turbojpeg/TJTransformer.html index 3be18ec6..333f3eb3 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/TJTransformer.html +++ b/java/doc/org/libjpegturbo/turbojpeg/TJTransformer.html @@ -117,7 +117,7 @@ extends

    Fields inherited from class org.libjpegturbo.turbojpeg.TJDecompressor

    -handle, jpegBuf, jpegBufSize, srcColorspace, srcHeight, srcSubsamp, srcWidth, yuvImage
  • +handle, jpegBuf, jpegBufSize, jpegColorspace, jpegHeight, jpegSubsamp, jpegWidth, yuvImage @@ -144,7 +144,7 @@ extends -TJTransformer(byte[] jpegImage, +TJTransformer(byte[] jpegImage, int imageSize)
    Create a TurboJPEG lossless transformer instance and associate the JPEG image of length imageSize bytes stored in @@ -175,7 +175,7 @@ extends void -transform(byte[][] dstBufs, +transform(byte[][] dstBufs, TJTransform[] transforms, int flags)
    Losslessly transform the JPEG image associated with this transformer @@ -185,7 +185,7 @@ extends TJDecompressor[] -transform(TJTransform[] transforms, +transform(TJTransform[] transforms, int flags)
    Losslessly transform the JPEG image associated with this transformer instance and return an array of TJDecompressor instances, each of @@ -198,7 +198,7 @@ extends

    Methods inherited from class org.libjpegturbo.turbojpeg.TJDecompressor

    -close, decompress, decompress, decompress, decompress, decompress, decompress, decompressToYUV, decompressToYUV, decompressToYUV, decompressToYUV, finalize, getColorspace, getHeight, getJPEGBuf, getJPEGSize, getScaledHeight, getScaledWidth, getSourceBuf, getSourceSize, getSubsamp, getWidth, setJPEGImage, setSourceImage, setSourceImage +close, decompress, decompress, decompress, decompress, decompress, decompress, decompressToYUV, decompressToYUV, decompressToYUV, decompressToYUV, decompressToYUV, finalize, getColorspace, getHeight, getJPEGBuf, getJPEGSize, getScaledHeight, getScaledWidth, getSubsamp, getWidth, setJPEGImage, setSourceImage, setSourceImage
    Returns:
    an array containing the sizes of the transformed JPEG images - generated by the most recent transform operation
    + generated by the most recent transform operation.
    Throws:
    java.lang.Exception
    diff --git a/java/doc/org/libjpegturbo/turbojpeg/YUVImage.html b/java/doc/org/libjpegturbo/turbojpeg/YUVImage.html index 13e6160c..0a3e0a51 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/YUVImage.html +++ b/java/doc/org/libjpegturbo/turbojpeg/YUVImage.html @@ -94,7 +94,7 @@
    public class YUVImage
     extends java.lang.Object
    -
    This class encapsulates a YUV planar image buffer and the metadata +
    This class encapsulates a YUV planar image and the metadata associated with it. The TurboJPEG API allows both the JPEG compression and decompression pipelines to be split into stages: YUV encode, compress from YUV, decompress to YUV, and YUV decode. A YUVImage instance @@ -105,18 +105,26 @@ extends java.lang.Object Technically, the JPEG format uses the YCbCr colorspace (which technically is not a "colorspace" but rather a "color transform"), but per the convention of the digital video community, the TurboJPEG API uses "YUV" to refer to an - image format consisting of Y, Cb, and Cr image planes. In this image - format, the Y, Cb (U), and Cr (V) planes are stored sequentially in the same - image buffer, and the size of each plane is determined by the image width, - height, line padding, and level of chrominance subsampling. If the - chrominance components are subsampled along the horizontal dimension, then - the width of the luminance plane would be padded to the nearest multiple of - 2 (same goes for the height of the luminance plane, if the chrominance - components are subsampled along the vertical dimension.) For instance, if - the source image is 35 x 35 pixels and 4:2:2 subsampling is used, then the - luminance plane would be 36 x 35 bytes, and each of the chrominance planes - would be 18 x 35 bytes. If you specify, for instance, a line padding of 4 - bytes on top of this, then the luminance plane would be 36 x 35 bytes, and + image format consisting of Y, Cb, and Cr image planes. +

    + Each plane is simply a 2D array of bytes, each byte representing the value + of one of the components (Y, Cb, or Cr) at a particular location in the + image. The width and height of each plane are determined by the image + width, height, and level of chrominance subsampling. The luminance plane + width is the image width padded to the nearest multiple of the horizontal + subsampling factor (2 in the case of 4:2:0 and 4:2:2, 4 in the case of + 4:1:1, 1 in the case of 4:4:4 or grayscale.) Similarly, the luminance plane + height is the image height padded to the nearest multiple of the vertical + subsampling factor (2 in the case of 4:2:0 or 4:4:0, 1 in the case of 4:4:4 + or grayscale.) The chrominance plane width is equal to the luminance plane + width divided by the horizontal subsampling factor, and the chrominance + plane height is equal to the luminance plane height divided by the vertical + subsampling factor. +

    + For example, if the source image is 35 x 35 pixels and 4:2:2 subsampling is + used, then the luminance plane would be 36 x 35 bytes, and each of the + chrominance planes would be 18 x 35 bytes. If you specify a line padding of + 4 bytes on top of this, then the luminance plane would be 36 x 35 bytes, and each of the chrominance planes would be 20 x 35 bytes.

    @@ -141,18 +149,26 @@ extends java.lang.Object
    handle  -protected byte[] -yuvBuf  - - protected int yuvHeight  + +protected int[] +yuvOffsets  + protected int yuvPad  +protected byte[][] +yuvPlanes  + + +protected int[] +yuvStrides  + + protected int yuvSubsamp  @@ -175,21 +191,42 @@ extends java.lang.Object Constructor and Description -YUVImage(byte[] yuvImage, +YUVImage(byte[][] planes, + int[] offsets, + int width, + int[] strides, + int height, + int subsamp) +
    Create a new YUVImage instance from a set of existing image + planes.
    + + + +YUVImage(byte[] yuvImage, int width, int pad, int height, int subsamp) -
    Create a YUVImage instance from an existing YUV planar image +
    Create a new YUVImage instance from an existing unified image buffer.
    + +YUVImage(int width, + int[] strides, + int height, + int subsamp) +
    Create a new YUVImage instance backed by separate image + planes, and allocate memory for the image planes.
    + + -YUVImage(int width, +YUVImage(int width, int pad, int height, int subsamp) -
    Create a YUVImage instance with a new image buffer.
    +
    Create a new YUVImage instance backed by a unified image + buffer, and allocate memory for the image buffer.
    @@ -210,48 +247,80 @@ extends java.lang.Object byte[] getBuf() -
    Returns the YUV image buffer
    +
    Returns the YUV image buffer (if this image is stored in a unified + buffer rather than separate image planes.)
    int getHeight() -
    Returns the height of the YUV image.
    +
    Returns the height of the YUV image (or subregion.)
    +int[] +getOffsets() +
    Returns the offsets (in bytes) of each plane within the planes of a larger + YUV image.
    + + + int getPad() -
    Returns the line padding used in the YUV image buffer.
    +
    Returns the line padding used in the YUV image buffer (if this image is + stored in a unified buffer rather than separate image planes.)
    + + + +byte[][] +getPlanes() +
    Returns the YUV image planes.
    int getSize() -
    Returns the size (in bytes) of the YUV image buffer
    +
    Returns the size (in bytes) of the YUV image buffer (if this image is + stored in a unified buffer rather than separate image planes.)
    +int[] +getStrides() +
    Returns the number of bytes per line of each plane in the YUV image.
    + + + int getSubsamp()
    Returns the level of chrominance subsampling used in the YUV image.
    - + int getWidth() -
    Returns the width of the YUV image.
    +
    Returns the width of the YUV image (or subregion.)
    + + + +void +setBuf(byte[][] planes, + int[] offsets, + int width, + int[] strides, + int height, + int subsamp) +
    Assign a set of image planes to this YUVImage instance.
    void -setBuf(byte[] yuvImage, +setBuf(byte[] yuvImage, int width, int pad, int height, int subsamp) -
    Assign an existing YUV planar image buffer to this YUVImage - instance.
    +
    Assign a unified image buffer to this YUVImage instance.
    @@ -285,13 +354,31 @@ extends java.lang.Object
    protected long handle
    - +
    • -

      yuvBuf

      -
      protected byte[] yuvBuf
      +

      yuvPlanes

      +
      protected byte[][] yuvPlanes
      +
    • +
    + + + +
      +
    • +

      yuvOffsets

      +
      protected int[] yuvOffsets
      +
    • +
    + + + +
      +
    • +

      yuvStrides

      +
      protected int[] yuvStrides
    @@ -338,6 +425,31 @@ extends java.lang.Object

    Constructor Detail

    + + + +
      +
    • +

      YUVImage

      +
      public YUVImage(int width,
      +        int[] strides,
      +        int height,
      +        int subsamp)
      +         throws java.lang.Exception
      +
      Create a new YUVImage instance backed by separate image + planes, and allocate memory for the image planes.
      +
      Parameters:
      width - width (in pixels) of the YUV image
      strides - an array of integers, each specifying the number of bytes + per line in the corresponding plane of the YUV image. Setting the stride + for any plane to 0 is the same as setting it to the plane width (see + above.) If strides is null, then the + strides for all planes will be set to their respective plane widths. When + using this constructor, the stride for each plane must be equal to or + greater than the plane width.
      height - height (in pixels) of the YUV image
      subsamp - the level of chrominance subsampling to be used in the YUV + image (one of TJ.SAMP_*)
      +
      Throws:
      +
      java.lang.Exception
      +
    • +
    @@ -349,7 +461,8 @@ extends java.lang.Object int height, int subsamp) throws java.lang.Exception -
    Create a YUVImage instance with a new image buffer.
    +
    Create a new YUVImage instance backed by a unified image + buffer, and allocate memory for the image buffer.
    Parameters:
    width - width (in pixels) of the YUV image
    pad - Each line of each plane in the YUV image buffer will be padded to this number of bytes (must be a power of 2.)
    height - height (in pixels) of the YUV image
    subsamp - the level of chrominance subsampling to be used in the YUV image (one of TJ.SAMP_*)
    @@ -357,6 +470,44 @@ extends java.lang.Object
    java.lang.Exception
    + + + +
      +
    • +

      YUVImage

      +
      public YUVImage(byte[][] planes,
      +        int[] offsets,
      +        int width,
      +        int[] strides,
      +        int height,
      +        int subsamp)
      +         throws java.lang.Exception
      +
      Create a new YUVImage instance from a set of existing image + planes.
      +
      Parameters:
      planes - an array of buffers representing the Y, U (Cb), and V (Cr) + image planes (or just the Y plane, if the image is grayscale.) These + planes can be contiguous or non-contiguous in memory. Plane + i should be at least offsets[i] + + TJ.planeSizeYUV(i, width, strides[i], height, subsamp) + bytes in size.
      offsets - If this YUVImage instance represents a + subregion of a larger image, then offsets[i] specifies the + offset (in bytes) of the subregion within plane i of the + larger image. Setting this to null is the same as setting the offsets for + all planes to 0.
      width - width (in pixels) of the new YUV image (or subregion)
      strides - an array of integers, each specifying the number of bytes + per line in the corresponding plane of the YUV image. Setting the stride + for any plane to 0 is the same as setting it to the plane width (see + above.) If strides is null, then the + strides for all planes will be set to their respective plane widths. You + can adjust the strides in order to add an arbitrary amount of line padding + to each plane or to specify that this YUVImage instance is a + subregion of a larger image (in which case, strides[i] should + be set to the plane width of plane i in the larger image.)
      height - height (in pixels) of the new YUV image (or subregion)
      subsamp - the level of chrominance subsampling used in the YUV + image (one of TJ.SAMP_*)
      +
      Throws:
      +
      java.lang.Exception
      +
    • +
    @@ -369,12 +520,13 @@ extends java.lang.Object int height, int subsamp) throws java.lang.Exception -
    Create a YUVImage instance from an existing YUV planar image +
    Create a new YUVImage instance from an existing unified image buffer.
    Parameters:
    yuvImage - image buffer that contains or will contain YUV planar - image data. See above for a description of the image - format. Use TJ.bufSizeYUV(int, int, int, int) to determine the minimum size for this - buffer.
    width - width (in pixels) of the YUV image
    pad - the line padding used in the YUV image buffer. For + image data. Use TJ.bufSizeYUV(int, int, int, int) to determine the minimum size for + this buffer. The Y, U (Cb), and V (Cr) image planes are stored + sequentially in the buffer (see above for a description + of the image format.)
    width - width (in pixels) of the YUV image
    pad - the line padding used in the YUV image buffer. For instance, if each line in each plane of the buffer is padded to the nearest multiple of 4 bytes, then pad should be set to 4.
    height - height (in pixels) of the YUV image
    subsamp - the level of chrominance subsampling used in the YUV image (one of TJ.SAMP_*)
    @@ -390,6 +542,43 @@ extends java.lang.Object

    Method Detail

    + + + +
      +
    • +

      setBuf

      +
      public void setBuf(byte[][] planes,
      +          int[] offsets,
      +          int width,
      +          int[] strides,
      +          int height,
      +          int subsamp)
      +            throws java.lang.Exception
      +
      Assign a set of image planes to this YUVImage instance.
      +
      Parameters:
      planes - an array of buffers representing the Y, U (Cb), and V (Cr) + image planes (or just the Y plane, if the image is grayscale.) These + planes can be contiguous or non-contiguous in memory. Plane + i should be at least offsets[i] + + TJ.planeSizeYUV(i, width, strides[i], height, subsamp) + bytes in size.
      offsets - If this YUVImage instance represents a + subregion of a larger image, then offsets[i] specifies the + offset (in bytes) of the subregion within plane i of the + larger image. Setting this to null is the same as setting the offsets for + all planes to 0.
      width - width (in pixels) of the YUV image (or subregion)
      strides - an array of integers, each specifying the number of bytes + per line in the corresponding plane of the YUV image. Setting the stride + for any plane to 0 is the same as setting it to the plane width (see + above.) If strides is null, then the + strides for all planes will be set to their respective plane widths. You + can adjust the strides in order to add an arbitrary amount of line padding + to each plane or to specify that this YUVImage image is a + subregion of a larger image (in which case, strides[i] should + be set to the plane width of plane i in the larger image.)
      height - height (in pixels) of the YUV image (or subregion)
      subsamp - the level of chrominance subsampling used in the YUV + image (one of TJ.SAMP_*)
      +
      Throws:
      +
      java.lang.Exception
      +
    • +
    @@ -402,12 +591,12 @@ extends java.lang.Object int height, int subsamp) throws java.lang.Exception -
    Assign an existing YUV planar image buffer to this YUVImage - instance.
    +
    Assign a unified image buffer to this YUVImage instance.
    Parameters:
    yuvImage - image buffer that contains or will contain YUV planar - image data. See above for a description of the image - format. Use TJ.bufSizeYUV(int, int, int, int) to determine the minimum size for this - buffer.
    width - width (in pixels) of the YUV image
    pad - the line padding used in the YUV image buffer. For + image data. Use TJ.bufSizeYUV(int, int, int, int) to determine the minimum size for + this buffer. The Y, U (Cb), and V (Cr) image planes are stored + sequentially in the buffer (see above for a description + of the image format.)
    width - width (in pixels) of the YUV image
    pad - the line padding used in the YUV image buffer. For instance, if each line in each plane of the buffer is padded to the nearest multiple of 4 bytes, then pad should be set to 4.
    height - height (in pixels) of the YUV image
    subsamp - the level of chrominance subsampling used in the YUV image (one of TJ.SAMP_*)
    @@ -423,8 +612,8 @@ extends java.lang.Object

    getWidth

    public int getWidth()
                  throws java.lang.Exception
    -
    Returns the width of the YUV image.
    -
    Returns:
    the width of the YUV image
    +
    Returns the width of the YUV image (or subregion.)
    +
    Returns:
    the width of the YUV image (or subregion)
    Throws:
    java.lang.Exception
    @@ -437,8 +626,8 @@ extends java.lang.Object

    getHeight

    public int getHeight()
                   throws java.lang.Exception
    -
    Returns the height of the YUV image.
    -
    Returns:
    the height of the YUV image
    +
    Returns the height of the YUV image (or subregion.)
    +
    Returns:
    the height of the YUV image (or subregion)
    Throws:
    java.lang.Exception
    @@ -451,12 +640,43 @@ extends java.lang.Object

    getPad

    public int getPad()
                throws java.lang.Exception
    -
    Returns the line padding used in the YUV image buffer.
    +
    Returns the line padding used in the YUV image buffer (if this image is + stored in a unified buffer rather than separate image planes.)
    Returns:
    the line padding used in the YUV image buffer
    Throws:
    java.lang.Exception
    + + + +
      +
    • +

      getStrides

      +
      public int[] getStrides()
      +                 throws java.lang.Exception
      +
      Returns the number of bytes per line of each plane in the YUV image.
      +
      Returns:
      the number of bytes per line of each plane in the YUV image
      +
      Throws:
      +
      java.lang.Exception
      +
    • +
    + + + +
      +
    • +

      getOffsets

      +
      public int[] getOffsets()
      +                 throws java.lang.Exception
      +
      Returns the offsets (in bytes) of each plane within the planes of a larger + YUV image.
      +
      Returns:
      the offsets (in bytes) of each plane within the planes of a larger + YUV image
      +
      Throws:
      +
      java.lang.Exception
      +
    • +
    @@ -472,6 +692,21 @@ extends java.lang.Object
    java.lang.Exception
    + + + +
      +
    • +

      getPlanes

      +
      public byte[][] getPlanes()
      +                   throws java.lang.Exception
      +
      Returns the YUV image planes. If the image is stored in a unified buffer, + then all image planes will point to that buffer.
      +
      Returns:
      the YUV image planes
      +
      Throws:
      +
      java.lang.Exception
      +
    • +
    @@ -480,7 +715,8 @@ extends java.lang.Object

    getBuf

    public byte[] getBuf()
                   throws java.lang.Exception
    -
    Returns the YUV image buffer
    +
    Returns the YUV image buffer (if this image is stored in a unified + buffer rather than separate image planes.)
    Returns:
    the YUV image buffer
    Throws:
    java.lang.Exception
    @@ -494,7 +730,8 @@ extends java.lang.Object

    getSize

    public int getSize()
                 throws java.lang.Exception
    -
    Returns the size (in bytes) of the YUV image buffer
    +
    Returns the size (in bytes) of the YUV image buffer (if this image is + stored in a unified buffer rather than separate image planes.)
    Returns:
    the size (in bytes) of the YUV image buffer
    Throws:
    java.lang.Exception
    diff --git a/java/doc/org/libjpegturbo/turbojpeg/package-summary.html b/java/doc/org/libjpegturbo/turbojpeg/package-summary.html index c5e2f7d8..ea360576 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/package-summary.html +++ b/java/doc/org/libjpegturbo/turbojpeg/package-summary.html @@ -127,7 +127,7 @@ YUVImage -
    This class encapsulates a YUV planar image buffer and the metadata +
    This class encapsulates a YUV planar image and the metadata associated with it.
    diff --git a/java/org/libjpegturbo/turbojpeg/TJ.java b/java/org/libjpegturbo/turbojpeg/TJ.java index ac4a4dd1..644a1978 100644 --- a/java/org/libjpegturbo/turbojpeg/TJ.java +++ b/java/org/libjpegturbo/turbojpeg/TJ.java @@ -84,7 +84,8 @@ public final class TJ { * @param subsamp the level of chrominance subsampling (one of * SAMP_*) * - * @return the MCU block width for the given level of chrominance subsampling + * @return the MCU block width for the given level of chrominance + * subsampling. */ public static int getMCUWidth(int subsamp) throws Exception { if (subsamp < 0 || subsamp >= NUMSAMP) @@ -105,7 +106,7 @@ public final class TJ { * SAMP_*) * * @return the MCU block height for the given level of chrominance - * subsampling + * subsampling. */ public static int getMCUHeight(int subsamp) throws Exception { if (subsamp < 0 || subsamp >= NUMSAMP) @@ -214,7 +215,7 @@ public final class TJ { * * @param pixelFormat the pixel format (one of PF_*) * - * @return the pixel size (in bytes) for the given pixel format + * @return the pixel size (in bytes) for the given pixel format. */ public static int getPixelSize(int pixelFormat) throws Exception { if (pixelFormat < 0 || pixelFormat >= NUMPF) @@ -236,7 +237,7 @@ public final class TJ { * * @param pixelFormat the pixel format (one of PF_*) * - * @return the red offset for the given pixel format + * @return the red offset for the given pixel format. */ public static int getRedOffset(int pixelFormat) throws Exception { if (pixelFormat < 0 || pixelFormat >= NUMPF) @@ -258,7 +259,7 @@ public final class TJ { * * @param pixelFormat the pixel format (one of PF_*) * - * @return the green offset for the given pixel format + * @return the green offset for the given pixel format. */ public static int getGreenOffset(int pixelFormat) throws Exception { if (pixelFormat < 0 || pixelFormat >= NUMPF) @@ -280,7 +281,7 @@ public final class TJ { * * @param pixelFormat the pixel format (one of PF_*) * - * @return the blue offset for the given pixel format + * @return the blue offset for the given pixel format. */ public static int getBlueOffset(int pixelFormat) throws Exception { if (pixelFormat < 0 || pixelFormat >= NUMPF) @@ -404,7 +405,7 @@ public final class TJ { * generating the JPEG image (one of {@link TJ TJ.SAMP_*}) * * @return the maximum size of the buffer (in bytes) required to hold a JPEG - * image with the given width, height, and level of chrominance subsampling + * image with the given width, height, and level of chrominance subsampling. */ public static native int bufSize(int width, int height, int jpegSubsamp) throws Exception; @@ -416,8 +417,7 @@ public final class TJ { * @param width the width (in pixels) of the YUV image * * @param pad the width of each line in each plane of the image is padded to - * the nearest multiple of this number of bytes (must be a power of - * 2.) + * the nearest multiple of this number of bytes (must be a power of 2.) * * @param height the height (in pixels) of the YUV image * @@ -425,7 +425,7 @@ public final class TJ { * image (one of {@link TJ TJ.SAMP_*}) * * @return the size of the buffer (in bytes) required to hold a YUV planar - * image with the given width, height, and level of chrominance subsampling + * image with the given width, height, and level of chrominance subsampling. */ public static native int bufSizeYUV(int width, int pad, int height, int subsamp) @@ -438,12 +438,72 @@ public final class TJ { public static native int bufSizeYUV(int width, int height, int subsamp) throws Exception; + /** + * Returns the size of the buffer (in bytes) required to hold a YUV image + * plane with the given parameters. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, + * 2 = V/Cr) + * + * @param width width (in pixels) of the YUV image. NOTE: this is the width + * of the whole image, not the plane width. + * + * @param stride bytes per line in the image plane. + * + * @param height height (in pixels) of the YUV image. NOTE: this is the + * height of the whole image, not the plane height. + * + * @param subsamp the level of chrominance subsampling used in the YUV + * image (one of {@link TJ TJ.SAMP_*}) + * + * @return the size of the buffer (in bytes) required to hold a YUV planar + * image with the given parameters. + */ + public static native int planeSizeYUV(int componentID, int width, int stride, + int height, int subsamp) + throws Exception; + + /** + * Returns the plane width of a YUV image plane with the given parameters. + * Refer to {@link YUVImage YUVImage} for a description of plane width. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, + * 2 = V/Cr) + * + * @param width width (in pixels) of the YUV image + * + * @param subsamp the level of chrominance subsampling used in the YUV image + * (one of {@link TJ TJ.SAMP_*}) + * + * @return the plane width of a YUV image plane with the given parameters. + */ + public static native int planeWidth(int componentID, int width, int subsamp) + throws Exception; + + /** + * Returns the plane height of a YUV image plane with the given parameters. + * Refer to {@link YUVImage YUVImage} for a description of plane height. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, + * 2 = V/Cr) + * + * @param height height (in pixels) of the YUV image + * + * @param subsamp the level of chrominance subsampling used in the YUV image + * (one of {@link TJ TJ.SAMP_*}) + * + * @return the plane height of a YUV image plane with the given parameters. + */ + public static native int planeHeight(int componentID, int height, + int subsamp) + throws Exception; + /** * Returns a list of fractional scaling factors that the JPEG decompressor in * this implementation of TurboJPEG supports. * * @return a list of fractional scaling factors that the JPEG decompressor in - * this implementation of TurboJPEG supports + * this implementation of TurboJPEG supports. */ public static native TJScalingFactor[] getScalingFactors() throws Exception; diff --git a/java/org/libjpegturbo/turbojpeg/TJCompressor.java b/java/org/libjpegturbo/turbojpeg/TJCompressor.java index 0debf53e..c4a8cc58 100644 --- a/java/org/libjpegturbo/turbojpeg/TJCompressor.java +++ b/java/org/libjpegturbo/turbojpeg/TJCompressor.java @@ -332,9 +332,10 @@ public class TJCompressor { throw new Exception("Subsampling level not set"); if (srcYUVImage != null) - compressedSize = compressFromYUV(srcYUVImage.getBuf(), + compressedSize = compressFromYUV(srcYUVImage.getPlanes(), + srcYUVImage.getOffsets(), srcYUVImage.getWidth(), - srcYUVImage.getPad(), + srcYUVImage.getStrides(), srcYUVImage.getHeight(), srcYUVImage.getSubsamp(), dstBuf, jpegQuality, flags); @@ -429,14 +430,14 @@ public class TJCompressor { if (srcBufInt != null) { encodeYUV(srcBufInt, srcX, srcY, srcWidth, srcStride, srcHeight, - srcPixelFormat, dstImage.getBuf(), dstImage.getPad(), - dstImage.getSubsamp(), flags); + srcPixelFormat, dstImage.getPlanes(), dstImage.getOffsets(), + dstImage.getStrides(), dstImage.getSubsamp(), flags); } else { encodeYUV(srcBuf, srcX, srcY, srcWidth, srcPitch, srcHeight, - srcPixelFormat, dstImage.getBuf(), dstImage.getPad(), - dstImage.getSubsamp(), flags); + srcPixelFormat, dstImage.getPlanes(), dstImage.getOffsets(), + dstImage.getStrides(), dstImage.getSubsamp(), flags); } - compressedSize = dstImage.getSize(); + compressedSize = 0; } /** @@ -456,11 +457,11 @@ public class TJCompressor { /** * Encode the uncompressed source image associated with this compressor - * instance into a YUV planar image and return a YUVImage - * instance containing the encoded image. This method uses the accelerated - * color conversion routines in TurboJPEG's underlying codec but does not - * execute any of the other steps in the JPEG compression process. Encoding - * CMYK source images to YUV is not supported. + * instance into a unified YUV planar image buffer and return a + * YUVImage instance containing the encoded image. This method + * uses the accelerated color conversion routines in TurboJPEG's underlying + * codec but does not execute any of the other steps in the JPEG compression + * process. Encoding CMYK source images to YUV is not supported. * * @param pad the width of each line in each plane of the YUV image will be * padded to the nearest multiple of this number of bytes (must be a power of @@ -469,7 +470,7 @@ public class TJCompressor { * @param flags the bitwise OR of one or more of * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*} * - * @return a YUV planar image + * @return a YUV planar image. */ public YUVImage encodeYUV(int pad, int flags) throws Exception { if (srcWidth < 1 || srcHeight < 1) @@ -483,6 +484,37 @@ public class TJCompressor { return yuvImage; } + /** + * Encode the uncompressed source image associated with this compressor + * instance into separate Y, U (Cb), and V (Cr) image planes and return a + * YUVImage instance containing the encoded image planes. This + * method uses the accelerated color conversion routines in TurboJPEG's + * underlying codec but does not execute any of the other steps in the JPEG + * compression process. Encoding CMYK source images to YUV is not supported. + * + * @param strides an array of integers, each specifying the number of bytes + * per line in the corresponding plane of the output image. Setting the + * stride for any plane to 0 is the same as setting it to the component width + * of the plane. If strides is null, then the strides for all + * planes will be set to their respective component widths. You can adjust + * the strides in order to add an arbitrary amount of line padding to each + * plane. + * + * @param flags the bitwise OR of one or more of + * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*} + * + * @return a YUV planar image. + */ + public YUVImage encodeYUV(int[] strides, int flags) throws Exception { + if (srcWidth < 1 || srcHeight < 1) + throw new Exception(NO_ASSOC_ERROR); + if (subsamp < 0) + throw new Exception("Subsampling level not set"); + YUVImage yuvImage = new YUVImage(srcWidth, strides, srcHeight, subsamp); + encodeYUV(yuvImage, flags); + return yuvImage; + } + /** * @deprecated Use {@link #encodeYUV(int, int)} instead. */ @@ -512,7 +544,7 @@ public class TJCompressor { /** * @deprecated Use * {@link #setSourceImage(BufferedImage, int, int, int, int)} and - * {@link #encodeYUV(int)} instead. + * {@link #encodeYUV(int, int)} instead. */ @Deprecated public byte[] encodeYUV(BufferedImage srcImage, int flags) throws Exception { @@ -522,10 +554,10 @@ public class TJCompressor { /** * Returns the size of the image (in bytes) generated by the most recent - * compress/encode operation. + * compress operation. * * @return the size of the image (in bytes) generated by the most recent - * compress/encode operation + * compress operation. */ public int getCompressedSize() { return compressedSize; @@ -568,8 +600,9 @@ public class TJCompressor { int stride, int height, int pixelFormat, byte[] dstBuf, int jpegSubsamp, int jpegQual, int flags) throws Exception; - private native int compressFromYUV(byte[] srcBuf, int width, int pad, - int height, int subsamp, byte[] dstBuf, int jpegQual, int flags) + private native int compressFromYUV(byte[][] srcPlanes, int[] srcOffsets, + int width, int[] srcStrides, int height, int subsamp, byte[] dstBuf, + int jpegQual, int flags) throws Exception; private native void encodeYUV(byte[] srcBuf, int width, int pitch, @@ -577,16 +610,18 @@ public class TJCompressor { throws Exception; // deprecated private native void encodeYUV(byte[] srcBuf, int x, int y, int width, - int pitch, int height, int pixelFormat, byte[] dstBuf, int pad, - int subsamp, int flags) throws Exception; + int pitch, int height, int pixelFormat, byte[][] dstPlanes, + int[] dstOffsets, int[] dstStrides, int subsamp, int flags) + throws Exception; private native void encodeYUV(int[] srcBuf, int width, int stride, int height, int pixelFormat, byte[] dstBuf, int subsamp, int flags) throws Exception; // deprecated private native void encodeYUV(int[] srcBuf, int x, int y, int width, - int pitch, int height, int pixelFormat, byte[] dstBuf, int pad, - int subsamp, int flags) throws Exception; + int srcStride, int height, int pixelFormat, byte[][] dstPlanes, + int[] dstOffsets, int[] dstStrides, int subsamp, int flags) + throws Exception; static { TJLoader.load(); diff --git a/java/org/libjpegturbo/turbojpeg/TJDecompressor.java b/java/org/libjpegturbo/turbojpeg/TJDecompressor.java index 83057212..1a2774c0 100644 --- a/java/org/libjpegturbo/turbojpeg/TJDecompressor.java +++ b/java/org/libjpegturbo/turbojpeg/TJDecompressor.java @@ -37,7 +37,7 @@ import java.nio.*; public class TJDecompressor { private static final String NO_ASSOC_ERROR = - "No source image is associated with this instance"; + "No JPEG image is associated with this instance"; /** * Create a TurboJPEG decompresssor instance. @@ -87,18 +87,18 @@ public class TJDecompressor { /** * Associate the JPEG image of length imageSize bytes stored in - * srcImage with this decompressor instance. This image will + * jpegImage with this decompressor instance. This image will * be used as the source image for subsequent decompress operations. * - * @param srcImage JPEG image buffer + * @param jpegImage JPEG image buffer * * @param imageSize size of the JPEG image (in bytes) */ - public void setSourceImage(byte[] srcImage, int imageSize) + public void setSourceImage(byte[] jpegImage, int imageSize) throws Exception { - if (srcImage == null || imageSize < 1) + if (jpegImage == null || imageSize < 1) throw new Exception("Invalid argument in setSourceImage()"); - jpegBuf = srcImage; + jpegBuf = jpegImage; jpegBufSize = imageSize; decompressHeader(jpegBuf, jpegBufSize); yuvImage = null; @@ -134,14 +134,14 @@ public class TJDecompressor { * decompressor instance. * * @return the width of the source image (JPEG or YUV) associated with this - * decompressor instance + * decompressor instance. */ public int getWidth() throws Exception { if (yuvImage != null) return yuvImage.getWidth(); - if (srcWidth < 1) + if (jpegWidth < 1) throw new Exception(NO_ASSOC_ERROR); - return srcWidth; + return jpegWidth; } /** @@ -149,14 +149,14 @@ public class TJDecompressor { * decompressor instance. * * @return the height of the source image (JPEG or YUV) associated with this - * decompressor instance + * decompressor instance. */ public int getHeight() throws Exception { if (yuvImage != null) return yuvImage.getHeight(); - if (srcHeight < 1) + if (jpegHeight < 1) throw new Exception(NO_ASSOC_ERROR); - return srcHeight; + return jpegHeight; } /** @@ -165,16 +165,16 @@ public class TJDecompressor { * {@link TJ#SAMP_444 TJ.SAMP_*}. * * @return the level of chrominance subsampling used in the source image - * (JPEG or YUV) associated with this decompressor instance + * (JPEG or YUV) associated with this decompressor instance. */ public int getSubsamp() throws Exception { if (yuvImage != null) return yuvImage.getSubsamp(); - if (srcSubsamp < 0) + if (jpegSubsamp < 0) throw new Exception(NO_ASSOC_ERROR); - if (srcSubsamp >= TJ.NUMSAMP) + if (jpegSubsamp >= TJ.NUMSAMP) throw new Exception("JPEG header information is invalid"); - return srcSubsamp; + return jpegSubsamp; } /** @@ -183,36 +183,23 @@ public class TJDecompressor { * source image is YUV, then this always returns {@link TJ#CS_YCbCr}. * * @return the colorspace used in the source image (JPEG or YUV) associated - * with this decompressor instance + * with this decompressor instance. */ public int getColorspace() throws Exception { if (yuvImage != null) return TJ.CS_YCbCr; - if (srcColorspace < 0) + if (jpegColorspace < 0) throw new Exception(NO_ASSOC_ERROR); - if (srcColorspace >= TJ.NUMCS) + if (jpegColorspace >= TJ.NUMCS) throw new Exception("JPEG header information is invalid"); - return srcColorspace; + return jpegColorspace; } /** - * Returns the source image buffer associated with this decompressor - * instance. + * Returns the JPEG image buffer associated with this decompressor instance. * - * @return the source image buffer associated with this decompressor instance + * @return the JPEG image buffer associated with this decompressor instance. */ - public byte[] getSourceBuf() throws Exception { - if (yuvImage != null) - return yuvImage.getBuf(); - if (jpegBuf == null) - throw new Exception(NO_ASSOC_ERROR); - return jpegBuf; - } - - /** - * @deprecated Use {@link #getSourceBuf} instead. - */ - @Deprecated public byte[] getJPEGBuf() throws Exception { if (jpegBuf == null) throw new Exception(NO_ASSOC_ERROR); @@ -220,24 +207,12 @@ public class TJDecompressor { } /** - * Returns the size of the source image (in bytes) associated with this + * Returns the size of the JPEG image (in bytes) associated with this * decompressor instance. * - * @return the size of the source image (in bytes) associated with this - * decompressor instance + * @return the size of the JPEG image (in bytes) associated with this + * decompressor instance. */ - public int getSourceSize() throws Exception { - if (yuvImage != null) - return yuvImage.getSize(); - if (jpegBufSize < 1) - throw new Exception(NO_ASSOC_ERROR); - return jpegBufSize; - } - - /** - * @deprecated Use {@link #getSourceSize} instead. - */ - @Deprecated public int getJPEGSize() throws Exception { if (jpegBufSize < 1) throw new Exception(NO_ASSOC_ERROR); @@ -261,23 +236,23 @@ public class TJDecompressor { * * @return the width of the largest scaled-down image that the TurboJPEG * decompressor can generate without exceeding the desired image width and - * height + * height. */ public int getScaledWidth(int desiredWidth, int desiredHeight) throws Exception { - if (srcWidth < 1 || srcHeight < 1) + if (jpegWidth < 1 || jpegHeight < 1) throw new Exception(NO_ASSOC_ERROR); if (desiredWidth < 0 || desiredHeight < 0) throw new Exception("Invalid argument in getScaledWidth()"); TJScalingFactor[] sf = TJ.getScalingFactors(); if (desiredWidth == 0) - desiredWidth = srcWidth; + desiredWidth = jpegWidth; if (desiredHeight == 0) - desiredHeight = srcHeight; - int scaledWidth = srcWidth, scaledHeight = srcHeight; + desiredHeight = jpegHeight; + int scaledWidth = jpegWidth, scaledHeight = jpegHeight; for (int i = 0; i < sf.length; i++) { - scaledWidth = sf[i].getScaled(srcWidth); - scaledHeight = sf[i].getScaled(srcHeight); + scaledWidth = sf[i].getScaled(jpegWidth); + scaledHeight = sf[i].getScaled(jpegHeight); if (scaledWidth <= desiredWidth && scaledHeight <= desiredHeight) break; } @@ -303,23 +278,23 @@ public class TJDecompressor { * * @return the height of the largest scaled-down image that the TurboJPEG * decompressor can generate without exceeding the desired image width and - * height + * height. */ public int getScaledHeight(int desiredWidth, int desiredHeight) throws Exception { - if (srcWidth < 1 || srcHeight < 1) + if (jpegWidth < 1 || jpegHeight < 1) throw new Exception(NO_ASSOC_ERROR); if (desiredWidth < 0 || desiredHeight < 0) throw new Exception("Invalid argument in getScaledHeight()"); TJScalingFactor[] sf = TJ.getScalingFactors(); if (desiredWidth == 0) - desiredWidth = srcWidth; + desiredWidth = jpegWidth; if (desiredHeight == 0) - desiredHeight = srcHeight; - int scaledWidth = srcWidth, scaledHeight = srcHeight; + desiredHeight = jpegHeight; + int scaledWidth = jpegWidth, scaledHeight = jpegHeight; for (int i = 0; i < sf.length; i++) { - scaledWidth = sf[i].getScaled(srcWidth); - scaledHeight = sf[i].getScaled(srcHeight); + scaledWidth = sf[i].getScaled(jpegWidth); + scaledHeight = sf[i].getScaled(jpegHeight); if (scaledWidth <= desiredWidth && scaledHeight <= desiredHeight) break; } @@ -402,9 +377,10 @@ public class TJDecompressor { pixelFormat < 0 || pixelFormat >= TJ.NUMPF || flags < 0) throw new Exception("Invalid argument in decompress()"); if (yuvImage != null) - decodeYUV(yuvImage.getBuf(), yuvImage.getPad(), yuvImage.getSubsamp(), - dstBuf, x, y, yuvImage.getWidth(), pitch, yuvImage.getHeight(), - pixelFormat, flags); + decodeYUV(yuvImage.getPlanes(), yuvImage.getOffsets(), + yuvImage.getStrides(), yuvImage.getSubsamp(), dstBuf, x, y, + yuvImage.getWidth(), pitch, yuvImage.getHeight(), pixelFormat, + flags); else { if (x > 0 || y > 0) decompress(jpegBuf, jpegBufSize, dstBuf, x, y, desiredWidth, pitch, @@ -449,7 +425,7 @@ public class TJDecompressor { * @param flags the bitwise OR of one or more of * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*} * - * @return a buffer containing the decompressed image + * @return a buffer containing the decompressed image. */ public byte[] decompress(int desiredWidth, int pitch, int desiredHeight, int pixelFormat, int flags) throws Exception { @@ -497,12 +473,12 @@ public class TJDecompressor { if (scaledWidth != dstImage.getWidth() || scaledHeight != dstImage.getHeight()) throw new Exception("YUVImage dimensions do not match one of the scaled image sizes that TurboJPEG is capable of generating."); - if (srcSubsamp != dstImage.getSubsamp()) + if (jpegSubsamp != dstImage.getSubsamp()) throw new Exception("YUVImage subsampling level does not match that of the JPEG image"); - decompressToYUV(jpegBuf, jpegBufSize, dstImage.getBuf(), - dstImage.getWidth(), dstImage.getPad(), - dstImage.getHeight(), flags); + decompressToYUV(jpegBuf, jpegBufSize, dstImage.getPlanes(), + dstImage.getOffsets(), dstImage.getWidth(), + dstImage.getStrides(), dstImage.getHeight(), flags); } /** @@ -510,19 +486,77 @@ public class TJDecompressor { */ @Deprecated public void decompressToYUV(byte[] dstBuf, int flags) throws Exception { - YUVImage dstImage = new YUVImage(dstBuf, srcWidth, 4, srcHeight, - srcSubsamp); + YUVImage dstImage = new YUVImage(dstBuf, jpegWidth, 4, jpegHeight, + jpegSubsamp); decompressToYUV(dstImage, flags); } /** * Decompress the JPEG source image associated with this decompressor - * instance into a YUV planar image and return a YUVImage - * instance containing the decompressed image. This method performs JPEG - * decompression but leaves out the color conversion step, so a planar YUV - * image is generated instead of an RGB or grayscale image. This method - * cannot be used to decompress JPEG source images with the CMYK or YCCK - * colorspace. + * instance into a set of Y, U (Cb), and V (Cr) image planes and return a + * YUVImage instance containing the decompressed image planes. + * This method performs JPEG decompression but leaves out the color + * conversion step, so a planar YUV image is generated instead of an RGB or + * grayscale image. This method cannot be used to decompress JPEG source + * images with the CMYK or YCCK colorspace. + * + * @param desiredWidth desired width (in pixels) of the YUV image. If the + * desired image dimensions are different than the dimensions of the JPEG + * image being decompressed, then TurboJPEG will use scaling in the JPEG + * decompressor to generate the largest possible image that will fit within + * the desired dimensions. Setting this to 0 is the same as setting it to + * the width of the JPEG image (in other words, the width will not be + * considered when determining the scaled image size.) + * + * @param strides an array of integers, each specifying the number of bytes + * per line in the corresponding plane of the output image. Setting the + * stride for any plane to 0 is the same as setting it to the scaled + * component width of the plane. If strides is NULL, then the + * strides for all planes will be set to their respective scaled component + * widths. You can adjust the strides in order to add an arbitrary amount of + * line padding to each plane. + * + * @param desiredHeight desired height (in pixels) of the YUV image. If the + * desired image dimensions are different than the dimensions of the JPEG + * image being decompressed, then TurboJPEG will use scaling in the JPEG + * decompressor to generate the largest possible image that will fit within + * the desired dimensions. Setting this to 0 is the same as setting it to + * the height of the JPEG image (in other words, the height will not be + * considered when determining the scaled image size.) + * + * @param flags the bitwise OR of one or more of + * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*} + * + * @return a YUV planar image. + */ + public YUVImage decompressToYUV(int desiredWidth, int[] strides, + int desiredHeight, + int flags) throws Exception { + if (flags < 0) + throw new Exception("Invalid argument in decompressToYUV()"); + if (jpegWidth < 1 || jpegHeight < 1 || jpegSubsamp < 0) + throw new Exception(NO_ASSOC_ERROR); + if (jpegSubsamp >= TJ.NUMSAMP) + throw new Exception("JPEG header information is invalid"); + if (yuvImage != null) + throw new Exception("Source image is the wrong type"); + + int scaledWidth = getScaledWidth(desiredWidth, desiredHeight); + int scaledHeight = getScaledHeight(desiredWidth, desiredHeight); + YUVImage yuvImage = new YUVImage(scaledWidth, null, scaledHeight, + jpegSubsamp); + decompressToYUV(yuvImage, flags); + return yuvImage; + } + + /** + * Decompress the JPEG source image associated with this decompressor + * instance into a unified YUV planar image buffer and return a + * YUVImage instance containing the decompressed image. This + * method performs JPEG decompression but leaves out the color conversion + * step, so a planar YUV image is generated instead of an RGB or grayscale + * image. This method cannot be used to decompress JPEG source images with + * the CMYK or YCCK colorspace. * * @param desiredWidth desired width (in pixels) of the YUV image. If the * desired image dimensions are different than the dimensions of the JPEG @@ -547,15 +581,15 @@ public class TJDecompressor { * @param flags the bitwise OR of one or more of * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*} * - * @return a YUV planar image + * @return a YUV planar image. */ public YUVImage decompressToYUV(int desiredWidth, int pad, int desiredHeight, int flags) throws Exception { if (flags < 0) throw new Exception("Invalid argument in decompressToYUV()"); - if (srcWidth < 1 || srcHeight < 1 || srcSubsamp < 0) + if (jpegWidth < 1 || jpegHeight < 1 || jpegSubsamp < 0) throw new Exception(NO_ASSOC_ERROR); - if (srcSubsamp >= TJ.NUMSAMP) + if (jpegSubsamp >= TJ.NUMSAMP) throw new Exception("JPEG header information is invalid"); if (yuvImage != null) throw new Exception("Source image is the wrong type"); @@ -563,7 +597,7 @@ public class TJDecompressor { int scaledWidth = getScaledWidth(desiredWidth, desiredHeight); int scaledHeight = getScaledHeight(desiredWidth, desiredHeight); YUVImage yuvImage = new YUVImage(scaledWidth, pad, scaledHeight, - srcSubsamp); + jpegSubsamp); decompressToYUV(yuvImage, flags); return yuvImage; } @@ -573,7 +607,7 @@ public class TJDecompressor { */ @Deprecated public byte[] decompressToYUV(int flags) throws Exception { - YUVImage dstImage = new YUVImage(srcWidth, 4, srcHeight, srcSubsamp); + YUVImage dstImage = new YUVImage(jpegWidth, 4, jpegHeight, jpegSubsamp); decompressToYUV(dstImage, flags); return dstImage.getBuf(); } @@ -650,9 +684,10 @@ public class TJDecompressor { pixelFormat < 0 || pixelFormat >= TJ.NUMPF || flags < 0) throw new Exception("Invalid argument in decompress()"); if (yuvImage != null) - decodeYUV(yuvImage.getBuf(), yuvImage.getPad(), yuvImage.getSubsamp(), - dstBuf, x, y, yuvImage.getWidth(), stride, - yuvImage.getHeight(), pixelFormat, flags); + decodeYUV(yuvImage.getPlanes(), yuvImage.getOffsets(), + yuvImage.getStrides(), yuvImage.getSubsamp(), dstBuf, x, y, + yuvImage.getWidth(), stride, yuvImage.getHeight(), pixelFormat, + flags); else decompress(jpegBuf, jpegBufSize, dstBuf, x, y, desiredWidth, stride, desiredHeight, pixelFormat, flags); @@ -734,8 +769,9 @@ public class TJDecompressor { DataBufferInt db = (DataBufferInt)wr.getDataBuffer(); int[] buf = db.getData(); if (yuvImage != null) - decodeYUV(yuvImage.getBuf(), yuvImage.getPad(), yuvImage.getSubsamp(), - buf, 0, 0, yuvImage.getWidth(), stride, yuvImage.getHeight(), + decodeYUV(yuvImage.getPlanes(), yuvImage.getOffsets(), + yuvImage.getStrides(), yuvImage.getSubsamp(), buf, 0, 0, + yuvImage.getWidth(), stride, yuvImage.getHeight(), pixelFormat, flags); else { if (jpegBuf == null) @@ -778,7 +814,7 @@ public class TJDecompressor { * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*} * * @return a BufferedImage instance containing the - * decompressed/decoded image + * decompressed/decoded image. */ public BufferedImage decompress(int desiredWidth, int desiredHeight, int bufferedImageType, int flags) @@ -836,16 +872,17 @@ public class TJDecompressor { private native void decompressToYUV(byte[] srcBuf, int size, byte[] dstBuf, int flags) throws Exception; // deprecated - private native void decompressToYUV(byte[] srcBuf, int size, byte[] dstBuf, - int desiredWidth, int pad, int desiredheight, int flags) throws Exception; + private native void decompressToYUV(byte[] srcBuf, int size, + byte[][] dstPlanes, int[] dstOffsets, int desiredWidth, int[] dstStrides, + int desiredheight, int flags) throws Exception; - private native void decodeYUV(byte[] srcBuf, int pad, int subsamp, - byte[] dstBuf, int x, int y, int width, int pitch, int height, - int pixelFormat, int flags) throws Exception; + private native void decodeYUV(byte[][] srcPlanes, int[] srcOffsets, + int[] srcStrides, int subsamp, byte[] dstBuf, int x, int y, int width, + int pitch, int height, int pixelFormat, int flags) throws Exception; - private native void decodeYUV(byte[] srcBuf, int pad, int subsamp, - int[] dstBuf, int x, int y, int width, int stride, int height, - int pixelFormat, int flags) throws Exception; + private native void decodeYUV(byte[][] srcPlanes, int[] srcOffsets, + int[] srcStrides, int subsamp, int[] dstBuf, int x, int y, int width, + int stride, int height, int pixelFormat, int flags) throws Exception; static { TJLoader.load(); @@ -855,9 +892,9 @@ public class TJDecompressor { protected byte[] jpegBuf = null; protected int jpegBufSize = 0; protected YUVImage yuvImage = null; - protected int srcWidth = 0; - protected int srcHeight = 0; - protected int srcSubsamp = -1; - protected int srcColorspace = -1; + protected int jpegWidth = 0; + protected int jpegHeight = 0; + protected int jpegSubsamp = -1; + protected int jpegColorspace = -1; private ByteOrder byteOrder = null; }; diff --git a/java/org/libjpegturbo/turbojpeg/TJScalingFactor.java b/java/org/libjpegturbo/turbojpeg/TJScalingFactor.java index 4e7363ff..e00fdf7d 100644 --- a/java/org/libjpegturbo/turbojpeg/TJScalingFactor.java +++ b/java/org/libjpegturbo/turbojpeg/TJScalingFactor.java @@ -42,6 +42,7 @@ public class TJScalingFactor { /** * Returns numerator + * * @return numerator */ public int getNum() { @@ -50,6 +51,7 @@ public class TJScalingFactor { /** * Returns denominator + * * @return denominator */ public int getDenom() { @@ -60,7 +62,8 @@ public class TJScalingFactor { * Returns the scaled value of dimension. This function * performs the integer equivalent of * ceil(dimension * scalingFactor). - * @return the scaled value of dimension + * + * @return the scaled value of dimension. */ public int getScaled(int dimension) { return (dimension * num + denom - 1) / denom; @@ -69,8 +72,9 @@ public class TJScalingFactor { /** * Returns true or false, depending on whether this instance and * other have the same numerator and denominator. + * * @return true or false, depending on whether this instance and - * other have the same numerator and denominator + * other have the same numerator and denominator. */ public boolean equals(TJScalingFactor other) { return (this.num == other.num && this.denom == other.denom); @@ -79,8 +83,9 @@ public class TJScalingFactor { /** * Returns true or false, depending on whether this instance is equal to * 1/1. + * * @return true or false, depending on whether this instance is equal to - * 1/1 + * 1/1. */ public boolean isOne() { return (num == 1 && denom == 1); diff --git a/java/org/libjpegturbo/turbojpeg/TJTransformer.java b/java/org/libjpegturbo/turbojpeg/TJTransformer.java index ee1f6071..cf773fae 100644 --- a/java/org/libjpegturbo/turbojpeg/TJTransformer.java +++ b/java/org/libjpegturbo/turbojpeg/TJTransformer.java @@ -111,7 +111,7 @@ public class TJTransformer extends TJDecompressor { * corresponding transformed output image * * @return an array of {@link TJDecompressor} instances, each of - * which has a transformed JPEG image associated with it + * which has a transformed JPEG image associated with it. * * @param flags the bitwise OR of one or more of * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*} @@ -119,15 +119,15 @@ public class TJTransformer extends TJDecompressor { public TJDecompressor[] transform(TJTransform[] transforms, int flags) throws Exception { byte[][] dstBufs = new byte[transforms.length][]; - if (srcWidth < 1 || srcHeight < 1) + if (jpegWidth < 1 || jpegHeight < 1) throw new Exception("JPEG buffer not initialized"); for (int i = 0; i < transforms.length; i++) { - int w = srcWidth, h = srcHeight; + int w = jpegWidth, h = jpegHeight; if ((transforms[i].options & TJTransform.OPT_CROP) != 0) { if (transforms[i].width != 0) w = transforms[i].width; if (transforms[i].height != 0) h = transforms[i].height; } - dstBufs[i] = new byte[TJ.bufSize(w, h, srcSubsamp)]; + dstBufs[i] = new byte[TJ.bufSize(w, h, jpegSubsamp)]; } TJDecompressor[] tjd = new TJDecompressor[transforms.length]; transform(dstBufs, transforms, flags); @@ -141,7 +141,7 @@ public class TJTransformer extends TJDecompressor { * generated by the most recent transform operation. * * @return an array containing the sizes of the transformed JPEG images - * generated by the most recent transform operation + * generated by the most recent transform operation. */ public int[] getTransformedSizes() throws Exception { if (transformedSizes == null) diff --git a/java/org/libjpegturbo/turbojpeg/YUVImage.java b/java/org/libjpegturbo/turbojpeg/YUVImage.java index 619b0c31..2d790e93 100644 --- a/java/org/libjpegturbo/turbojpeg/YUVImage.java +++ b/java/org/libjpegturbo/turbojpeg/YUVImage.java @@ -29,7 +29,7 @@ package org.libjpegturbo.turbojpeg; /** - * This class encapsulates a YUV planar image buffer and the metadata + * This class encapsulates a YUV planar image and the metadata * associated with it. The TurboJPEG API allows both the JPEG compression and * decompression pipelines to be split into stages: YUV encode, compress from * YUV, decompress to YUV, and YUV decode. A YUVImage instance @@ -40,27 +40,60 @@ package org.libjpegturbo.turbojpeg; * Technically, the JPEG format uses the YCbCr colorspace (which technically is * not a "colorspace" but rather a "color transform"), but per the convention * of the digital video community, the TurboJPEG API uses "YUV" to refer to an - * image format consisting of Y, Cb, and Cr image planes. In this image - * format, the Y, Cb (U), and Cr (V) planes are stored sequentially in the same - * image buffer, and the size of each plane is determined by the image width, - * height, line padding, and level of chrominance subsampling. If the - * chrominance components are subsampled along the horizontal dimension, then - * the width of the luminance plane would be padded to the nearest multiple of - * 2 (same goes for the height of the luminance plane, if the chrominance - * components are subsampled along the vertical dimension.) For instance, if - * the source image is 35 x 35 pixels and 4:2:2 subsampling is used, then the - * luminance plane would be 36 x 35 bytes, and each of the chrominance planes - * would be 18 x 35 bytes. If you specify, for instance, a line padding of 4 - * bytes on top of this, then the luminance plane would be 36 x 35 bytes, and + * image format consisting of Y, Cb, and Cr image planes. + *

    + * Each plane is simply a 2D array of bytes, each byte representing the value + * of one of the components (Y, Cb, or Cr) at a particular location in the + * image. The width and height of each plane are determined by the image + * width, height, and level of chrominance subsampling. The luminance plane + * width is the image width padded to the nearest multiple of the horizontal + * subsampling factor (2 in the case of 4:2:0 and 4:2:2, 4 in the case of + * 4:1:1, 1 in the case of 4:4:4 or grayscale.) Similarly, the luminance plane + * height is the image height padded to the nearest multiple of the vertical + * subsampling factor (2 in the case of 4:2:0 or 4:4:0, 1 in the case of 4:4:4 + * or grayscale.) The chrominance plane width is equal to the luminance plane + * width divided by the horizontal subsampling factor, and the chrominance + * plane height is equal to the luminance plane height divided by the vertical + * subsampling factor. + *

    + * For example, if the source image is 35 x 35 pixels and 4:2:2 subsampling is + * used, then the luminance plane would be 36 x 35 bytes, and each of the + * chrominance planes would be 18 x 35 bytes. If you specify a line padding of + * 4 bytes on top of this, then the luminance plane would be 36 x 35 bytes, and * each of the chrominance planes would be 20 x 35 bytes. */ public class YUVImage { private static final String NO_ASSOC_ERROR = - "No YUV buffer is associated with this instance"; + "No image data is associated with this instance"; /** - * Create a YUVImage instance with a new image buffer. + * Create a new YUVImage instance backed by separate image + * planes, and allocate memory for the image planes. + * + * @param width width (in pixels) of the YUV image + * + * @param strides an array of integers, each specifying the number of bytes + * per line in the corresponding plane of the YUV image. Setting the stride + * for any plane to 0 is the same as setting it to the plane width (see + * {@link YUVImage above}.) If strides is null, then the + * strides for all planes will be set to their respective plane widths. When + * using this constructor, the stride for each plane must be equal to or + * greater than the plane width. + * + * @param height height (in pixels) of the YUV image + * + * @param subsamp the level of chrominance subsampling to be used in the YUV + * image (one of {@link TJ#SAMP_444 TJ.SAMP_*}) + */ + public YUVImage(int width, int[] strides, int height, int subsamp) + throws Exception { + setBuf(null, null, width, strides, height, subsamp, true); + } + + /** + * Create a new YUVImage instance backed by a unified image + * buffer, and allocate memory for the image buffer. * * @param width width (in pixels) of the YUV image * @@ -73,19 +106,59 @@ public class YUVImage { * image (one of {@link TJ#SAMP_444 TJ.SAMP_*}) */ public YUVImage(int width, int pad, int height, int subsamp) - throws Exception { + throws Exception { setBuf(new byte[TJ.bufSizeYUV(width, pad, height, subsamp)], width, pad, height, subsamp); } /** - * Create a YUVImage instance from an existing YUV planar image + * Create a new YUVImage instance from a set of existing image + * planes. + * + * @param planes an array of buffers representing the Y, U (Cb), and V (Cr) + * image planes (or just the Y plane, if the image is grayscale.) These + * planes can be contiguous or non-contiguous in memory. Plane + * i should be at least offsets[i] + + * {@link TJ#planeSizeYUV TJ.planeSizeYUV}(i, width, strides[i], height, subsamp) + * bytes in size. + * + * @param offsets If this YUVImage instance represents a + * subregion of a larger image, then offsets[i] specifies the + * offset (in bytes) of the subregion within plane i of the + * larger image. Setting this to null is the same as setting the offsets for + * all planes to 0. + * + * @param width width (in pixels) of the new YUV image (or subregion) + * + * @param strides an array of integers, each specifying the number of bytes + * per line in the corresponding plane of the YUV image. Setting the stride + * for any plane to 0 is the same as setting it to the plane width (see + * {@link YUVImage above}.) If strides is null, then the + * strides for all planes will be set to their respective plane widths. You + * can adjust the strides in order to add an arbitrary amount of line padding + * to each plane or to specify that this YUVImage instance is a + * subregion of a larger image (in which case, strides[i] should + * be set to the plane width of plane i in the larger image.) + * + * @param height height (in pixels) of the new YUV image (or subregion) + * + * @param subsamp the level of chrominance subsampling used in the YUV + * image (one of {@link TJ#SAMP_444 TJ.SAMP_*}) + */ + public YUVImage(byte[][] planes, int[] offsets, int width, int[] strides, + int height, int subsamp) throws Exception { + setBuf(planes, offsets, width, strides, height, subsamp, false); + } + + /** + * Create a new YUVImage instance from an existing unified image * buffer. * * @param yuvImage image buffer that contains or will contain YUV planar - * image data. See {@link YUVImage above} for a description of the image - * format. Use {@link TJ#bufSizeYUV} to determine the minimum size for this - * buffer. + * image data. Use {@link TJ#bufSizeYUV} to determine the minimum size for + * this buffer. The Y, U (Cb), and V (Cr) image planes are stored + * sequentially in the buffer (see {@link YUVImage above} for a description + * of the image format.) * * @param width width (in pixels) of the YUV image * @@ -104,13 +177,95 @@ public class YUVImage { } /** - * Assign an existing YUV planar image buffer to this YUVImage - * instance. + * Assign a set of image planes to this YUVImage instance. + * + * @param planes an array of buffers representing the Y, U (Cb), and V (Cr) + * image planes (or just the Y plane, if the image is grayscale.) These + * planes can be contiguous or non-contiguous in memory. Plane + * i should be at least offsets[i] + + * {@link TJ#planeSizeYUV TJ.planeSizeYUV}(i, width, strides[i], height, subsamp) + * bytes in size. + * + * @param offsets If this YUVImage instance represents a + * subregion of a larger image, then offsets[i] specifies the + * offset (in bytes) of the subregion within plane i of the + * larger image. Setting this to null is the same as setting the offsets for + * all planes to 0. + * + * @param width width (in pixels) of the YUV image (or subregion) + * + * @param strides an array of integers, each specifying the number of bytes + * per line in the corresponding plane of the YUV image. Setting the stride + * for any plane to 0 is the same as setting it to the plane width (see + * {@link YUVImage above}.) If strides is null, then the + * strides for all planes will be set to their respective plane widths. You + * can adjust the strides in order to add an arbitrary amount of line padding + * to each plane or to specify that this YUVImage image is a + * subregion of a larger image (in which case, strides[i] should + * be set to the plane width of plane i in the larger image.) + * + * @param height height (in pixels) of the YUV image (or subregion) + * + * @param subsamp the level of chrominance subsampling used in the YUV + * image (one of {@link TJ#SAMP_444 TJ.SAMP_*}) + */ + public void setBuf(byte[][] planes, int[] offsets, int width, int strides[], + int height, int subsamp) throws Exception { + setBuf(planes, offsets, width, strides, height, subsamp, false); + } + + private void setBuf(byte[][] planes, int[] offsets, int width, int strides[], + int height, int subsamp, boolean alloc) throws Exception { + if ((planes == null && !alloc) || width < 1 || height < 1 || subsamp < 0 || + subsamp >= TJ.NUMSAMP) + throw new Exception("Invalid argument in YUVImage::setBuf()"); + + int nc = (subsamp == TJ.SAMP_GRAY ? 1 : 3); + if (planes.length != nc || (offsets != null && offsets.length != nc) || + (strides != null && strides.length != nc)) + throw new Exception("YUVImage::setBuf(): planes, offsets, or strides array is the wrong size"); + + if (offsets == null) + offsets = new int[nc]; + if (strides == null) + strides = new int[nc]; + + for (int i = 0; i < nc; i++) { + int pw = TJ.planeWidth(i, width, subsamp); + int ph = TJ.planeHeight(i, height, subsamp); + int planeSize = TJ.planeSizeYUV(i, width, strides[i], height, subsamp); + + if (strides[i] == 0) + strides[i] = pw; + if (alloc) { + if (strides[i] < pw) + throw new Exception("Stride must be >= plane width when allocating a new YUV image"); + planes[i] = new byte[strides[i] * ph]; + } + if (planes[i] == null || offsets[i] < 0) + throw new Exception("Invalid argument in YUVImage::setBuf()"); + if (strides[i] < 0 && offsets[i] - planeSize + pw < 0) + throw new Exception("Stride for plane " + i + " would cause memory to be accessed below plane boundary"); + if (planes[i].length < offsets[i] + planeSize) + throw new Exception("Image plane " + i + " is not large enough"); + } + + yuvPlanes = planes; + yuvOffsets = offsets; + yuvWidth = width; + yuvStrides = strides; + yuvHeight = height; + yuvSubsamp = subsamp; + } + + /** + * Assign a unified image buffer to this YUVImage instance. * * @param yuvImage image buffer that contains or will contain YUV planar - * image data. See {@link YUVImage above} for a description of the image - * format. Use {@link TJ#bufSizeYUV} to determine the minimum size for this - * buffer. + * image data. Use {@link TJ#bufSizeYUV} to determine the minimum size for + * this buffer. The Y, U (Cb), and V (Cr) image planes are stored + * sequentially in the buffer (see {@link YUVImage above} for a description + * of the image format.) * * @param width width (in pixels) of the YUV image * @@ -127,20 +282,34 @@ public class YUVImage { int subsamp) throws Exception { if (yuvImage == null || width < 1 || pad < 1 || ((pad & (pad - 1)) != 0) || height < 1 || subsamp < 0 || subsamp >= TJ.NUMSAMP) - throw new Exception("Invalid argument in YUVImage()"); + throw new Exception("Invalid argument in YUVImage::setBuf()"); if (yuvImage.length < TJ.bufSizeYUV(width, pad, height, subsamp)) throw new Exception("YUV image buffer is not large enough"); - yuvBuf = yuvImage; - yuvWidth = width; + + int nc = (subsamp == TJ.SAMP_GRAY ? 1 : 3); + byte[][] planes = new byte[nc][]; + int[] strides = new int[nc]; + int[] offsets = new int[nc]; + + planes[0] = yuvImage; + strides[0] = PAD(TJ.planeWidth(0, width, subsamp), pad); + if (subsamp != TJ.SAMP_GRAY) { + strides[1] = strides[2] = PAD(TJ.planeWidth(1, width, subsamp), pad); + planes[1] = planes[2] = yuvImage; + offsets[1] = offsets[0] + + strides[0] * TJ.planeHeight(0, height, subsamp); + offsets[2] = offsets[1] + + strides[1] * TJ.planeHeight(1, height, subsamp); + } + yuvPad = pad; - yuvHeight = height; - yuvSubsamp = subsamp; + setBuf(planes, offsets, width, strides, height, subsamp); } /** - * Returns the width of the YUV image. + * Returns the width of the YUV image (or subregion.) * - * @return the width of the YUV image + * @return the width of the YUV image (or subregion) */ public int getWidth() throws Exception { if (yuvWidth < 1) @@ -149,9 +318,9 @@ public class YUVImage { } /** - * Returns the height of the YUV image. + * Returns the height of the YUV image (or subregion.) * - * @return the height of the YUV image + * @return the height of the YUV image (or subregion) */ public int getHeight() throws Exception { if (yuvHeight < 1) @@ -160,16 +329,43 @@ public class YUVImage { } /** - * Returns the line padding used in the YUV image buffer. + * Returns the line padding used in the YUV image buffer (if this image is + * stored in a unified buffer rather than separate image planes.) * * @return the line padding used in the YUV image buffer */ public int getPad() throws Exception { - if (yuvPad < 1 || ((yuvPad & (yuvPad - 1)) != 0)) + if (yuvPlanes == null) throw new Exception(NO_ASSOC_ERROR); + if (yuvPad < 1 || ((yuvPad & (yuvPad - 1)) != 0)) + throw new Exception("Image is not stored in a unified buffer"); return yuvPad; } + /** + * Returns the number of bytes per line of each plane in the YUV image. + * + * @return the number of bytes per line of each plane in the YUV image + */ + public int[] getStrides() throws Exception { + if (yuvStrides == null) + throw new Exception(NO_ASSOC_ERROR); + return yuvStrides; + } + + /** + * Returns the offsets (in bytes) of each plane within the planes of a larger + * YUV image. + * + * @return the offsets (in bytes) of each plane within the planes of a larger + * YUV image + */ + public int[] getOffsets() throws Exception { + if (yuvOffsets == null) + throw new Exception(NO_ASSOC_ERROR); + return yuvOffsets; + } + /** * Returns the level of chrominance subsampling used in the YUV image. See * {@link TJ#SAMP_444 TJ.SAMP_*}. @@ -183,29 +379,61 @@ public class YUVImage { } /** - * Returns the YUV image buffer + * Returns the YUV image planes. If the image is stored in a unified buffer, + * then all image planes will point to that buffer. + * + * @return the YUV image planes + */ + public byte[][] getPlanes() throws Exception { + if (yuvPlanes == null) + throw new Exception(NO_ASSOC_ERROR); + return yuvPlanes; + } + + /** + * Returns the YUV image buffer (if this image is stored in a unified + * buffer rather than separate image planes.) * * @return the YUV image buffer */ public byte[] getBuf() throws Exception { - if (yuvBuf == null) + if (yuvPlanes == null || yuvSubsamp < 0 || yuvSubsamp >= TJ.NUMSAMP) throw new Exception(NO_ASSOC_ERROR); - return yuvBuf; + int nc = (yuvSubsamp == TJ.SAMP_GRAY ? 1 : 3); + for (int i = 1; i < nc; i++) { + if (yuvPlanes[i] != yuvPlanes[0]) + throw new Exception("Image is not stored in a unified buffer"); + } + return yuvPlanes[0]; } /** - * Returns the size (in bytes) of the YUV image buffer + * Returns the size (in bytes) of the YUV image buffer (if this image is + * stored in a unified buffer rather than separate image planes.) * * @return the size (in bytes) of the YUV image buffer */ - public int getSize() throws Exception { - if (yuvBuf == null) - throw new Exception(NO_ASSOC_ERROR); - return TJ.bufSizeYUV(yuvWidth, yuvPad, yuvHeight, yuvSubsamp); - } + public int getSize() throws Exception { + if (yuvPlanes == null || yuvSubsamp < 0 || yuvSubsamp >= TJ.NUMSAMP) + throw new Exception(NO_ASSOC_ERROR); + int nc = (yuvSubsamp == TJ.SAMP_GRAY ? 1 : 3); + if (yuvPad < 1) + throw new Exception("Image is not stored in a unified buffer"); + for (int i = 1; i < nc; i++) { + if (yuvPlanes[i] != yuvPlanes[0]) + throw new Exception("Image is not stored in a unified buffer"); + } + return TJ.bufSizeYUV(yuvWidth, yuvPad, yuvHeight, yuvSubsamp); + } + + private static final int PAD(int v, int p) { + return (v + p - 1) & (~(p - 1)); + } protected long handle = 0; - protected byte[] yuvBuf = null; + protected byte[][] yuvPlanes = null; + protected int[] yuvOffsets = null; + protected int[] yuvStrides = null; protected int yuvPad = 0; protected int yuvWidth = 0; protected int yuvHeight = 0; diff --git a/java/org_libjpegturbo_turbojpeg_TJ.h b/java/org_libjpegturbo_turbojpeg_TJ.h index b00a128a..84ee8711 100644 --- a/java/org_libjpegturbo_turbojpeg_TJ.h +++ b/java/org_libjpegturbo_turbojpeg_TJ.h @@ -91,6 +91,30 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__III (JNIEnv *, jclass, jint, jint, jint); +/* + * Class: org_libjpegturbo_turbojpeg_TJ + * Method: planeSizeYUV + * Signature: (IIIII)I + */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeSizeYUV__IIIII + (JNIEnv *, jclass, jint, jint, jint, jint, jint); + +/* + * Class: org_libjpegturbo_turbojpeg_TJ + * Method: planeWidth + * Signature: (III)I + */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeWidth__III + (JNIEnv *, jclass, jint, jint, jint); + +/* + * Class: org_libjpegturbo_turbojpeg_TJ + * Method: planeHeight + * Signature: (III)I + */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeHeight__III + (JNIEnv *, jclass, jint, jint, jint); + /* * Class: org_libjpegturbo_turbojpeg_TJ * Method: getScalingFactors diff --git a/java/org_libjpegturbo_turbojpeg_TJCompressor.h b/java/org_libjpegturbo_turbojpeg_TJCompressor.h index edb23b4d..e76bd0ef 100644 --- a/java/org_libjpegturbo_turbojpeg_TJCompressor.h +++ b/java/org_libjpegturbo_turbojpeg_TJCompressor.h @@ -58,10 +58,10 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3 /* * Class: org_libjpegturbo_turbojpeg_TJCompressor * Method: compressFromYUV - * Signature: ([BIIII[BII)I + * Signature: ([[B[II[III[BII)I */ -JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV___3BIIII_3BII - (JNIEnv *, jobject, jbyteArray, jint, jint, jint, jint, jbyteArray, jint, jint); +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV___3_3B_3II_3III_3BII + (JNIEnv *, jobject, jobjectArray, jintArray, jint, jintArray, jint, jint, jbyteArray, jint, jint); /* * Class: org_libjpegturbo_turbojpeg_TJCompressor @@ -74,10 +74,10 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___ /* * Class: org_libjpegturbo_turbojpeg_TJCompressor * Method: encodeYUV - * Signature: ([BIIIIII[BIII)V + * Signature: ([BIIIIII[[B[I[III)V */ -JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIIIII_3BIII - (JNIEnv *, jobject, jbyteArray, jint, jint, jint, jint, jint, jint, jbyteArray, jint, jint, jint); +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIIIII_3_3B_3I_3III + (JNIEnv *, jobject, jbyteArray, jint, jint, jint, jint, jint, jint, jobjectArray, jintArray, jintArray, jint, jint); /* * Class: org_libjpegturbo_turbojpeg_TJCompressor @@ -90,10 +90,10 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___ /* * Class: org_libjpegturbo_turbojpeg_TJCompressor * Method: encodeYUV - * Signature: ([IIIIIII[BIII)V + * Signature: ([IIIIIII[[B[I[III)V */ -JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIIIII_3BIII - (JNIEnv *, jobject, jintArray, jint, jint, jint, jint, jint, jint, jbyteArray, jint, jint, jint); +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIIIII_3_3B_3I_3III + (JNIEnv *, jobject, jintArray, jint, jint, jint, jint, jint, jint, jobjectArray, jintArray, jintArray, jint, jint); #ifdef __cplusplus } diff --git a/java/org_libjpegturbo_turbojpeg_TJDecompressor.h b/java/org_libjpegturbo_turbojpeg_TJDecompressor.h index 1d8205c5..2d58e735 100644 --- a/java/org_libjpegturbo_turbojpeg_TJDecompressor.h +++ b/java/org_libjpegturbo_turbojpeg_TJDecompressor.h @@ -74,26 +74,26 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress /* * Class: org_libjpegturbo_turbojpeg_TJDecompressor * Method: decompressToYUV - * Signature: ([BI[BIIII)V + * Signature: ([BI[[B[II[III)V */ -JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BIIII - (JNIEnv *, jobject, jbyteArray, jint, jbyteArray, jint, jint, jint, jint); +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3_3B_3II_3III + (JNIEnv *, jobject, jbyteArray, jint, jobjectArray, jintArray, jint, jintArray, jint, jint); /* * Class: org_libjpegturbo_turbojpeg_TJDecompressor * Method: decodeYUV - * Signature: ([BII[BIIIIIII)V + * Signature: ([[B[I[II[BIIIIIII)V */ -JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3BII_3BIIIIIII - (JNIEnv *, jobject, jbyteArray, jint, jint, jbyteArray, jint, jint, jint, jint, jint, jint, jint); +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3BIIIIIII + (JNIEnv *, jobject, jobjectArray, jintArray, jintArray, jint, jbyteArray, jint, jint, jint, jint, jint, jint, jint); /* * Class: org_libjpegturbo_turbojpeg_TJDecompressor * Method: decodeYUV - * Signature: ([BII[IIIIIIII)V + * Signature: ([[B[I[II[IIIIIIII)V */ -JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3BII_3IIIIIIII - (JNIEnv *, jobject, jbyteArray, jint, jint, jintArray, jint, jint, jint, jint, jint, jint, jint); +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3IIIIIIII + (JNIEnv *, jobject, jobjectArray, jintArray, jintArray, jint, jintArray, jint, jint, jint, jint, jint, jint, jint); #ifdef __cplusplus } diff --git a/jcdctmgr.c b/jcdctmgr.c index c259aea2..6cab5ab5 100644 --- a/jcdctmgr.c +++ b/jcdctmgr.c @@ -6,7 +6,7 @@ * libjpeg-turbo Modifications: * Copyright (C) 1999-2006, MIYASAKA Masaru. * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2011 D. R. Commander + * Copyright (C) 2011, 2014 D. R. Commander * mozjpeg Modifications: * Copyright (C) 2014, Mozilla Corporation. * For conditions of distribution and use, see the accompanying README file. @@ -20,7 +20,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ +#include "jdct.h" /* Private declarations for DCT subsystem */ #include "jsimddct.h" #include #include @@ -46,7 +46,7 @@ typedef void (*float_quantize_method_ptr) (JCOEFPTR coef_block, METHODDEF(void) quantize (JCOEFPTR, DCTELEM *, DCTELEM *); typedef struct { - struct jpeg_forward_dct pub; /* public fields */ + struct jpeg_forward_dct pub; /* public fields */ /* Pointer to the DCT routine actually in use */ forward_DCT_method_ptr dct; @@ -75,9 +75,12 @@ typedef struct { typedef my_fdct_controller * my_fdct_ptr; +#if BITS_IN_JSAMPLE == 8 + /* * Find the highest bit in an integer through binary search. */ + LOCAL(int) flss (UINT16 val) { @@ -108,6 +111,7 @@ flss (UINT16 val) return bit; } + /* * Compute values to do a division using reciprocal. * @@ -149,7 +153,7 @@ flss (UINT16 val) * * In order to allow SIMD implementations we also tweak the values to * allow the same calculation to be made at all times: - * + * * dctbl[0] = f rounded to nearest integer * dctbl[1] = divisor / 2 (+ 1 if fractional part of f < 0.5) * dctbl[2] = 1 << ((word size) * 2 - r) @@ -166,6 +170,7 @@ flss (UINT16 val) * of in a consecutive manner, yet again in order to allow SIMD * routines. */ + LOCAL(int) compute_reciprocal (UINT16 divisor, DCTELEM * dtbl) { @@ -200,6 +205,9 @@ compute_reciprocal (UINT16 divisor, DCTELEM * dtbl) else return 1; } +#endif + + /* * Initialize for a processing pass. * Verify that all referenced Q-tables are present, and set up @@ -223,7 +231,7 @@ start_pass_fdctmgr (j_compress_ptr cinfo) qtblno = compptr->quant_tbl_no; /* Make sure specified quantization table is present */ if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || - cinfo->quant_tbl_ptrs[qtblno] == NULL) + cinfo->quant_tbl_ptrs[qtblno] == NULL) ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); qtbl = cinfo->quant_tbl_ptrs[qtblno]; /* Compute divisors for this quant table */ @@ -235,91 +243,102 @@ start_pass_fdctmgr (j_compress_ptr cinfo) * coefficients multiplied by 8 (to counteract scaling). */ if (fdct->divisors[qtblno] == NULL) { - fdct->divisors[qtblno] = (DCTELEM *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (DCTSIZE2 * 4) * sizeof(DCTELEM)); } dtbl = fdct->divisors[qtblno]; for (i = 0; i < DCTSIZE2; i++) { - if(!compute_reciprocal(qtbl->quantval[i] << 3, &dtbl[i]) - && fdct->quantize == jsimd_quantize) - fdct->quantize = quantize; +#if BITS_IN_JSAMPLE == 8 + if(!compute_reciprocal(qtbl->quantval[i] << 3, &dtbl[i]) + && fdct->quantize == jsimd_quantize) + fdct->quantize = quantize; +#else + dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; +#endif } break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: { - /* For AA&N IDCT method, divisors are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * We apply a further scale factor of 8. - */ + /* For AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + */ #define CONST_BITS 14 - static const INT16 aanscales[DCTSIZE2] = { - /* precomputed values scaled up by 14 bits */ - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, - 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, - 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, - 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, - 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 - }; - SHIFT_TEMPS + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS - if (fdct->divisors[qtblno] == NULL) { - fdct->divisors[qtblno] = (DCTELEM *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (DCTSIZE2 * 4) * sizeof(DCTELEM)); - } - dtbl = fdct->divisors[qtblno]; - for (i = 0; i < DCTSIZE2; i++) { - if(!compute_reciprocal( - DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], - (INT32) aanscales[i]), - CONST_BITS-3), &dtbl[i]) - && fdct->quantize == jsimd_quantize) - fdct->quantize = quantize; - } + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { +#if BITS_IN_JSAMPLE == 8 + if(!compute_reciprocal( + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + CONST_BITS-3), &dtbl[i]) + && fdct->quantize == jsimd_quantize) + fdct->quantize = quantize; +#else + dtbl[i] = (DCTELEM) + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + CONST_BITS-3); +#endif + } } break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: { - /* For float AA&N IDCT method, divisors are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * We apply a further scale factor of 8. - * What's actually stored is 1/divisor so that the inner loop can - * use a multiplication rather than a division. - */ - FAST_FLOAT * fdtbl; - int row, col; - static const double aanscalefactor[DCTSIZE] = { - 1.0, 1.387039845, 1.306562965, 1.175875602, - 1.0, 0.785694958, 0.541196100, 0.275899379 - }; + /* For float AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + * What's actually stored is 1/divisor so that the inner loop can + * use a multiplication rather than a division. + */ + FAST_FLOAT * fdtbl; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; - if (fdct->float_divisors[qtblno] == NULL) { - fdct->float_divisors[qtblno] = (FAST_FLOAT *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + if (fdct->float_divisors[qtblno] == NULL) { + fdct->float_divisors[qtblno] = (FAST_FLOAT *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, DCTSIZE2 * sizeof(FAST_FLOAT)); - } - fdtbl = fdct->float_divisors[qtblno]; - i = 0; - for (row = 0; row < DCTSIZE; row++) { - for (col = 0; col < DCTSIZE; col++) { - fdtbl[i] = (FAST_FLOAT) - (1.0 / (((double) qtbl->quantval[i] * - aanscalefactor[row] * aanscalefactor[col] * 8.0))); - i++; - } - } + } + fdtbl = fdct->float_divisors[qtblno]; + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fdtbl[i] = (FAST_FLOAT) + (1.0 / (((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col] * 8.0))); + i++; + } + } } break; #endif @@ -346,7 +365,7 @@ convsamp (JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM * workspace) for (elemr = 0; elemr < DCTSIZE; elemr++) { elemptr = sample_data[elemr] + start_col; -#if DCTSIZE == 8 /* unroll the inner loop */ +#if DCTSIZE == 8 /* unroll the inner loop */ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; @@ -375,9 +394,12 @@ quantize (JCOEFPTR coef_block, DCTELEM * divisors, DCTELEM * workspace) { int i; DCTELEM temp; + JCOEFPTR output_ptr = coef_block; + +#if BITS_IN_JSAMPLE == 8 + UDCTELEM recip, corr, shift; UDCTELEM2 product; - JCOEFPTR output_ptr = coef_block; for (i = 0; i < DCTSIZE2; i++) { temp = workspace[i]; @@ -396,9 +418,47 @@ quantize (JCOEFPTR coef_block, DCTELEM * divisors, DCTELEM * workspace) product >>= shift + sizeof(DCTELEM)*8; temp = product; } - output_ptr[i] = (JCOEF) temp; } + +#else + + register DCTELEM qval; + + for (i = 0; i < DCTSIZE2; i++) { + qval = divisors[i]; + temp = workspace[i]; + /* Divide the coefficient value by qval, ensuring proper rounding. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * + * In most files, at least half of the output values will be zero + * (at default quantization settings, more like three-quarters...) + * so we should ensure that this case is fast. On many machines, + * a comparison is enough cheaper than a divide to make a special test + * a win. Since both inputs will be nonnegative, we need only test + * for a < b to discover whether a/b is 0. + * If your machine's division is fast enough, define FAST_DIVIDE. + */ +#ifdef FAST_DIVIDE +#define DIVIDE_BY(a,b) a /= b +#else +#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 +#endif + if (temp < 0) { + temp = -temp; + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + temp = -temp; + } else { + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + } + output_ptr[i] = (JCOEF) temp; + } + +#endif + } @@ -412,8 +472,8 @@ quantize (JCOEFPTR coef_block, DCTELEM * divisors, DCTELEM * workspace) METHODDEF(void) forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks, JBLOCKROW dst) /* This version is used for integer DCT implementations. */ { @@ -429,7 +489,7 @@ forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, quantize_method_ptr do_quantize = fdct->quantize; workspace = fdct->workspace; - sample_data += start_row; /* fold in the vertical offset once */ + sample_data += start_row; /* fold in the vertical offset once */ for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { /* Load data into workspace, applying unsigned->signed conversion */ @@ -487,7 +547,7 @@ convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT * works workspaceptr = workspace; for (elemr = 0; elemr < DCTSIZE; elemr++) { elemptr = sample_data[elemr] + start_col; -#if DCTSIZE == 8 /* unroll the inner loop */ +#if DCTSIZE == 8 /* unroll the inner loop */ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); @@ -532,8 +592,8 @@ quantize_float (JCOEFPTR coef_block, FAST_FLOAT * divisors, FAST_FLOAT * workspa METHODDEF(void) forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks, JBLOCKROW dst) /* This version is used for floating-point DCT implementations. */ { @@ -552,7 +612,7 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, float_quantize_method_ptr do_quantize = fdct->float_quantize; workspace = fdct->float_workspace; - sample_data += start_row; /* fold in the vertical offset once */ + sample_data += start_row; /* fold in the vertical offset once */ for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { /* Load data into workspace, applying unsigned->signed conversion */ diff --git a/jchuff.c b/jchuff.c index 5f6288aa..d8eb1d35 100644 --- a/jchuff.c +++ b/jchuff.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2009-2011, D. R. Commander. + * Copyright (C) 2009-2011, 2014 D. R. Commander. * For conditions of distribution and use, see the accompanying README file. * * This file contains Huffman entropy encoding routines. @@ -408,7 +408,7 @@ dump_buffer (working_state * state) #endif -#define BUFSIZE (DCTSIZE2 * 2) +#define BUFSIZE (DCTSIZE2 * 2) + 8 #define LOAD_BUFFER() { \ if (state->free_in_buffer < BUFSIZE) { \ diff --git a/jconfig.h.in b/jconfig.h.in index cdca01f3..42d86f24 100644 --- a/jconfig.h.in +++ b/jconfig.h.in @@ -12,6 +12,17 @@ /* Support arithmetic decoding */ #undef D_ARITH_CODING_SUPPORTED +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ + /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H diff --git a/jdatadst-tj.c b/jdatadst-tj.c index bc4a35dd..1f6f3a5e 100644 --- a/jdatadst-tj.c +++ b/jdatadst-tj.c @@ -5,7 +5,7 @@ * Copyright (C) 1994-1996, Thomas G. Lane. * Modified 2009-2012 by Guido Vollbeding. * libjpeg-turbo Modifications: - * Copyright (C) 2011, D. R. Commander. + * Copyright (C) 2011, 2014 D. R. Commander. * For conditions of distribution and use, see the accompanying README file. * * This file contains compression data destination routines for the case of @@ -150,6 +150,7 @@ jpeg_mem_dest_tj (j_compress_ptr cinfo, unsigned char ** outbuffer, unsigned long * outsize, boolean alloc) { + boolean reused = FALSE; my_mem_dest_ptr dest; if (outbuffer == NULL || outsize == NULL) /* sanity check */ @@ -164,12 +165,15 @@ jpeg_mem_dest_tj (j_compress_ptr cinfo, sizeof(my_mem_destination_mgr)); dest = (my_mem_dest_ptr) cinfo->dest; dest->newbuffer = NULL; + dest->buffer = NULL; } dest = (my_mem_dest_ptr) cinfo->dest; dest->pub.init_destination = init_mem_destination; dest->pub.empty_output_buffer = empty_mem_output_buffer; dest->pub.term_destination = term_mem_destination; + if (dest->buffer == *outbuffer && *outbuffer != NULL && alloc) + reused = TRUE; dest->outbuffer = outbuffer; dest->outsize = outsize; dest->alloc = alloc; @@ -186,5 +190,7 @@ jpeg_mem_dest_tj (j_compress_ptr cinfo, } dest->pub.next_output_byte = dest->buffer = *outbuffer; - dest->pub.free_in_buffer = dest->bufsize = *outsize; + if (!reused) + dest->bufsize = *outsize; + dest->pub.free_in_buffer = dest->bufsize; } diff --git a/jdcolor.c b/jdcolor.c index 6927e5ed..ffedabd5 100644 --- a/jdcolor.c +++ b/jdcolor.c @@ -6,7 +6,7 @@ * Modified 2011 by Guido Vollbeding. * libjpeg-turbo Modifications: * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009, 2011-2012, D. R. Commander. + * Copyright (C) 2009, 2011-2012, 2014, D. R. Commander. * Copyright (C) 2013, Linaro Limited. * For conditions of distribution and use, see the accompanying README file. * @@ -657,8 +657,12 @@ jinit_color_deconverter (j_decompress_ptr cinfo) cinfo->out_color_components = 3; if (cinfo->dither_mode == JDITHER_NONE) { if (cinfo->jpeg_color_space == JCS_YCbCr) { - cconvert->pub.color_convert = ycc_rgb565_convert; - build_ycc_rgb_table(cinfo); + if (jsimd_can_ycc_rgb565()) + cconvert->pub.color_convert = jsimd_ycc_rgb565_convert; + else { + cconvert->pub.color_convert = ycc_rgb565_convert; + build_ycc_rgb_table(cinfo); + } } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { cconvert->pub.color_convert = gray_rgb565_convert; } else if (cinfo->jpeg_color_space == JCS_RGB) { diff --git a/jdct.h b/jdct.h index c06bf9dc..6f8b1591 100644 --- a/jdct.h +++ b/jdct.h @@ -41,7 +41,6 @@ typedef unsigned int UDCTELEM2; #endif #else typedef INT32 DCTELEM; /* must have 32 bits */ -typedef UINT32 UDCTELEM; typedef unsigned long long UDCTELEM2; #endif diff --git a/jmorecfg.h b/jmorecfg.h index 91fbd15f..36fe9714 100644 --- a/jmorecfg.h +++ b/jmorecfg.h @@ -13,18 +13,6 @@ */ -/* - * Define BITS_IN_JSAMPLE as either - * 8 for 8-bit sample values (the usual setting) - * 12 for 12-bit sample values - * Only 8 and 12 are legal data precisions for lossy JPEG according to the - * JPEG standard, and the IJG code does not support anything else! - * We do not support run-time selection of data precision, sorry. - */ - -#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ - - /* * Maximum number of components (color channels) allowed in JPEG image. * To meet the letter of the JPEG spec, set this to 255. However, darn diff --git a/jsimd.h b/jsimd.h index d45fd700..f1f584b8 100644 --- a/jsimd.h +++ b/jsimd.h @@ -2,7 +2,7 @@ * jsimd.h * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright 2011 D. R. Commander + * Copyright 2011, 2014 D. R. Commander * * Based on the x86 SIMD extension for IJG JPEG library, * Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -13,6 +13,7 @@ EXTERN(int) jsimd_can_rgb_ycc (void); EXTERN(int) jsimd_can_rgb_gray (void); EXTERN(int) jsimd_can_ycc_rgb (void); +EXTERN(int) jsimd_can_ycc_rgb565 (void); EXTERN(int) jsimd_c_can_null_convert (void); EXTERN(void) jsimd_rgb_ycc_convert @@ -24,6 +25,9 @@ EXTERN(void) jsimd_rgb_gray_convert EXTERN(void) jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows); +EXTERN(void) jsimd_ycc_rgb565_convert + (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows); EXTERN(void) jsimd_c_null_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows); diff --git a/jsimd_none.c b/jsimd_none.c index 96a9842a..34aefc9f 100644 --- a/jsimd_none.c +++ b/jsimd_none.c @@ -2,7 +2,7 @@ * jsimd_none.c * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright 2009-2011 D. R. Commander + * Copyright 2009-2011, 2014 D. R. Commander * * Based on the x86 SIMD extension for IJG JPEG library, * Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -36,6 +36,12 @@ jsimd_can_ycc_rgb (void) return 0; } +GLOBAL(int) +jsimd_can_ycc_rgb565 (void) +{ + return 0; +} + GLOBAL(int) jsimd_c_can_null_convert (void) { @@ -63,6 +69,13 @@ jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, { } +GLOBAL(void) +jsimd_ycc_rgb565_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ +} + GLOBAL(void) jsimd_c_null_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, diff --git a/release/deb-control.tmpl b/release/deb-control.tmpl index 5c0cfd0b..50df76b2 100644 --- a/release/deb-control.tmpl +++ b/release/deb-control.tmpl @@ -6,6 +6,7 @@ Architecture: {__ARCH} Essential: no Maintainer: The libmozjpeg Project Homepage: https://github.com/mozilla/mozjpeg +Installed-Size: {__SIZE} Description: A SIMD-accelerated JPEG codec that provides both the libjpeg and TurboJPEG APIs libmozjpeg is a JPEG image codec that uses SIMD instructions (MMX, SSE2, NEON) to accelerate baseline JPEG compression and decompression on x86, diff --git a/release/makedpkg.in b/release/makedpkg.in index bca323f9..06cc4db3 100644 --- a/release/makedpkg.in +++ b/release/makedpkg.in @@ -7,14 +7,20 @@ trap onexit TERM trap onexit EXIT TMPDIR= +SUDO= onexit() { if [ ! "$TMPDIR" = "" ]; then - sudo rm -rf $TMPDIR + $SUDO rm -rf $TMPDIR fi } +uid() +{ + id | cut -f2 -d = | cut -f1 -d \(; +} + makedeb() { SUPPLEMENT=$1 @@ -29,9 +35,6 @@ makedeb() rm -f $PACKAGE_NAME\_$VERSION\_$DEBARCH.deb TMPDIR=`mktemp -d /tmp/$PACKAGE_NAME-build.XXXXXX` mkdir $TMPDIR/DEBIAN - (cat $SRCDIR/release/deb-control.tmpl | sed s/{__PKGNAME}/$PACKAGE_NAME/g \ - | sed s/{__VERSION}/$VERSION/g | sed s/{__BUILD}/$BUILD/g \ - | sed s/{__ARCH}/$DEBARCH/g > $TMPDIR/DEBIAN/control) if [ $SUPPLEMENT = 1 ]; then make install DESTDIR=$TMPDIR bindir=/dummy/bin datadir=/dummy/data \ @@ -47,9 +50,16 @@ makedeb() fi fi + SIZE=`du -s $TMPDIR | cut -f1` + (cat $SRCDIR/release/deb-control.tmpl | sed s/{__PKGNAME}/$PACKAGE_NAME/g \ + | sed s/{__VERSION}/$VERSION/g | sed s/{__BUILD}/$BUILD/g \ + | sed s/{__ARCH}/$DEBARCH/g | sed s/{__SIZE}/$SIZE/g \ + > $TMPDIR/DEBIAN/control) + + /sbin/ldconfig -n $TMPDIR$LIBDIR - sudo chown -Rh root:root $TMPDIR/* + $SUDO chown -Rh root:root $TMPDIR/* dpkg -b $TMPDIR $PACKAGE_NAME\_$VERSION\_$DEBARCH.deb } @@ -62,6 +72,10 @@ PREFIX=%{__prefix} DOCDIR=%{__docdir} LIBDIR=%{__libdir} +if [ ! `uid` -eq 0 ]; then + SUDO=sudo +fi + makedeb 0 if [ "$DEBARCH" = "i386" ]; then makedeb 1; fi diff --git a/sharedlib/CMakeLists.txt b/sharedlib/CMakeLists.txt index fc3ae915..268cc141 100755 --- a/sharedlib/CMakeLists.txt +++ b/sharedlib/CMakeLists.txt @@ -42,16 +42,22 @@ if(WITH_SIMD) add_dependencies(jpeg simd) endif() -add_executable(cjpeg ../cjpeg.c ../cdjpeg.c ../rdbmp.c ../rdgif.c ../rdppm.c - ../rdswitch.c ../rdtarga.c ../rdjpeg.c) -set_property(TARGET cjpeg PROPERTY COMPILE_FLAGS - "-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED -DUSE_SETMODE") +if(WITH_12BIT) + set(COMPILE_FLAGS "-DGIF_SUPPORTED -DPPM_SUPPORTED -DUSE_SETMODE") +else() + set(COMPILE_FLAGS "-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED -DUSE_SETMODE") + set(CJPEG_BMP_SOURCES ../rdbmp.c ../rdtarga.c) + set(DJPEG_BMP_SOURCES ../wrbmp.c ../wrtarga.c) +endif() + +add_executable(cjpeg ../cjpeg.c ../cdjpeg.c ../rdgif.c ../rdppm.c ../rdjpeg.c + ../rdswitch.c ${CJPEG_BMP_SOURCES}) +set_property(TARGET cjpeg PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS}) target_link_libraries(cjpeg jpeg) add_executable(djpeg ../djpeg.c ../cdjpeg.c ../rdcolmap.c ../rdswitch.c - ../wrbmp.c ../wrgif.c ../wrppm.c ../wrtarga.c) -set_property(TARGET djpeg PROPERTY COMPILE_FLAGS - "-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED -DUSE_SETMODE") + ../wrgif.c ../wrppm.c ${DJPEG_BMP_SOURCES}) +set_property(TARGET djpeg PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS}) target_link_libraries(djpeg jpeg) add_executable(jpegtran ../jpegtran.c ../cdjpeg.c ../rdswitch.c ../transupp.c) diff --git a/simd/CMakeLists.txt b/simd/CMakeLists.txt index 382bfb8b..81ba2948 100755 --- a/simd/CMakeLists.txt +++ b/simd/CMakeLists.txt @@ -3,12 +3,15 @@ if(NOT DEFINED NASM) endif() if(SIMD_X86_64) - set(NAFLAGS -fwin64 -DWIN64 -D__x86_64__ "-I${CMAKE_SOURCE_DIR}/win/" - "-I${CMAKE_CURRENT_SOURCE_DIR}/") + set(NAFLAGS -fwin64 -DWIN64 -D__x86_64__) else() - set(NAFLAGS -fwin32 -DWIN32 "-I${CMAKE_SOURCE_DIR}/win/" - "-I${CMAKE_CURRENT_SOURCE_DIR}/") + if(BORLAND) + set(NAFLAGS -fobj -DOBJ32) + else() + set(NAFLAGS -fwin32 -DWIN32) + endif() endif() +set(NAFLAGS ${NAFLAGS} -I${CMAKE_SOURCE_DIR}/win/ -I${CMAKE_CURRENT_SOURCE_DIR}/) # This only works if building from the command line. There is currently no way # to set a variable's value based on the build type when using the MSVC IDE. diff --git a/simd/Makefile.am b/simd/Makefile.am index c4f6a53b..bc631452 100644 --- a/simd/Makefile.am +++ b/simd/Makefile.am @@ -60,7 +60,7 @@ endif if SIMD_ARM_64 -libsimd_la_SOURCES = jsimd_arm64.c jsimd_arm_neon_64.S +libsimd_la_SOURCES = jsimd_arm64.c jsimd_arm64_neon.S endif diff --git a/simd/jsimd.h b/simd/jsimd.h index 609b91f5..c5abd458 100644 --- a/simd/jsimd.h +++ b/simd/jsimd.h @@ -4,6 +4,7 @@ * Copyright 2009 Pierre Ossman for Cendio AB * Copyright 2011 D. R. Commander * Copyright (C) 2013-2014, MIPS Technologies, Inc., California + * Copyright (C) 2014 Linaro Limited * * Based on the x86 SIMD extension for IJG JPEG library, * Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -249,6 +250,9 @@ EXTERN(void) jsimd_ycc_extxbgr_convert_neon EXTERN(void) jsimd_ycc_extxrgb_convert_neon (JDIMENSION out_width, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows); +EXTERN(void) jsimd_ycc_rgb565_convert_neon + (JDIMENSION out_width, JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows); EXTERN(void) jsimd_ycc_rgb_convert_mips_dspr2 (JDIMENSION out_width, JSAMPIMAGE input_buf, JDIMENSION input_row, diff --git a/simd/jsimd_arm.c b/simd/jsimd_arm.c index aefb1e67..4cbcf2d5 100644 --- a/simd/jsimd_arm.c +++ b/simd/jsimd_arm.c @@ -2,7 +2,7 @@ * jsimd_arm.c * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright 2009-2011, 2013 D. R. Commander + * Copyright 2009-2011, 2013-2014 D. R. Commander * * Based on the x86 SIMD extension for IJG JPEG library, * Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -175,6 +175,23 @@ jsimd_can_ycc_rgb (void) return 0; } +GLOBAL(int) +jsimd_can_ycc_rgb565 (void) +{ + init_simd(); + + /* The code is optimised for these values only */ + if (BITS_IN_JSAMPLE != 8) + return 0; + if (sizeof(JDIMENSION) != 4) + return 0; + + if (simd_support & JSIMD_ARM_NEON) + return 1; + + return 0; +} + GLOBAL(void) jsimd_rgb_ycc_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, @@ -251,7 +268,7 @@ jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, case JCS_EXT_ARGB: neonfct=jsimd_ycc_extxrgb_convert_neon; break; - default: + default: neonfct=jsimd_ycc_extrgb_convert_neon; break; } @@ -260,6 +277,16 @@ jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, neonfct(cinfo->output_width, input_buf, input_row, output_buf, num_rows); } +GLOBAL(void) +jsimd_ycc_rgb565_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + if (simd_support & JSIMD_ARM_NEON) + jsimd_ycc_rgb565_convert_neon(cinfo->output_width, input_buf, input_row, + output_buf, num_rows); +} + GLOBAL(int) jsimd_can_h2v2_downsample (void) { diff --git a/simd/jsimd_arm64.c b/simd/jsimd_arm64.c index 988023a6..65724cb9 100644 --- a/simd/jsimd_arm64.c +++ b/simd/jsimd_arm64.c @@ -27,98 +27,29 @@ static unsigned int simd_support = ~0; -#if defined(__linux__) || defined(ANDROID) || defined(__ANDROID__) - -#define SOMEWHAT_SANE_PROC_CPUINFO_SIZE_LIMIT (1024 * 1024) - -LOCAL(int) -check_feature (char *buffer, char *feature) -{ - char *p; - if (*feature == 0) - return 0; - if (strncmp(buffer, "Features", 8) != 0) - return 0; - buffer += 8; - while (isspace(*buffer)) - buffer++; - - /* Check if 'feature' is present in the buffer as a separate word */ - while ((p = strstr(buffer, feature))) { - if (p > buffer && !isspace(*(p - 1))) { - buffer++; - continue; - } - p += strlen(feature); - if (*p != 0 && !isspace(*p)) { - buffer++; - continue; - } - return 1; - } - return 0; -} - -LOCAL(int) -parse_proc_cpuinfo (int bufsize) -{ - char *buffer = (char *)malloc(bufsize); - FILE *fd; - simd_support = 0; - - if (!buffer) - return 0; - - fd = fopen("/proc/cpuinfo", "r"); - if (fd) { - while (fgets(buffer, bufsize, fd)) { - if (!strchr(buffer, '\n') && !feof(fd)) { - /* "impossible" happened - insufficient size of the buffer! */ - fclose(fd); - free(buffer); - return 0; - } - if (check_feature(buffer, "neon")) - simd_support |= JSIMD_ARM_NEON; - } - fclose(fd); - } - free(buffer); - return 1; -} - -#endif - /* * Check what SIMD accelerations are supported. * * FIXME: This code is racy under a multi-threaded environment. */ + +/* + * ARMv8 architectures support NEON extensions by default. + * It is no longer optional as it was with ARMv7. + */ + + LOCAL(void) init_simd (void) { char *env = NULL; -#if !defined(__ARM_NEON__) && defined(__linux__) || defined(ANDROID) || defined(__ANDROID__) - int bufsize = 1024; /* an initial guess for the line buffer size limit */ -#endif if (simd_support != ~0U) return; simd_support = 0; -#if defined(__ARM_NEON__) simd_support |= JSIMD_ARM_NEON; -#elif defined(__linux__) || defined(ANDROID) || defined(__ANDROID__) - /* We still have a chance to use NEON regardless of globally used - * -mcpu/-mfpu options passed to gcc by performing runtime detection via - * /proc/cpuinfo parsing on linux/android */ - while (!parse_proc_cpuinfo(bufsize)) { - bufsize *= 2; - if (bufsize > SOMEWHAT_SANE_PROC_CPUINFO_SIZE_LIMIT) - break; - } -#endif /* Force different settings through environment variables */ env = getenv("JSIMD_FORCENEON"); @@ -164,6 +95,23 @@ jsimd_can_ycc_rgb (void) return 0; } +GLOBAL(int) +jsimd_can_ycc_rgb565 (void) +{ + init_simd(); + + /* The code is optimised for these values only */ + if (BITS_IN_JSAMPLE != 8) + return 0; + if (sizeof(JDIMENSION) != 4) + return 0; + + if (simd_support & JSIMD_ARM_NEON) + return 1; + + return 0; +} + GLOBAL(void) jsimd_rgb_ycc_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, @@ -208,7 +156,7 @@ jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, case JCS_EXT_ARGB: neonfct=jsimd_ycc_extxrgb_convert_neon; break; - default: + default: neonfct=jsimd_ycc_extrgb_convert_neon; break; } @@ -217,6 +165,16 @@ jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, neonfct(cinfo->output_width, input_buf, input_row, output_buf, num_rows); } +GLOBAL(void) +jsimd_ycc_rgb565_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + if (simd_support & JSIMD_ARM_NEON) + jsimd_ycc_rgb565_convert_neon(cinfo->output_width, input_buf, input_row, + output_buf, num_rows); +} + GLOBAL(int) jsimd_can_h2v2_downsample (void) { diff --git a/simd/jsimd_arm_neon_64.S b/simd/jsimd_arm64_neon.S similarity index 85% rename from simd/jsimd_arm_neon_64.S rename to simd/jsimd_arm64_neon.S index 8806abc6..f488b0f1 100644 --- a/simd/jsimd_arm_neon_64.S +++ b/simd/jsimd_arm64_neon.S @@ -4,7 +4,7 @@ * Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). * All rights reserved. * Author: Siarhei Siamashka - * Copyright (C) 2013, Linaro Limited + * Copyright (C) 2013-2014, Linaro Limited * Author: Ragesh Radhakrishnan * * This software is provided 'as-is', without any express or implied @@ -34,19 +34,15 @@ #define RESPECT_STRICT_ALIGNMENT 1 -#define RTSM_SQSHRN_SIM_ISSUE - /*****************************************************************************/ /* Supplementary macro for setting function attributes */ .macro asm_function fname #ifdef __APPLE__ - .func _\fname .globl _\fname _\fname: #else - .func \fname .global \fname #ifdef __ELF__ .hidden \fname @@ -257,8 +253,18 @@ asm_function jsimd_idct_islow_neon ROW6R .req v29 ROW7L .req v30 ROW7R .req v31 - + /* Save all NEON registers and x15 (32 NEON registers * 8 bytes + 16) */ + sub sp, sp, 272 + str x15, [sp], 16 adr x15, jsimd_idct_islow_neon_consts + st1 {v0.8b - v3.8b}, [sp], 32 + st1 {v4.8b - v7.8b}, [sp], 32 + st1 {v8.8b - v11.8b}, [sp], 32 + st1 {v12.8b - v15.8b}, [sp], 32 + st1 {v16.8b - v19.8b}, [sp], 32 + st1 {v20.8b - v23.8b}, [sp], 32 + st1 {v24.8b - v27.8b}, [sp], 32 + st1 {v28.8b - v31.8b}, [sp], 32 ld1 {v16.4h, v17.4h, v18.4h, v19.4h}, [COEF_BLOCK], 32 ld1 {v0.4h, v1.4h, v2.4h, v3.4h}, [DCT_TABLE], 32 ld1 {v20.4h, v21.4h, v22.4h, v23.4h}, [COEF_BLOCK], 32 @@ -277,7 +283,7 @@ asm_function jsimd_idct_islow_neon mul v22.4h, v22.4h, v6.4h mul v23.4h, v23.4h, v7.4h ins v22.2d[1], v23.2d[0] /* 128 bit q11 */ - ld1 {v28.4h, v29.4h, v30.4h, v31.4h}, [COEF_BLOCK], 32 + ld1 {v28.4h, v29.4h, v30.4h, v31.4h}, [COEF_BLOCK] mul v24.4h, v24.4h, v0.4h mul v25.4h, v25.4h, v1.4h ins v24.2d[1], v25.2d[0] /* 128 bit q12 */ @@ -293,85 +299,84 @@ asm_function jsimd_idct_islow_neon mul v30.4h, v30.4h, v6.4h mul v31.4h, v31.4h, v7.4h ins v30.2d[1], v31.2d[0] /* 128 bit q15 */ - sub sp, sp, #32 - st1 {v8.4h-v11.4h}, [sp] /* save NEON registers */ - sub sp, sp, #32 - st1 {v12.4h-v15.4h}, [sp] + /* Go to the bottom of the stack */ + sub sp, sp, 352 + stp x4, x5, [sp], 16 + st1 {v8.4h - v11.4h}, [sp], 32 /* save NEON registers */ + st1 {v12.4h - v15.4h}, [sp], 32 /* 1-D IDCT, pass 1, left 4x8 half */ add v4.4h, ROW7L.4h, ROW3L.4h add v5.4h, ROW5L.4h, ROW1L.4h smull v12.4s, v4.4h, XFIX_1_175875602_MINUS_1_961570560 smlal v12.4s, v5.4h, XFIX_1_175875602 smull v14.4s, v4.4h, XFIX_1_175875602 - /* Check for the zero coefficients in the right 4x8 half */ - /* push {x4, x5} */ - stp x4, x5, [sp, -16]! - mov x5, #0 + /* Check for the zero coefficients in the right 4x8 half */ smlal v14.4s, v5.4h, XFIX_1_175875602_MINUS_0_390180644 ssubl v6.4s, ROW0L.4h, ROW4L.4h - ldr x4, [COEF_BLOCK, #(-96 + 2 * (4 + 1 * 8))] + ldp w4, w5, [COEF_BLOCK, #(-96 + 2 * (4 + 1 * 8))] smull v4.4s, ROW2L.4h, XFIX_0_541196100 smlal v4.4s, ROW6L.4h, XFIX_0_541196100_MINUS_1_847759065 - orr x0, x4, x5 + orr x0, x4, x5 mov v8.16b, v12.16b smlsl v12.4s, ROW5L.4h, XFIX_2_562915447 - ldr x4, [COEF_BLOCK, #(-96 + 2 * (4 + 2 * 8))] + ldp w4, w5, [COEF_BLOCK, #(-96 + 2 * (4 + 2 * 8))] smlal v12.4s, ROW3L.4h, XFIX_3_072711026_MINUS_2_562915447 shl v6.4s, v6.4s, #13 - orr x0, x0, x4 + orr x0, x0, x4 smlsl v8.4s, ROW1L.4h, XFIX_0_899976223 - orr x0, x0 , x5 + orr x0, x0 , x5 add v2.4s, v6.4s, v4.4s - ldr x4, [COEF_BLOCK, #(-96 + 2 * (4 + 3 * 8))] + ldp w4, w5, [COEF_BLOCK, #(-96 + 2 * (4 + 3 * 8))] mov v10.16b, v14.16b add v2.4s, v2.4s, v12.4s - orr x0, x0, x4 + orr x0, x0, x4 smlsl v14.4s, ROW7L.4h, XFIX_0_899976223 - orr x0, x0, x5 + orr x0, x0, x5 smlal v14.4s, ROW1L.4h, XFIX_1_501321110_MINUS_0_899976223 rshrn ROW1L.4h, v2.4s, #11 - ldr x4, [COEF_BLOCK, #(-96 + 2 * (4 + 4 * 8))] + ldp w4, w5, [COEF_BLOCK, #(-96 + 2 * (4 + 4 * 8))] sub v2.4s, v2.4s, v12.4s smlal v10.4s, ROW5L.4h, XFIX_2_053119869_MINUS_2_562915447 - orr x0, x0, x4 + orr x0, x0, x4 smlsl v10.4s, ROW3L.4h, XFIX_2_562915447 - orr x0, x0, x5 + orr x0, x0, x5 sub v2.4s, v2.4s, v12.4s smull v12.4s, ROW2L.4h, XFIX_0_541196100_PLUS_0_765366865 - ldr x4, [COEF_BLOCK, #(-96 + 2 * (4 + 5 * 8))] + ldp w4, w5, [COEF_BLOCK, #(-96 + 2 * (4 + 5 * 8))] smlal v12.4s, ROW6L.4h, XFIX_0_541196100 sub v6.4s, v6.4s, v4.4s - orr x0, x0, x4 + orr x0, x0, x4 rshrn ROW6L.4h, v2.4s, #11 - orr x0, x0, x5 + orr x0, x0, x5 add v2.4s, v6.4s, v10.4s - ldr x4, [COEF_BLOCK, #(-96 + 2 * (4 + 6 * 8))] + ldp w4, w5, [COEF_BLOCK, #(-96 + 2 * (4 + 6 * 8))] sub v6.4s, v6.4s, v10.4s saddl v10.4s, ROW0L.4h, ROW4L.4h - orr x0, x0, x4 + orr x0, x0, x4 rshrn ROW2L.4h, v2.4s, #11 - orr x0, x0, x5 + orr x0, x0, x5 rshrn ROW5L.4h, v6.4s, #11 - ldr x4, [COEF_BLOCK, #(-96 + 2 * (4 + 7 * 8))] + ldp w4, w5, [COEF_BLOCK, #(-96 + 2 * (4 + 7 * 8))] shl v10.4s, v10.4s, #13 smlal v8.4s, ROW7L.4h, XFIX_0_298631336_MINUS_0_899976223 - orr x0, x0, x4 + orr x0, x0, x4 add v4.4s, v10.4s, v12.4s - orr x0, x0, x5 + orr x0, x0, x5 + cmp x0, #0 /* orrs instruction removed */ sub v2.4s, v10.4s, v12.4s add v12.4s, v4.4s, v14.4s - ldr x4, [COEF_BLOCK, #(-96 + 2 * (4 + 0 * 8))] + ldp w4, w5, [COEF_BLOCK, #(-96 + 2 * (4 + 0 * 8))] sub v4.4s, v4.4s, v14.4s add v10.4s, v2.4s, v8.4s - orr x0, x4, x5 + orr x0, x4, x5 sub v6.4s, v2.4s, v8.4s /* pop {x4, x5} */ - ldp x4, x5, [sp], 16 + sub sp, sp, 80 + ldp x4, x5, [sp], 16 rshrn ROW7L.4h, v4.4s, #11 rshrn ROW3L.4h, v10.4s, #11 rshrn ROW0L.4h, v12.4s, #11 rshrn ROW4L.4h, v6.4s, #11 - cmp x0, #0 /* orrs instruction removed */ beq 3f /* Go to do some special handling for the sparse right 4x8 half */ @@ -433,7 +438,7 @@ asm_function jsimd_idct_islow_neon add v12.4s, v4.4s, v14.4s sub v4.4s, v4.4s, v14.4s add v10.4s, v2.4s, v8.4s - sub v12.4s, v2.4s, v8.4s + sub v6.4s, v2.4s, v8.4s rshrn ROW7R.4h, v4.4s, #11 rshrn ROW3R.4h, v10.4s, #11 rshrn ROW0R.4h, v12.4s, #11 @@ -552,48 +557,27 @@ asm_function jsimd_idct_islow_neon ins v18.2d[1], v19.2d[0] ins v20.2d[1], v21.2d[0] ins v22.2d[1], v23.2d[0] -#ifdef RTSM_SQSHRN_SIM_ISSUE sqrshrn v16.8b, v16.8h, #2 sqrshrn2 v16.16b, v18.8h, #2 sqrshrn v18.8b, v20.8h, #2 sqrshrn2 v18.16b, v22.8h, #2 -#else - sqrshrn v16.4h, v16.4s, #2 - sqrshrn2 v16.8h, v18.4s, #2 - sqrshrn v18.4h, v20.4s, #2 - sqrshrn2 v18.8h, v22.4s, #2 -#endif - /* vpop {v8.4h-d15.4h} */ /* restore NEON registers */ - ld1 {v12.4h-v15.4h}, [sp], 32 - ld1 {v8.4h-v11.4h}, [sp], 32 + /* vpop {v8.4h - d15.4h} */ /* restore NEON registers */ + ld1 {v8.4h - v11.4h}, [sp], 32 + ld1 {v12.4h - v15.4h}, [sp], 32 ins v24.2d[1], v25.2d[0] -#ifdef RTSM_SQSHRN_SIM_ISSUE sqrshrn v20.8b, v24.8h, #2 -#else - - sqrshrn v20.4h, v24.4s, #2 -#endif /* Transpose the final 8-bit samples and do signed->unsigned conversion */ /* trn1 v16.8h, v16.8h, v18.8h */ transpose v16, v18, v3, .16b, .8h ins v26.2d[1], v27.2d[0] ins v28.2d[1], v29.2d[0] ins v30.2d[1], v31.2d[0] -#ifdef RTSM_SQSHRN_SIM_ISSUE sqrshrn2 v20.16b, v26.8h, #2 sqrshrn v22.8b, v28.8h, #2 -#else - sqrshrn2 v20.8h, v26.4s, #2 - sqrshrn v22.4h, v28.4s, #2 -#endif movi v0.16b, #(CENTERJSAMPLE) -#ifdef RTSM_SQSHRN_SIM_ISSUE sqrshrn2 v22.16b, v30.8h, #2 -#else - sqrshrn2 v22.8h, v30.4s, #2 -#endif transpose_single v16, v17, v3, .2d, .8b transpose_single v18, v19, v3, .2d, .8b add v16.8b, v16.8b, v0.8b @@ -628,6 +612,15 @@ asm_function jsimd_idct_islow_neon st1 {v21.8b}, [TMP2] st1 {v22.8b}, [TMP3] st1 {v23.8b}, [TMP4] + ldr x15, [sp], 16 + ld1 {v0.8b - v3.8b}, [sp], 32 + ld1 {v4.8b - v7.8b}, [sp], 32 + ld1 {v8.8b - v11.8b}, [sp], 32 + ld1 {v12.8b - v15.8b}, [sp], 32 + ld1 {v16.8b - v19.8b}, [sp], 32 + ld1 {v20.8b - v23.8b}, [sp], 32 + ld1 {v24.8b - v27.8b}, [sp], 32 + ld1 {v28.8b - v31.8b}, [sp], 32 blr x30 3: /* Left 4x8 half is done, right 4x8 half contains mostly zeros */ @@ -757,7 +750,6 @@ asm_function jsimd_idct_islow_neon .unreq ROW6R .unreq ROW7L .unreq ROW7R -.endfunc /*****************************************************************************/ @@ -799,7 +791,8 @@ asm_function jsimd_idct_ifast_neon TMP1 .req x0 TMP2 .req x1 TMP3 .req x2 - TMP4 .req x15 + TMP4 .req x22 + TMP5 .req x23 /* Load and dequantize coefficients into NEON registers * with the following allocation: @@ -814,7 +807,15 @@ asm_function jsimd_idct_ifast_neon * 6 | d28 | d29 ( v14.8h ) * 7 | d30 | d31 ( v15.8h ) */ - adr x15, jsimd_idct_ifast_neon_consts + /* Save NEON registers used in fast IDCT */ + sub sp, sp, #176 + stp x22, x23, [sp], 16 + adr x23, jsimd_idct_ifast_neon_consts + st1 {v0.8b - v3.8b}, [sp], 32 + st1 {v4.8b - v7.8b}, [sp], 32 + st1 {v8.8b - v11.8b}, [sp], 32 + st1 {v12.8b - v15.8b}, [sp], 32 + st1 {v16.8b - v19.8b}, [sp], 32 ld1 {v8.8h, v9.8h}, [COEF_BLOCK], 32 ld1 {v0.8h, v1.8h}, [DCT_TABLE], 32 ld1 {v10.8h, v11.8h}, [COEF_BLOCK], 32 @@ -830,14 +831,9 @@ asm_function jsimd_idct_ifast_neon ld1 {v2.8h, v3.8h}, [DCT_TABLE], 32 mul v14.8h, v14.8h, v2.8h mul v13.8h, v13.8h, v1.8h - ld1 {v0.4h}, [x15] /* load constants */ + ld1 {v0.4h}, [x23] /* load constants */ mul v15.8h, v15.8h, v3.8h - /* vpush {v4.8h-v6.8h} */ /* save NEON registers */ - sub sp, sp, #32 - st1 {v4.8h-v5.8h}, [sp] /* save NEON registers */ - sub sp, sp, #16 - st1 {v6.8h}, [sp] /* 1-D IDCT, pass 1 */ sub v2.8h, v10.8h, v14.8h add v14.8h, v10.8h, v14.8h @@ -912,25 +908,25 @@ asm_function jsimd_idct_ifast_neon trn1 v13.4s, v13.4s, v15.4s trn2 v15.4s, v18.4s, v15.4s /* vswp v14.4h, v10-MSB.4h */ - umov x10, v14.d[0] + umov x22, v14.d[0] ins v14.2d[0], v10.2d[1] - ins v10.2d[1], x10 + ins v10.2d[1], x22 /* vswp v13.4h, v9MSB.4h */ - umov x10, v13.d[0] + umov x22, v13.d[0] ins v13.2d[0], v9.2d[1] - ins v9.2d[1], x10 + ins v9.2d[1], x22 /* 1-D IDCT, pass 2 */ sub v2.8h, v10.8h, v14.8h /* vswp v15.4h, v11MSB.4h */ - umov x10, v15.d[0] + umov x22, v15.d[0] ins v15.2d[0], v11.2d[1] - ins v11.2d[1], x10 + ins v11.2d[1], x22 add v14.8h, v10.8h, v14.8h /* vswp v12.4h, v8-MSB.4h */ - umov x10, v12.d[0] + umov x22, v12.d[0] ins v12.2d[0], v8.2d[1] - ins v8.2d[1], x10 + ins v8.2d[1], x22 sub v1.8h, v11.8h, v13.8h add v13.8h, v11.8h, v13.8h sub v5.8h, v9.8h, v15.8h @@ -966,15 +962,11 @@ asm_function jsimd_idct_ifast_neon add v14.8h, v5.8h, v3.8h sub v9.8h, v5.8h, v3.8h sub v13.8h, v10.8h, v2.8h - /* vpop {v4.8h-v7.4h} */ /* restore NEON registers...not available */ - ld1 {v6.8h}, [sp], 16 - ld1 {v4.8h-v5.8h}, [sp], 32 add v10.8h, v10.8h, v2.8h sub v11.8h, v12.8h, v1.8h add v12.8h, v12.8h, v1.8h /* Descale to 8-bit and range limit */ movi v0.16b, #0x80 -#ifdef RTSM_SQSHRN_SIM_ISSUE sqshrn v8.8b, v8.8h, #5 sqshrn2 v8.16b, v9.8h, #5 sqshrn v9.8b, v10.8h, #5 @@ -983,16 +975,6 @@ asm_function jsimd_idct_ifast_neon sqshrn2 v10.16b, v13.8h, #5 sqshrn v11.8b, v14.8h, #5 sqshrn2 v11.16b, v15.8h, #5 -#else - sqshrn v8.4h, v8.4s, #5 - sqshrn2 v8.8h, v9.4s, #5 - sqshrn v9.4h, v10.4s, #5 - sqshrn2 v9.8h, v11.4s, #5 - sqshrn v10.4h, v12.4s, #5 - sqshrn2 v10.8h, v13.4s, #5 - sqshrn v11.4h, v14.4s, #5 - sqshrn2 v11.8h, v15.4s, #5 -#endif add v8.16b, v8.16b, v0.16b add v9.16b, v9.16b, v0.16b add v10.16b, v10.16b, v0.16b @@ -1036,26 +1018,33 @@ asm_function jsimd_idct_ifast_neon add TMP2, TMP2, OUTPUT_COL st1 {v9.8b}, [TMP1] /* make copy */ - ins v21.2d[0], v10.2d[1] + ins v7.2d[0], v10.2d[1] mov v18.16b, v10.16b - trn1 v10.8b, v10.8b, v21.8b - trn2 v21.8b, v18.8b, v21.8b + trn1 v10.8b, v10.8b, v7.8b + trn2 v7.8b, v18.8b, v7.8b st1 {v19.8b}, [TMP2] ldp TMP1, TMP2, [OUTPUT_BUF], 16 - ldp TMP3, TMP4, [OUTPUT_BUF] + ldp TMP4, TMP5, [OUTPUT_BUF], 16 add TMP1, TMP1, OUTPUT_COL add TMP2, TMP2, OUTPUT_COL - add TMP3, TMP3, OUTPUT_COL add TMP4, TMP4, OUTPUT_COL + add TMP5, TMP5, OUTPUT_COL st1 {v10.8b}, [TMP1] /* make copy */ - ins v23.2d[0], v11.2d[1] + ins v16.2d[0], v11.2d[1] mov v18.16b, v11.16b - trn1 v11.8b, v11.8b, v23.8b - trn2 v23.8b, v18.8b, v23.8b - st1 {v21.8b}, [TMP2] - st1 {v11.8b}, [TMP3] - st1 {v23.8b}, [TMP4] + trn1 v11.8b, v11.8b, v16.8b + trn2 v16.8b, v18.8b, v16.8b + st1 {v7.8b}, [TMP2] + st1 {v11.8b}, [TMP4] + st1 {v16.8b}, [TMP5] + sub sp, sp, #176 + ldp x22, x23, [sp], 16 + ld1 {v0.8b - v3.8b}, [sp], 32 + ld1 {v4.8b - v7.8b}, [sp], 32 + ld1 {v8.8b - v11.8b}, [sp], 32 + ld1 {v12.8b - v15.8b}, [sp], 32 + ld1 {v16.8b - v19.8b}, [sp], 32 blr x30 .unreq DCT_TABLE @@ -1066,7 +1055,6 @@ asm_function jsimd_idct_ifast_neon .unreq TMP2 .unreq TMP3 .unreq TMP4 -.endfunc /*****************************************************************************/ @@ -1179,14 +1167,19 @@ asm_function jsimd_idct_4x4_neon TMP3 .req x2 TMP4 .req x15 - /* vpush {v8.4h-v15.4h} */ - sub sp, sp, #32 - st1 {v8.4h-v11.4h}, [sp] /* save NEON registers */ - sub sp, sp, #32 - st1 {v12.4h-v15.4h}, [sp] - + /* Save all used NEON registers */ + sub sp, sp, 272 + str x15, [sp], 16 /* Load constants (v3.4h is just used for padding) */ adr TMP4, jsimd_idct_4x4_neon_consts + st1 {v0.8b - v3.8b}, [sp], 32 + st1 {v4.8b - v7.8b}, [sp], 32 + st1 {v8.8b - v11.8b}, [sp], 32 + st1 {v12.8b - v15.8b}, [sp], 32 + st1 {v16.8b - v19.8b}, [sp], 32 + st1 {v20.8b - v23.8b}, [sp], 32 + st1 {v24.8b - v27.8b}, [sp], 32 + st1 {v28.8b - v31.8b}, [sp], 32 ld1 {v0.4h, v1.4h, v2.4h, v3.4h}, [TMP4] /* Load all COEF_BLOCK into NEON registers with the following allocation: @@ -1226,7 +1219,7 @@ asm_function jsimd_idct_4x4_neon mul v12.4h, v12.4h, v26.4h mul v13.4h, v13.4h, v27.4h ins v12.2d[1], v13.2d[0] /* 128 bit q12 */ - ld1 {v30.8h}, [DCT_TABLE], 16 + ld1 {v30.4h, v31.4h}, [DCT_TABLE], 16 mul v14.4h, v14.4h, v28.4h mul v15.4h, v15.4h, v29.4h ins v14.2d[1], v15.2d[0] /* 128 bit q14 */ @@ -1290,10 +1283,17 @@ asm_function jsimd_idct_4x4_neon st1 {v27.b}[7], [TMP4], 1 #endif - /* vpop {v8.4h-v15.4h} ;not available */ - ld1 {v12.4h-v15.4h}, [sp], 32 - ld1 {v8.4h-v11.4h}, [sp], 32 - + /* vpop {v8.4h - v15.4h} ;not available */ + sub sp, sp, #272 + ldr x15, [sp], 16 + ld1 {v0.8b - v3.8b}, [sp], 32 + ld1 {v4.8b - v7.8b}, [sp], 32 + ld1 {v8.8b - v11.8b}, [sp], 32 + ld1 {v12.8b - v15.8b}, [sp], 32 + ld1 {v16.8b - v19.8b}, [sp], 32 + ld1 {v20.8b - v23.8b}, [sp], 32 + ld1 {v24.8b - v27.8b}, [sp], 32 + ld1 {v28.8b - v31.8b}, [sp], 32 blr x30 .unreq DCT_TABLE @@ -1304,7 +1304,6 @@ asm_function jsimd_idct_4x4_neon .unreq TMP2 .unreq TMP3 .unreq TMP4 -.endfunc .purgem idct_helper @@ -1327,29 +1326,29 @@ asm_function jsimd_idct_4x4_neon .balign 8 jsimd_idct_2x2_neon_consts: - .short -FIX_0_720959822 /* d0[0] */ - .short FIX_0_850430095 /* d0[1] */ - .short -FIX_1_272758580 /* d0[2] */ - .short FIX_3_624509785 /* d0[3] */ + .short -FIX_0_720959822 /* v14[0] */ + .short FIX_0_850430095 /* v14[1] */ + .short -FIX_1_272758580 /* v14[2] */ + .short FIX_3_624509785 /* v14[3] */ .macro idct_helper x4, x6, x10, x12, x16, shift, y26, y27 - sshll v28.4s, \x4, #15 - smull v26.4s, \x6, v0.4h[3] - smlal v26.4s, \x10, v0.4h[2] - smlal v26.4s, \x12, v0.4h[1] - smlal v26.4s, \x16, v0.4h[0] + sshll v15.4s, \x4, #15 + smull v26.4s, \x6, v14.4h[3] + smlal v26.4s, \x10, v14.4h[2] + smlal v26.4s, \x12, v14.4h[1] + smlal v26.4s, \x16, v14.4h[0] - add v20.4s, v28.4s, v26.4s - sub v28.4s, v28.4s, v26.4s + add v20.4s, v15.4s, v26.4s + sub v15.4s, v15.4s, v26.4s .if \shift > 16 srshr v20.4s, v20.4s, #\shift - srshr v28.4s, v28.4s, #\shift + srshr v15.4s, v15.4s, #\shift xtn \y26, v20.4s - xtn \y27, v28.4s + xtn \y27, v15.4s .else rshrn \y26, v20.4s, #\shift - rshrn \y27, v28.4s, #\shift + rshrn \y27, v15.4s, #\shift .endif .endm @@ -1363,15 +1362,20 @@ asm_function jsimd_idct_2x2_neon TMP1 .req x0 TMP2 .req x15 - /* vpush {v8.4h-v15.4h} ; not available */ - sub sp, sp, #32 - st1 {v8.4h-v11.4h}, [sp] /* save NEON registers */ - sub sp, sp, #32 - st1 {v12.4h-v15.4h}, [sp] + /* vpush {v8.4h - v15.4h} ; not available */ + sub sp, sp, 208 + str x15, [sp], 16 /* Load constants */ adr TMP2, jsimd_idct_2x2_neon_consts - ld1 {v0.4h}, [TMP2] + st1 {v4.8b - v7.8b}, [sp], 32 + st1 {v8.8b - v11.8b}, [sp], 32 + st1 {v12.8b - v15.8b}, [sp], 32 + st1 {v16.8b - v19.8b}, [sp], 32 + st1 {v21.8b - v22.8b}, [sp], 16 + st1 {v24.8b - v27.8b}, [sp], 32 + st1 {v30.8b - v31.8b}, [sp], 16 + ld1 {v14.4h}, [TMP2] /* Load all COEF_BLOCK into NEON registers with the following allocation: * 0 1 2 3 | 4 5 6 7 @@ -1394,26 +1398,26 @@ asm_function jsimd_idct_2x2_neon ld1 {v16.4h, v17.4h}, [COEF_BLOCK], 16 /* Dequantize */ ld1 {v18.4h, v19.4h, v20.4h, v21.4h}, [DCT_TABLE], 32 - mul v4.8h, v4.8h, v18.8h - mul v5.8h, v5.8h, v18.8h + mul v4.4h, v4.4h, v18.4h + mul v5.4h, v5.4h, v19.4h ins v4.2d[1], v5.2d[0] - mul v6.8h, v6.8h, v20.8h - mul v7.8h, v7.8h, v21.8h + mul v6.4h, v6.4h, v20.4h + mul v7.4h, v7.4h, v21.4h ins v6.2d[1], v7.2d[0] add DCT_TABLE, DCT_TABLE, #16 ld1 {v24.4h, v25.4h}, [DCT_TABLE], 16 - mul v10.8h, v10.8h, v24.8h - mul v11.8h, v11.8h, v25.8h + mul v10.4h, v10.4h, v24.4h + mul v11.4h, v11.4h, v25.4h ins v10.2d[1], v11.2d[0] add DCT_TABLE, DCT_TABLE, #16 ld1 {v26.4h, v27.4h}, [DCT_TABLE], 16 - mul v12.8h, v12.8h, v26.8h - mul v13.8h, v13.8h, v27.8h + mul v12.4h, v12.4h, v26.4h + mul v13.4h, v13.4h, v27.4h ins v12.2d[1], v13.2d[0] add DCT_TABLE, DCT_TABLE, #16 ld1 {v30.4h, v31.4h}, [DCT_TABLE], 16 - mul v16.8h, v16.8h, v30.8h - mul v17.8h, v17.8h, v31.8h + mul v16.4h, v16.4h, v30.4h + mul v17.4h, v17.4h, v31.4h ins v16.2d[1], v17.2d[0] /* Pass 1 */ @@ -1423,26 +1427,30 @@ asm_function jsimd_idct_2x2_neon idct_helper v5.4h, v7.4h, v11.4h, v13.4h, v17.4h, 13, v5.4h, v7.4h transpose_4x4 v5.4h, v7.4h, v9.4h, v11.4h #else - smull v26.4s, v6.4h, v0.4h[3] - smlal v26.4s, v10.4h, v0.4h[2] - smlal v26.4s, v12.4h, v0.4h[1] - smlal v26.4s, v16.4h, v0.4h[0] - smull v24.4s, v7.4h, v0.4h[3] - smlal v24.4s, v11.4h, v0.4h[2] - smlal v24.4s, v13.4h, v0.4h[1] - smlal v24.4s, v17.4h, v0.4h[0] - sshll v28.4s, v4.4h, #15 + smull v26.4s, v6.4h, v14.4h[3] + smlal v26.4s, v10.4h, v14.4h[2] + smlal v26.4s, v12.4h, v14.4h[1] + smlal v26.4s, v16.4h, v14.4h[0] + smull v24.4s, v7.4h, v14.4h[3] + smlal v24.4s, v11.4h, v14.4h[2] + smlal v24.4s, v13.4h, v14.4h[1] + smlal v24.4s, v17.4h, v14.4h[0] + sshll v15.4s, v4.4h, #15 sshll v30.4s, v5.4h, #15 - add v20.4s, v28.4s, v26.4s - sub v28.4s, v28.4s, v26.4s + add v20.4s, v15.4s, v26.4s + sub v15.4s, v15.4s, v26.4s rshrn v4.4h, v20.4s, #13 - rshrn v6.4h, v28.4s, #13 + rshrn v6.4h, v15.4s, #13 add v20.4s, v30.4s, v24.4s - sub v28.4s, v30.4s, v24.4s + sub v15.4s, v30.4s, v24.4s rshrn v5.4h, v20.4s, #13 - rshrn v7.4h, v28.4s, #13 + rshrn v7.4h, v15.4s, #13 + ins v4.2d[1], v5.2d[0] + ins v6.2d[1], v7.2d[0] transpose v4, v6, v3, .16b, .8h transpose v6, v10, v3, .16b, .4s + ins v11.2d[0], v10.2d[1] + ins v7.2d[0], v6.2d[1] #endif /* Pass 2 */ @@ -1466,11 +1474,15 @@ asm_function jsimd_idct_2x2_neon st1 {v26.b}[1], [TMP2], 1 st1 {v27.b}[5], [TMP2], 1 - /* vpop {v8.4h-v15.4h} ;not available */ - - ld1 {v12.4h-v15.4h}, [sp], 32 - ld1 {v8.4h-v11.4h}, [sp], 32 - + sub sp, sp, #208 + ldr x15, [sp], 16 + ld1 {v4.8b - v7.8b}, [sp], 32 + ld1 {v8.8b - v11.8b}, [sp], 32 + ld1 {v12.8b - v15.8b}, [sp], 32 + ld1 {v16.8b - v19.8b}, [sp], 32 + ld1 {v21.8b - v22.8b}, [sp], 16 + ld1 {v24.8b - v27.8b}, [sp], 32 + ld1 {v30.8b - v31.8b}, [sp], 16 blr x30 .unreq DCT_TABLE @@ -1479,7 +1491,6 @@ asm_function jsimd_idct_2x2_neon .unreq OUTPUT_COL .unreq TMP1 .unreq TMP2 -.endfunc .purgem idct_helper @@ -1507,11 +1518,11 @@ asm_function jsimd_idct_2x2_neon prfm PLDL1KEEP, [V, #64] prfm PLDL1KEEP, [Y, #64] .elseif \size == 4 - ld1 {v4.b}[0], [U] - ld1 {v4.b}[1], [U] - ld1 {v4.b}[2], [U] - ld1 {v4.b}[3], [U] - ld1 {v5.b}[0], [V] + ld1 {v4.b}[0], [U], 1 + ld1 {v4.b}[1], [U], 1 + ld1 {v4.b}[2], [U], 1 + ld1 {v4.b}[3], [U], 1 + ld1 {v5.b}[0], [V], 1 ld1 {v5.b}[1], [V], 1 ld1 {v5.b}[2], [V], 1 ld1 {v5.b}[3], [V], 1 @@ -1546,7 +1557,7 @@ asm_function jsimd_idct_2x2_neon st3 {v10.b, v11.b, v12.b}[3], [RGB], 3 .elseif \size == 2 st3 {v10.b, v11.b, v12.b}[4], [RGB], 3 - st3 {v10.b, v11.b, v12.b}[4], [RGB], 3 + st3 {v10.b, v11.b, v12.b}[5], [RGB], 3 .elseif \size == 1 st3 {v10.b, v11.b, v12.b}[6], [RGB], 3 .else @@ -1568,17 +1579,28 @@ asm_function jsimd_idct_2x2_neon .else .error unsupported macroblock size .endif - .else + .elseif \bpp==16 + .if \size == 8 + st1 {v25.8h}, [RGB],16 + .elseif \size == 4 + st1 {v25.4h}, [RGB],8 + .elseif \size == 2 + st1 {v25.h}[4], [RGB],2 + st1 {v25.h}[5], [RGB],2 + .elseif \size == 1 + st1 {v25.h}[6], [RGB],2 + .else + .error unsupported macroblock size + .endif + .else .error unsupported bpp .endif .endm -#ifdef RTSM_SQSHRN_SIM_ISSUE + .macro generate_jsimd_ycc_rgb_convert_neon colorid, bpp, r_offs, rsize, g_offs, gsize, b_offs, bsize, defsize -#else -.macro generate_jsimd_ycc_rgb_convert_neon colorid, bpp, r_offs, rsize, g_offs, gsize, b_offs, bsize -#endif + /* - * 2 stage pipelined YCbCr->RGB conversion + * 2-stage pipelined YCbCr->RGB conversion */ .macro do_yuv_to_rgb_stage1 @@ -1604,58 +1626,68 @@ asm_function jsimd_idct_2x2_neon uaddw v20.8h, v20.8h, v0.8b uaddw v24.8h, v24.8h, v0.8b uaddw v28.8h, v28.8h, v0.8b -#ifdef RTSM_SQSHRN_SIM_ISSUE +.if \bpp != 16 sqxtun v1\g_offs\defsize, v20.8h sqxtun v1\r_offs\defsize, v24.8h sqxtun v1\b_offs\defsize, v28.8h +.else + sqshlu v21.8h, v20.8h, #8 + sqshlu v25.8h, v24.8h, #8 + sqshlu v29.8h, v28.8h, #8 + sri v25.8h, v21.8h, #5 + sri v25.8h, v29.8h, #11 +.endif -#else - sqxtun v1\g_offs\gsize, v20.4s - sqxtun v1\r_offs\rsize, v24.4s - sqxtun v1\b_offs\bsize, v28.4s -#endif .endm .macro do_yuv_to_rgb_stage2_store_load_stage1 - ld1 {v4.8b}, [U], 8 rshrn v20.4h, v20.4s, #15 - rshrn2 v20.8h, v22.4s, #15 rshrn v24.4h, v24.4s, #14 - rshrn2 v24.8h, v26.4s, #14 rshrn v28.4h, v28.4s, #14 - ld1 {v5.8b}, [V], 8 + ld1 {v4.8b}, [U], 8 + rshrn2 v20.8h, v22.4s, #15 + rshrn2 v24.8h, v26.4s, #14 rshrn2 v28.8h, v30.4s, #14 + ld1 {v5.8b}, [V], 8 uaddw v20.8h, v20.8h, v0.8b uaddw v24.8h, v24.8h, v0.8b uaddw v28.8h, v28.8h, v0.8b -#ifdef RTSM_SQSHRN_SIM_ISSUE +.if \bpp != 16 /**************** rgb24/rgb32 *********************************/ sqxtun v1\g_offs\defsize, v20.8h -#else - sqxtun v1\g_offs\gsize, v20.4s -#endif ld1 {v0.8b}, [Y], 8 -#ifdef RTSM_SQSHRN_SIM_ISSUE sqxtun v1\r_offs\defsize, v24.8h -#else - sqxtun v1\r_offs\rsize, v24.4s -#endif prfm PLDL1KEEP, [U, #64] prfm PLDL1KEEP, [V, #64] prfm PLDL1KEEP, [Y, #64] -#ifdef RTSM_SQSHRN_SIM_ISSUE sqxtun v1\b_offs\defsize, v28.8h -#else - sqxtun v1\b_offs\gsize, v28.4s -#endif uaddw v6.8h, v2.8h, v4.8b /* v6.16b = u - 128 */ uaddw v8.8h, v2.8h, v5.8b /* q2 = v - 128 */ - do_store \bpp, 8 smull v20.4s, v6.4h, v1.4h[1] /* multiply by -11277 */ smlal v20.4s, v8.4h, v1.4h[2] /* multiply by -23401 */ smull2 v22.4s, v6.8h, v1.4h[1] /* multiply by -11277 */ smlal2 v22.4s, v8.8h, v1.4h[2] /* multiply by -23401 */ smull v24.4s, v8.4h, v1.4h[0] /* multiply by 22971 */ smull2 v26.4s, v8.8h, v1.4h[0] /* multiply by 22971 */ +.else /**************************** rgb565 ***********************************/ + sqshlu v21.8h, v20.8h, #8 + sqshlu v25.8h, v24.8h, #8 + sqshlu v29.8h, v28.8h, #8 + uaddw v6.8h, v2.8h, v4.8b /* v6.16b = u - 128 */ + uaddw v8.8h, v2.8h, v5.8b /* q2 = v - 128 */ + ld1 {v0.8b}, [Y], 8 + smull v20.4s, v6.4h, v1.4h[1] /* multiply by -11277 */ + smlal v20.4s, v8.4h, v1.4h[2] /* multiply by -23401 */ + smull2 v22.4s, v6.8h, v1.4h[1] /* multiply by -11277 */ + smlal2 v22.4s, v8.8h, v1.4h[2] /* multiply by -23401 */ + sri v25.8h, v21.8h, #5 + smull v24.4s, v8.4h, v1.4h[0] /* multiply by 22971 */ + smull2 v26.4s, v8.8h, v1.4h[0] /* multiply by 22971 */ + prfm PLDL1KEEP, [U, #64] + prfm PLDL1KEEP, [V, #64] + prfm PLDL1KEEP, [Y, #64] + sri v25.8h, v29.8h, #11 +.endif + do_store \bpp, 8 smull v28.4s, v6.4h, v1.4h[3] /* multiply by 29033 */ smull2 v30.4s, v6.8h, v1.4h[3] /* multiply by 29033 */ .endm @@ -1693,32 +1725,36 @@ asm_function jsimd_ycc_\colorid\()_convert_neon V .req x10 N .req x15 + sub sp, sp, 336 + str x15, [sp], 16 /* Load constants to d1, d2, d3 (v0.4h is just used for padding) */ adr x15, jsimd_ycc_\colorid\()_neon_consts + /* Save NEON registers */ + st1 {v0.8b - v3.8b}, [sp], 32 + st1 {v4.8b - v7.8b}, [sp], 32 + st1 {v8.8b - v11.8b}, [sp], 32 + st1 {v12.8b - v15.8b}, [sp], 32 + st1 {v16.8b - v19.8b}, [sp], 32 + st1 {v20.8b - v23.8b}, [sp], 32 + st1 {v24.8b - v27.8b}, [sp], 32 + st1 {v28.8b - v31.8b}, [sp], 32 ld1 {v0.4h, v1.4h}, [x15], 16 ld1 {v2.8h}, [x15] /* Save ARM registers and handle input arguments */ /* push {x4, x5, x6, x7, x8, x9, x10, x30} */ - stp x4, x5, [sp,-16]! - stp x6, x7, [sp,-16]! - stp x8, x9, [sp,-16]! - stp x10, x30, [sp,-16]! + stp x4, x5, [sp], 16 + stp x6, x7, [sp], 16 + stp x8, x9, [sp], 16 + stp x10, x30, [sp], 16 ldr INPUT_BUF0, [INPUT_BUF] ldr INPUT_BUF1, [INPUT_BUF, 8] ldr INPUT_BUF2, [INPUT_BUF, 16] .unreq INPUT_BUF - /* Save NEON registers */ - /* vpush {v8.4h-v15.4h} */ - sub sp, sp, #32 - st1 {v8.4h-v11.4h}, [sp] - sub sp, sp, #32 - st1 {v12.4h-v15.4h}, [sp] - /* Initially set v10, v11.4h, v12.8b, d13 to 0xFF */ movi v10.16b, #255 - movi v12.16b, #255 + movi v13.16b, #255 /* Outer loop over scanlines */ cmp NUM_ROWS, #1 @@ -1778,14 +1814,21 @@ asm_function jsimd_ycc_\colorid\()_convert_neon bgt 0b 9: /* Restore all registers and return */ - /* vpop {v8.4h-v15.4h} */ - ld1 {v12.4h-v15.4h}, [sp], #32 - ld1 {v8.4h-v11.4h}, [sp], #32 + sub sp, sp, #336 + ldr x15, [sp], 16 + ld1 {v0.8b - v3.8b}, [sp], 32 + ld1 {v4.8b - v7.8b}, [sp], 32 + ld1 {v8.8b - v11.8b}, [sp], 32 + ld1 {v12.8b - v15.8b}, [sp], 32 + ld1 {v16.8b - v19.8b}, [sp], 32 + ld1 {v20.8b - v23.8b}, [sp], 32 + ld1 {v24.8b - v27.8b}, [sp], 32 + ld1 {v28.8b - v31.8b}, [sp], 32 /* pop {r4, r5, r6, r7, r8, r9, r10, pc} */ - ldp x10, x30, [sp], #16 - ldp x8, x9, [sp], #16 - ldp x6, x5, [sp], #16 - ldp x4, x5, [sp], #16 + ldp x4, x5, [sp], 16 + ldp x6, x7, [sp], 16 + ldp x8, x9, [sp], 16 + ldp x10, x30, [sp], 16 br x30 .unreq OUTPUT_WIDTH .unreq INPUT_ROW @@ -1799,7 +1842,6 @@ asm_function jsimd_ycc_\colorid\()_convert_neon .unreq U .unreq V .unreq N -.endfunc .purgem do_yuv_to_rgb .purgem do_yuv_to_rgb_stage1 @@ -1807,10 +1849,6 @@ asm_function jsimd_ycc_\colorid\()_convert_neon .purgem do_yuv_to_rgb_stage2_store_load_stage1 .endm -/* RTSM simulator fix integer saturation works on 8b boundry add a new parameter - * as a workaround for the simulator fix - */ -#ifdef RTSM_SQSHRN_SIM_ISSUE /*--------------------------------- id ----- bpp R rsize G gsize B bsize defsize */ generate_jsimd_ycc_rgb_convert_neon extrgb, 24, 0, .4h, 1, .4h, 2, .4h, .8b generate_jsimd_ycc_rgb_convert_neon extbgr, 24, 2, .4h, 1, .4h, 0, .4h, .8b @@ -1818,15 +1856,6 @@ generate_jsimd_ycc_rgb_convert_neon extrgbx, 32, 0, .4h, 1, .4h, 2, .4h, . generate_jsimd_ycc_rgb_convert_neon extbgrx, 32, 2, .4h, 1, .4h, 0, .4h, .8b generate_jsimd_ycc_rgb_convert_neon extxbgr, 32, 3, .4h, 2, .4h, 1, .4h, .8b generate_jsimd_ycc_rgb_convert_neon extxrgb, 32, 1, .4h, 2, .4h, 3, .4h, .8b -#else -/*--------------------------------- id ----- bpp R rsize G gsize B bsize */ -generate_jsimd_ycc_rgb_convert_neon extrgb, 24, 0, .4h, 1, .4h, 2, .4h -generate_jsimd_ycc_rgb_convert_neon extbgr, 24, 2, .4h, 1, .4h, 0, .4h -generate_jsimd_ycc_rgb_convert_neon extrgbx, 32, 0, .4h, 1, .4h, 2, .4h -generate_jsimd_ycc_rgb_convert_neon extbgrx, 32, 2, .4h, 1, .4h, 0, .4h -generate_jsimd_ycc_rgb_convert_neon extxbgr, 32, 3, .4h, 2, .4h, 1, .4h -generate_jsimd_ycc_rgb_convert_neon extxrgb, 32, 1, .4h, 2, .4h, 3, .4h -#endif - +generate_jsimd_ycc_rgb_convert_neon rgb565, 16, 0, .4h, 0, .4h, 0, .4h, .8b .purgem do_load .purgem do_store diff --git a/simd/jsimd_arm_neon.S b/simd/jsimd_arm_neon.S index 44c61fdd..4d9685b0 100644 --- a/simd/jsimd_arm_neon.S +++ b/simd/jsimd_arm_neon.S @@ -4,6 +4,8 @@ * Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). * All rights reserved. * Author: Siarhei Siamashka + * Copyright (C) 2014 Siarhei Siamashka. All Rights Reserved. + * Copyright (C) 2014 Linaro Limited. All Rights Reserved. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -1346,6 +1348,19 @@ asm_function jsimd_idct_2x2_neon .else .error unsupported macroblock size .endif + .elseif \bpp == 16 + .if \size == 8 + vst1.16 {q15}, [RGB]! + .elseif \size == 4 + vst1.16 {d30}, [RGB]! + .elseif \size == 2 + vst1.16 {d31[0]}, [RGB]! + vst1.16 {d31[1]}, [RGB]! + .elseif \size == 1 + vst1.16 {d31[2]}, [RGB]! + .else + .error unsupported macroblock size + .endif .else .error unsupported bpp .endif @@ -1377,44 +1392,71 @@ asm_function jsimd_idct_2x2_neon vrshrn.s32 d25, q13, #14 vrshrn.s32 d28, q14, #14 vrshrn.s32 d29, q15, #14 - vaddw.u8 q10, q10, d0 + vaddw.u8 q11, q10, d0 vaddw.u8 q12, q12, d0 vaddw.u8 q14, q14, d0 - vqmovun.s16 d1\g_offs, q10 +.if \bpp != 16 + vqmovun.s16 d1\g_offs, q11 vqmovun.s16 d1\r_offs, q12 vqmovun.s16 d1\b_offs, q14 +.else /* rgb565 */ + vqshlu.s16 q13, q11, #8 + vqshlu.s16 q15, q12, #8 + vqshlu.s16 q14, q14, #8 + vsri.u16 q15, q13, #5 + vsri.u16 q15, q14, #11 +.endif .endm .macro do_yuv_to_rgb_stage2_store_load_stage1 - vld1.8 {d4}, [U, :64]! - vrshrn.s32 d20, q10, #15 - vrshrn.s32 d21, q11, #15 - vrshrn.s32 d24, q12, #14 - vrshrn.s32 d25, q13, #14 - vrshrn.s32 d28, q14, #14 - vld1.8 {d5}, [V, :64]! - vrshrn.s32 d29, q15, #14 - vaddw.u8 q10, q10, d0 - vaddw.u8 q12, q12, d0 - vaddw.u8 q14, q14, d0 - vqmovun.s16 d1\g_offs, q10 - vld1.8 {d0}, [Y, :64]! - vqmovun.s16 d1\r_offs, q12 + /* "do_yuv_to_rgb_stage2" and "store" */ + vrshrn.s32 d20, q10, #15 + /* "load" and "do_yuv_to_rgb_stage1" */ pld [U, #64] + vrshrn.s32 d21, q11, #15 pld [V, #64] - pld [Y, #64] - vqmovun.s16 d1\b_offs, q14 + vrshrn.s32 d24, q12, #14 + vrshrn.s32 d25, q13, #14 + vld1.8 {d4}, [U, :64]! + vrshrn.s32 d28, q14, #14 + vld1.8 {d5}, [V, :64]! + vrshrn.s32 d29, q15, #14 vaddw.u8 q3, q1, d4 /* q3 = u - 128 */ vaddw.u8 q4, q1, d5 /* q2 = v - 128 */ - do_store \bpp, 8 + vaddw.u8 q11, q10, d0 vmull.s16 q10, d6, d1[1] /* multiply by -11277 */ vmlal.s16 q10, d8, d1[2] /* multiply by -23401 */ + vaddw.u8 q12, q12, d0 + vaddw.u8 q14, q14, d0 +.if \bpp != 16 /**************** rgb24/rgb32 *********************************/ + vqmovun.s16 d1\g_offs, q11 + pld [Y, #64] + vqmovun.s16 d1\r_offs, q12 + vld1.8 {d0}, [Y, :64]! + vqmovun.s16 d1\b_offs, q14 vmull.s16 q11, d7, d1[1] /* multiply by -11277 */ vmlal.s16 q11, d9, d1[2] /* multiply by -23401 */ + do_store \bpp, 8 vmull.s16 q12, d8, d1[0] /* multiply by 22971 */ vmull.s16 q13, d9, d1[0] /* multiply by 22971 */ vmull.s16 q14, d6, d1[3] /* multiply by 29033 */ vmull.s16 q15, d7, d1[3] /* multiply by 29033 */ +.else /**************************** rgb565 ***********************************/ + vqshlu.s16 q13, q11, #8 + pld [Y, #64] + vqshlu.s16 q15, q12, #8 + vqshlu.s16 q14, q14, #8 + vld1.8 {d0}, [Y, :64]! + vmull.s16 q11, d7, d1[1] + vmlal.s16 q11, d9, d1[2] + vsri.u16 q15, q13, #5 + vmull.s16 q12, d8, d1[0] + vsri.u16 q15, q14, #11 + vmull.s16 q13, d9, d1[0] + vmull.s16 q14, d6, d1[3] + do_store \bpp, 8 + vmull.s16 q15, d7, d1[3] +.endif .endm .macro do_yuv_to_rgb @@ -1556,6 +1598,7 @@ generate_jsimd_ycc_rgb_convert_neon extrgbx, 32, 0, 1, 2 generate_jsimd_ycc_rgb_convert_neon extbgrx, 32, 2, 1, 0 generate_jsimd_ycc_rgb_convert_neon extxbgr, 32, 3, 2, 1 generate_jsimd_ycc_rgb_convert_neon extxrgb, 32, 1, 2, 3 +generate_jsimd_ycc_rgb_convert_neon rgb565, 16, 0, 0, 0 .purgem do_load .purgem do_store diff --git a/simd/jsimd_i386.c b/simd/jsimd_i386.c index c173e740..25d06974 100644 --- a/simd/jsimd_i386.c +++ b/simd/jsimd_i386.c @@ -2,7 +2,7 @@ * jsimd_i386.c * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright 2009-2011, 2013 D. R. Commander + * Copyright 2009-2011, 2013-2014 D. R. Commander * * Based on the x86 SIMD extension for IJG JPEG library, * Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -130,6 +130,12 @@ jsimd_can_ycc_rgb (void) return 0; } +GLOBAL(int) +jsimd_can_ycc_rgb565 (void) +{ + return 0; +} + GLOBAL(void) jsimd_rgb_ycc_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, @@ -280,6 +286,13 @@ jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, mmxfct(cinfo->output_width, input_buf, input_row, output_buf, num_rows); } +GLOBAL(void) +jsimd_ycc_rgb565_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ +} + GLOBAL(int) jsimd_can_h2v2_downsample (void) { diff --git a/simd/jsimd_mips.c b/simd/jsimd_mips.c index e95023a2..abcd19f5 100644 --- a/simd/jsimd_mips.c +++ b/simd/jsimd_mips.c @@ -2,7 +2,7 @@ * jsimd_mips.c * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright 2009-2011 D. R. Commander + * Copyright 2009-2011, 2014 D. R. Commander * Copyright (C) 2013-2014, MIPS Technologies, Inc., California * * Based on the x86 SIMD extension for IJG JPEG library, @@ -161,6 +161,12 @@ jsimd_can_ycc_rgb (void) return 0; } +GLOBAL(int) +jsimd_can_ycc_rgb565 (void) +{ + return 0; +} + GLOBAL(int) jsimd_c_can_null_convert (void) { @@ -299,6 +305,13 @@ jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, num_rows); } +GLOBAL(void) +jsimd_ycc_rgb565_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ +} + GLOBAL(void) jsimd_c_null_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, diff --git a/simd/jsimd_x86_64.c b/simd/jsimd_x86_64.c index 87c9d56f..2c47a7f3 100644 --- a/simd/jsimd_x86_64.c +++ b/simd/jsimd_x86_64.c @@ -2,7 +2,7 @@ * jsimd_x86_64.c * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright 2009-2011 D. R. Commander + * Copyright 2009-2011, 2014 D. R. Commander * * Based on the x86 SIMD extension for IJG JPEG library, * Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -80,6 +80,12 @@ jsimd_can_ycc_rgb (void) return 1; } +GLOBAL(int) +jsimd_can_ycc_rgb565 (void) +{ + return 0; +} + GLOBAL(void) jsimd_rgb_ycc_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, @@ -194,6 +200,13 @@ jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, sse2fct(cinfo->output_width, input_buf, input_row, output_buf, num_rows); } +GLOBAL(void) +jsimd_ycc_rgb565_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ +} + GLOBAL(int) jsimd_can_h2v2_downsample (void) { diff --git a/simd/jsimdext.inc b/simd/jsimdext.inc index 0f1a8dac..e1442de1 100644 --- a/simd/jsimdext.inc +++ b/simd/jsimdext.inc @@ -65,8 +65,8 @@ ; -- segment definition -- ; -%define SEG_TEXT .text align=16 public use32 class=CODE -%define SEG_CONST .data align=16 public use32 class=DATA +%define SEG_TEXT _text align=16 public use32 class=CODE +%define SEG_CONST _data align=16 public use32 class=DATA %elifdef ELF ; ----(nasm -felf[64] -DELF ...)------------ ; * Linux diff --git a/testimages/testorig12.jpg b/testimages/testorig12.jpg new file mode 100644 index 00000000..861aff98 Binary files /dev/null and b/testimages/testorig12.jpg differ diff --git a/tjbench.c b/tjbench.c index 51efaca4..2a3f9445 100644 --- a/tjbench.c +++ b/tjbench.c @@ -388,7 +388,7 @@ int fullTest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual, if((flags&TJFLAG_NOREALLOC)!=0) for(i=0; iFindClass(env, "java/lang/Exception"); \ if(!_exccls) goto bailout; \ @@ -55,8 +57,46 @@ jfieldID _fid; \ if(!_cls) goto bailout; \ bailif0(_fid=(*env)->GetFieldID(env, _cls, "handle", "J")); \ - handle=(tjhandle)(jlong)(*env)->GetLongField(env, obj, _fid); \ + handle=(tjhandle)(size_t)(*env)->GetLongField(env, obj, _fid); \ +#ifdef _WIN32 +#define setenv(envvar, value, dummy) _putenv_s(envvar, value) +#endif + +#define prop2env(property, envvar) \ +{ \ + if((jName=(*env)->NewStringUTF(env, property))!=NULL \ + && (jValue=(*env)->CallStaticObjectMethod(env, cls, mid, jName))!=NULL) \ + { \ + if((value=(*env)->GetStringUTFChars(env, jValue, 0))!=NULL) \ + { \ + setenv(envvar, value, 1); \ + (*env)->ReleaseStringUTFChars(env, jValue, value); \ + } \ + } \ +} + +int ProcessSystemProperties(JNIEnv *env) +{ + jclass cls; jmethodID mid; + jstring jName, jValue; + const char *value; + + bailif0(cls=(*env)->FindClass(env, "java/lang/System")); + bailif0(mid=(*env)->GetStaticMethodID(env, cls, "getProperty", + "(Ljava/lang/String;)Ljava/lang/String;")); + + prop2env("turbojpeg.optimize", "TJ_OPTIMIZE"); + prop2env("turbojpeg.arithmetic", "TJ_ARITHMETIC"); + prop2env("turbojpeg.restart", "TJ_RESTART"); + prop2env("turbojpeg.progressive", "TJ_PROGRESSIVE"); + return 0; + + bailout: + return -1; +} + +/* TurboJPEG 1.2.x: TJ::bufSize() */ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize (JNIEnv *env, jclass cls, jint width, jint height, jint jpegSubsamp) { @@ -67,6 +107,7 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize return retval; } +/* TurboJPEG 1.4.x: TJ::bufSizeYUV() */ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII (JNIEnv *env, jclass cls, jint width, jint pad, jint height, jint subsamp) { @@ -77,6 +118,7 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII return retval; } +/* TurboJPEG 1.2.x: TJ::bufSizeYUV() */ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__III (JNIEnv *env, jclass cls, jint width, jint height, jint subsamp) { @@ -84,6 +126,42 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__III 4, height, subsamp); } +/* TurboJPEG 1.4.x: TJ::planeSizeYUV() */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeSizeYUV__IIIII + (JNIEnv *env, jclass cls, jint componentID, jint width, jint stride, + jint height, jint subsamp) +{ + jint retval=(jint)tjPlaneSizeYUV(componentID, width, stride, height, + subsamp); + if(retval==-1) _throw(tjGetErrorStr()); + + bailout: + return retval; +} + +/* TurboJPEG 1.4.x: TJ::planeWidth() */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeWidth__III + (JNIEnv *env, jclass cls, jint componentID, jint width, jint subsamp) +{ + jint retval=(jint)tjPlaneWidth(componentID, width, subsamp); + if(retval==-1) _throw(tjGetErrorStr()); + + bailout: + return retval; +} + +/* TurboJPEG 1.4.x: TJ::planeHeight() */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeHeight__III + (JNIEnv *env, jclass cls, jint componentID, jint height, jint subsamp) +{ + jint retval=(jint)tjPlaneHeight(componentID, height, subsamp); + if(retval==-1) _throw(tjGetErrorStr()); + + bailout: + return retval; +} + +/* TurboJPEG 1.2.x: TJCompressor::init() */ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init (JNIEnv *env, jobject obj) { @@ -96,16 +174,16 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init bailif0(cls=(*env)->GetObjectClass(env, obj)); bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J")); - (*env)->SetLongField(env, obj, fid, (jlong)handle); + (*env)->SetLongField(env, obj, fid, (size_t)handle); bailout: return; } -JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII - (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width, - jint pitch, jint height, jint pf, jbyteArray dst, jint jpegSubsamp, - jint jpegQual, jint flags) +static jint TJCompressor_compress + (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y, + jint width, jint pitch, jint height, jint pf, jbyteArray dst, + jint jpegSubsamp, jint jpegQual, jint flags) { tjhandle handle=0; unsigned long jpegSize=0; @@ -121,8 +199,8 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3 _throw("Mismatch between Java and C API"); actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch; - arraySize=(y+height-1)*actualPitch + x+width; - if((*env)->GetArrayLength(env, src)GetArrayLength(env, src)*srcElementSizeGetArrayLength(env, dst)<(jsize)jpegSize) @@ -131,15 +209,12 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3 bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); + if(ProcessSystemProperties(env)<0) goto bailout; + if(tjCompress2(handle, &srcBuf[y*actualPitch + x*tjPixelSize[pf]], width, pitch, height, pf, &jpegBuf, &jpegSize, jpegSubsamp, jpegQual, flags|TJFLAG_NOREALLOC)==-1) - { - (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); - (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); - jpegBuf=srcBuf=NULL; _throw(tjGetErrorStr()); - } bailout: if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); @@ -147,116 +222,251 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3 return (jint)jpegSize; } +/* TurboJPEG 1.3.x: TJCompressor::compress() byte source */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII + (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width, + jint pitch, jint height, jint pf, jbyteArray dst, jint jpegSubsamp, + jint jpegQual, jint flags) +{ + return TJCompressor_compress(env, obj, src, 1, x, y, width, pitch, height, + pf, dst, jpegSubsamp, jpegQual, flags); +} + +/* TurboJPEG 1.2.x: TJCompressor::compress() byte source */ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch, jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual, jint flags) { - return Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII( - env, obj, src, 0, 0, width, pitch, height, pf, dst, jpegSubsamp, jpegQual, - flags); + return TJCompressor_compress(env, obj, src, 1, 0, 0, width, pitch, height, + pf, dst, jpegSubsamp, jpegQual, flags); } +/* TurboJPEG 1.3.x: TJCompressor::compress() int source */ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width, jint stride, jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual, jint flags) { - tjhandle handle=0; - unsigned long jpegSize=0; - jsize arraySize=0, actualStride; - unsigned char *srcBuf=NULL, *jpegBuf=NULL; - - gethandle(); - - if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1 - || stride<0) + if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF) _throw("Invalid argument in compress()"); - if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) - _throw("Mismatch between Java and C API"); if(tjPixelSize[pf]!=sizeof(jint)) _throw("Pixel format must be 32-bit when compressing from an integer buffer."); - actualStride=(stride==0)? width:stride; - arraySize=(y+height-1)*actualStride + x+width; - if((*env)->GetArrayLength(env, src)GetArrayLength(env, dst)<(jsize)jpegSize) - _throw("Destination buffer is not large enough"); - - bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); - bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); - - if(tjCompress2(handle, &srcBuf[(y*actualStride + x)*sizeof(int)], width, - stride*sizeof(jint), height, pf, &jpegBuf, &jpegSize, jpegSubsamp, - jpegQual, flags|TJFLAG_NOREALLOC)==-1) - { - (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); - (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); - jpegBuf=srcBuf=NULL; - _throw(tjGetErrorStr()); - } + return TJCompressor_compress(env, obj, src, sizeof(jint), x, y, width, + stride*sizeof(jint), height, pf, dst, jpegSubsamp, jpegQual, flags); bailout: - if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); - if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); - return (jint)jpegSize; + return 0; } +/* TurboJPEG 1.2.x: TJCompressor::compress() int source */ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIII_3BIII - (JNIEnv *env, jobject obj, jintArray src, jint width, jint pitch, + (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride, jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual, jint flags) { - return Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII( - env, obj, src, 0, 0, width, pitch, height, pf, dst, jpegSubsamp, jpegQual, - flags); + if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF) + _throw("Invalid argument in compress()"); + if(tjPixelSize[pf]!=sizeof(jint)) + _throw("Pixel format must be 32-bit when compressing from an integer buffer."); + + return TJCompressor_compress(env, obj, src, sizeof(jint), 0, 0, width, + stride*sizeof(jint), height, pf, dst, jpegSubsamp, jpegQual, flags); + + bailout: + return 0; } -JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV___3BIIII_3BII - (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pad, jint height, - jint subsamp, jbyteArray dst, jint jpegQual, jint flags) +/* TurboJPEG 1.4.x: TJCompressor::compressFromYUV() */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV___3_3B_3II_3III_3BII + (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets, + jint width, jintArray jSrcStrides, jint height, jint subsamp, + jbyteArray dst, jint jpegQual, jint flags) { tjhandle handle=0; unsigned long jpegSize=0; - jsize arraySize=0; - unsigned char *srcBuf=NULL, *jpegBuf=NULL; + jbyteArray jSrcPlanes[3]={NULL, NULL, NULL}; + unsigned char *srcPlanes[3], *jpegBuf=NULL; + int *srcOffsets=NULL, *srcStrides=NULL; + int nc=(subsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3), i; gethandle(); - arraySize=tjBufSizeYUV2(width, pad, height, subsamp); - if((*env)->GetArrayLength(env, src)=org_libjpegturbo_turbojpeg_TJ_NUMSAMP) + _throw("Invalid argument in compressFromYUV()"); + if(org_libjpegturbo_turbojpeg_TJ_NUMSAMP!=TJ_NUMSAMP) + _throw("Mismatch between Java and C API"); + + if((*env)->GetArrayLength(env, srcobjs)GetArrayLength(env, jSrcOffsets)GetArrayLength(env, jSrcStrides)GetArrayLength(env, dst)<(jsize)jpegSize) _throw("Destination buffer is not large enough"); - bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); + bailif0(srcOffsets=(*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0)); + bailif0(srcStrides=(*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0)); + for(i=0; iGetObjectArrayElement(env, srcobjs, i)); + if((*env)->GetArrayLength(env, jSrcPlanes[i])GetPrimitiveArrayCritical(env, jSrcPlanes[i], + 0)); + srcPlanes[i]=&srcPlanes[i][srcOffsets[i]]; + } bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); - if(tjCompressFromYUV(handle, srcBuf, width, pad, height, subsamp, &jpegBuf, - &jpegSize, jpegQual, flags|TJFLAG_NOREALLOC)==-1) - { - (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); - (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); - jpegBuf=srcBuf=NULL; + if(ProcessSystemProperties(env)<0) goto bailout; + + if(tjCompressFromYUVPlanes(handle, srcPlanes, width, srcStrides, height, + subsamp, &jpegBuf, &jpegSize, jpegQual, flags|TJFLAG_NOREALLOC)==-1) _throw(tjGetErrorStr()); - } bailout: if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); - if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); + for(i=0; iReleasePrimitiveArrayCritical(env, jSrcPlanes[i], srcPlanes[i], + 0); + } + if(srcStrides) + (*env)->ReleasePrimitiveArrayCritical(env, jSrcStrides, srcStrides, 0); + if(srcOffsets) + (*env)->ReleasePrimitiveArrayCritical(env, jSrcOffsets, srcOffsets, 0); return (jint)jpegSize; } -JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIIIII_3BIII - (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width, - jint pitch, jint height, jint pf, jbyteArray dst, jint pad, jint subsamp, - jint flags) +static void TJCompressor_encodeYUV + (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y, + jint width, jint pitch, jint height, jint pf, jobjectArray dstobjs, + jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags) { tjhandle handle=0; - jsize arraySize=0, actualPitch, yuvSize; + jsize arraySize=0, actualPitch; + jbyteArray jDstPlanes[3]={NULL, NULL, NULL}; + unsigned char *srcBuf=NULL, *dstPlanes[3]; + int *dstOffsets=NULL, *dstStrides=NULL; + int nc=(subsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3), i; + + gethandle(); + + if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1 + || pitch<0 || subsamp<0 || subsamp>=org_libjpegturbo_turbojpeg_TJ_NUMSAMP) + _throw("Invalid argument in encodeYUV()"); + if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF + || org_libjpegturbo_turbojpeg_TJ_NUMSAMP!=TJ_NUMSAMP) + _throw("Mismatch between Java and C API"); + + if((*env)->GetArrayLength(env, dstobjs)GetArrayLength(env, jDstOffsets)GetArrayLength(env, jDstStrides)GetArrayLength(env, src)*srcElementSizeGetPrimitiveArrayCritical(env, jDstOffsets, 0)); + bailif0(dstStrides=(*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0)); + for(i=0; iGetObjectArrayElement(env, dstobjs, i)); + if((*env)->GetArrayLength(env, jDstPlanes[i])GetPrimitiveArrayCritical(env, jDstPlanes[i], + 0)); + dstPlanes[i]=&dstPlanes[i][dstOffsets[i]]; + } + bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); + + if(tjEncodeYUVPlanes(handle, &srcBuf[y*actualPitch + x*tjPixelSize[pf]], + width, pitch, height, pf, dstPlanes, dstStrides, subsamp, flags)==-1) + _throw(tjGetErrorStr()); + + bailout: + if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); + for(i=0; iReleasePrimitiveArrayCritical(env, jDstPlanes[i], dstPlanes[i], + 0); + } + if(dstStrides) + (*env)->ReleasePrimitiveArrayCritical(env, jDstStrides, dstStrides, 0); + if(dstOffsets) + (*env)->ReleasePrimitiveArrayCritical(env, jDstOffsets, dstOffsets, 0); + return; +} + +/* TurboJPEG 1.4.x: TJCompressor::encodeYUV() byte source */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIIIII_3_3B_3I_3III + (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width, + jint pitch, jint height, jint pf, jobjectArray dstobjs, + jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags) +{ + TJCompressor_encodeYUV(env, obj, src, 1, x, y, width, pitch, height, pf, + dstobjs, jDstOffsets, jDstStrides, subsamp, flags); +} + +/* TurboJPEG 1.4.x: TJCompressor::encodeYUV() int source */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIIIII_3_3B_3I_3III + (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width, + jint stride, jint height, jint pf, jobjectArray dstobjs, + jintArray jDstOffsets, jintArray jDstStrides, jint subsamp, jint flags) +{ + if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF) + _throw("Invalid argument in encodeYUV()"); + if(tjPixelSize[pf]!=sizeof(jint)) + _throw("Pixel format must be 32-bit when encoding from an integer buffer."); + + TJCompressor_encodeYUV(env, obj, src, sizeof(jint), x, y, width, + stride*sizeof(jint), height, pf, dstobjs, jDstOffsets, jDstStrides, + subsamp, flags); + + bailout: + return; +} + +JNIEXPORT void JNICALL TJCompressor_encodeYUV_12 + (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint width, + jint pitch, jint height, jint pf, jbyteArray dst, jint subsamp, jint flags) +{ + tjhandle handle=0; + jsize arraySize=0; unsigned char *srcBuf=NULL, *dstBuf=NULL; gethandle(); @@ -267,27 +477,19 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___ if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) _throw("Mismatch between Java and C API"); - actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch; - arraySize=(y+height-1)*actualPitch + x+width; - if((*env)->GetArrayLength(env, src)GetArrayLength(env, src)*srcElementSizeGetArrayLength(env, dst)GetArrayLength(env, dst) + <(jsize)tjBufSizeYUV(width, height, subsamp)) _throw("Destination buffer is not large enough"); bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); - if(tjEncodeYUV3(handle, &srcBuf[y*actualPitch + x*tjPixelSize[pf]], width, - pitch, height, pf, dstBuf, pad, subsamp, flags)==-1) - { - (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); - (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); - dstBuf=srcBuf=NULL; + if(tjEncodeYUV2(handle, srcBuf, width, pitch, height, pf, dstBuf, subsamp, + flags)==-1) _throw(tjGetErrorStr()); - } bailout: if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); @@ -295,69 +497,33 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___ return; } +/* TurboJPEG 1.2.x: TJCompressor::encodeYUV() byte source */ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIII_3BII (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch, jint height, jint pf, jbyteArray dst, jint subsamp, jint flags) { - Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIIIII_3BIII( - env, obj, src, 0, 0, width, pitch, height, pf, dst, 4, subsamp, flags); + TJCompressor_encodeYUV_12(env, obj, src, 1, width, pitch, height, pf, dst, + subsamp, flags); } -JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIIIII_3BIII - (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width, - jint stride, jint height, jint pf, jbyteArray dst, jint pad, jint subsamp, - jint flags) +/* TurboJPEG 1.2.x: TJCompressor::encodeYUV() int source */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII + (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride, + jint height, jint pf, jbyteArray dst, jint subsamp, jint flags) { - tjhandle handle=0; - jsize arraySize=0, actualStride, yuvSize; - unsigned char *srcBuf=NULL, *dstBuf=NULL; - - gethandle(); - - if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1 - || stride<0) + if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF) _throw("Invalid argument in encodeYUV()"); - if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) - _throw("Mismatch between Java and C API"); if(tjPixelSize[pf]!=sizeof(jint)) _throw("Pixel format must be 32-bit when encoding from an integer buffer."); - actualStride=(stride==0)? width:stride; - arraySize=(y+height-1)*actualStride + x+width; - if((*env)->GetArrayLength(env, src)GetArrayLength(env, dst)GetPrimitiveArrayCritical(env, src, 0)); - bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); - - if(tjEncodeYUV3(handle, &srcBuf[(y*actualStride + x)*sizeof(int)], width, - stride*sizeof(jint), height, pf, dstBuf, pad, subsamp, flags)==-1) - { - (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); - (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); - dstBuf=srcBuf=NULL; - _throw(tjGetErrorStr()); - } + TJCompressor_encodeYUV_12(env, obj, src, sizeof(jint), width, + stride*sizeof(jint), height, pf, dst, subsamp, flags); bailout: - if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); - if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); return; } -JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII - (JNIEnv *env, jobject obj, jintArray src, jint width, jint pitch, - jint height, jint pf, jbyteArray dst, jint subsamp, jint flags) -{ - Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIIIII_3BIII( - env, obj, src, 0, 0, width, pitch, height, pf, dst, 4, subsamp, flags); -} - +/* TurboJPEG 1.2.x: TJCompressor::destroy() */ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy (JNIEnv *env, jobject obj) { @@ -372,6 +538,7 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy return; } +/* TurboJPEG 1.2.x: TJDecompressor::init() */ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_init (JNIEnv *env, jobject obj) { @@ -383,16 +550,17 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_init bailif0(cls=(*env)->GetObjectClass(env, obj)); bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J")); - (*env)->SetLongField(env, obj, fid, (jlong)handle); + (*env)->SetLongField(env, obj, fid, (size_t)handle); bailout: return; } +/* TurboJPEG 1.2.x: TJDecompressor::getScalingFactors() */ JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors (JNIEnv *env, jclass cls) { - jclass sfcls=NULL; jfieldID fid=0; + jclass sfcls=NULL; jfieldID fid=0; tjscalingfactor *sf=NULL; int n=0, i; jobject sfobj=NULL; jobjectArray sfjava=NULL; @@ -417,6 +585,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFact return sfjava; } +/* TurboJPEG 1.2.x: TJDecompressor::decompressHeader() */ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize) { @@ -433,163 +602,232 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress if(tjDecompressHeader3(handle, jpegBuf, (unsigned long)jpegSize, &width, &height, &jpegSubsamp, &jpegColorspace)==-1) - { - (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); _throw(tjGetErrorStr()); - } + (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); jpegBuf=NULL; - bailif0(_fid=(*env)->GetFieldID(env, _cls, "srcSubsamp", "I")); + bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I")); (*env)->SetIntField(env, obj, _fid, jpegSubsamp); - bailif0(_fid=(*env)->GetFieldID(env, _cls, "srcColorspace", "I")); - (*env)->SetIntField(env, obj, _fid, jpegColorspace); - bailif0(_fid=(*env)->GetFieldID(env, _cls, "srcWidth", "I")); + if((_fid=(*env)->GetFieldID(env, _cls, "jpegColorspace", "I"))==0) + (*env)->ExceptionClear(env); + else + (*env)->SetIntField(env, obj, _fid, jpegColorspace); + bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I")); (*env)->SetIntField(env, obj, _fid, width); - bailif0(_fid=(*env)->GetFieldID(env, _cls, "srcHeight", "I")); + bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I")); (*env)->SetIntField(env, obj, _fid, height); bailout: + if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); return; } +static void TJDecompressor_decompress + (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jarray dst, + jint dstElementSize, jint x, jint y, jint width, jint pitch, jint height, + jint pf, jint flags) +{ + tjhandle handle=0; + jsize arraySize=0, actualPitch; + unsigned char *jpegBuf=NULL, *dstBuf=NULL; + + gethandle(); + + if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF) + _throw("Invalid argument in decompress()"); + if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) + _throw("Mismatch between Java and C API"); + + if((*env)->GetArrayLength(env, src)GetArrayLength(env, dst)*dstElementSizeGetPrimitiveArrayCritical(env, src, 0)); + bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); + + if(tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize, + &dstBuf[y*actualPitch + x*tjPixelSize[pf]], width, pitch, height, pf, + flags)==-1) + _throw(tjGetErrorStr()); + + bailout: + if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); + if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); + return; +} + +/* TurboJPEG 1.3.x: TJDecompressor::decompress() byte destination */ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIIIII (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst, jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags) { - tjhandle handle=0; - jsize arraySize=0, actualPitch; - unsigned char *jpegBuf=NULL, *dstBuf=NULL; - - gethandle(); - - if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF) - _throw("Invalid argument in decompress()"); - if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) - _throw("Mismatch between Java and C API"); - - if((*env)->GetArrayLength(env, src)GetArrayLength(env, dst)GetPrimitiveArrayCritical(env, src, 0)); - bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); - - if(tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize, - &dstBuf[y*actualPitch + x*tjPixelSize[pf]], width, pitch, height, pf, - flags)==-1) - { - (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); - (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); - dstBuf=jpegBuf=NULL; - _throw(tjGetErrorStr()); - } - - bailout: - if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); - if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); - return; + TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, x, y, width, + pitch, height, pf, flags); } +/* TurboJPEG 1.2.x: TJDecompressor::decompress() byte destination */ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst, jint width, jint pitch, jint height, jint pf, jint flags) { - Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIIIII - (env, obj, src, jpegSize, dst, 0, 0, width, pitch, height, pf, flags); + TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, 0, 0, width, + pitch, height, pf, flags); } +/* TurboJPEG 1.3.x: TJDecompressor::decompress() int destination */ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIIIII (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst, jint x, jint y, jint width, jint stride, jint height, jint pf, jint flags) { - tjhandle handle=0; - jsize arraySize=0, actualStride; - unsigned char *jpegBuf=NULL, *dstBuf=NULL; - - gethandle(); - if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF) _throw("Invalid argument in decompress()"); - if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) - _throw("Mismatch between Java and C API"); if(tjPixelSize[pf]!=sizeof(jint)) _throw("Pixel format must be 32-bit when decompressing to an integer buffer."); - if((*env)->GetArrayLength(env, src)GetArrayLength(env, dst)GetPrimitiveArrayCritical(env, src, 0)); - bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); - - if(tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize, - &dstBuf[(y*actualStride + x)*sizeof(int)], width, stride*sizeof(jint), - height, pf, flags)==-1) - { - (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); - (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); - dstBuf=jpegBuf=NULL; - _throw(tjGetErrorStr()); - } + TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), x, y, + width, stride*sizeof(jint), height, pf, flags); bailout: - if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); - if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); return; } +/* TurboJPEG 1.2.x: TJDecompressor::decompress() int destination */ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIII (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst, jint width, jint stride, jint height, jint pf, jint flags) { - Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIIIII - (env, obj, src, jpegSize, dst, 0, 0, width, stride, height, pf, flags); + if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF) + _throw("Invalid argument in decompress()"); + if(tjPixelSize[pf]!=sizeof(jint)) + _throw("Pixel format must be 32-bit when decompressing to an integer buffer."); + + TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), 0, 0, + width, stride*sizeof(jint), height, pf, flags); + + bailout: + return; } -JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BIIII - (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst, - jint desiredWidth, jint pad, jint desiredHeight, jint flags) +/* TurboJPEG 1.4.x: TJDecompressor::decompressToYUV() */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3_3B_3II_3III + (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, + jobjectArray dstobjs, jintArray jDstOffsets, jint desiredWidth, + jintArray jDstStrides, jint desiredHeight, jint flags) { tjhandle handle=0; - unsigned char *jpegBuf=NULL, *dstBuf=NULL; + jbyteArray jDstPlanes[3]={NULL, NULL, NULL}; + unsigned char *jpegBuf=NULL, *dstPlanes[3]; + int *dstOffsets=NULL, *dstStrides=NULL; int jpegSubsamp=-1, jpegWidth=0, jpegHeight=0; - jsize yuvSize; + int nc=0, i, width, height, scaledWidth, scaledHeight, nsf=0; + tjscalingfactor *sf; + gethandle(); if((*env)->GetArrayLength(env, src)GetFieldID(env, _cls, "srcSubsamp", "I")); + bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I")); jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid); - bailif0(_fid=(*env)->GetFieldID(env, _cls, "srcWidth", "I")); + bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I")); jpegWidth=(int)(*env)->GetIntField(env, obj, _fid); - bailif0(_fid=(*env)->GetFieldID(env, _cls, "srcHeight", "I")); + bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I")); jpegHeight=(int)(*env)->GetIntField(env, obj, _fid); - yuvSize=(jsize)tjBufSizeYUV2(desiredWidth==0? jpegWidth:desiredWidth, - pad, desiredHeight==0? jpegHeight:desiredHeight, jpegSubsamp); - if(yuvSize==(unsigned long)-1) + nc=(jpegSubsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3); + + width=desiredWidth; height=desiredHeight; + if(width==0) width=jpegWidth; + if(height==0) height=jpegHeight; + sf=tjGetScalingFactors(&nsf); + if(!sf || nsf<1) _throw(tjGetErrorStr()); - if((*env)->GetArrayLength(env, dst)GetPrimitiveArrayCritical(env, jDstOffsets, 0)); + bailif0(dstStrides=(*env)->GetPrimitiveArrayCritical(env, jDstStrides, 0)); + for(i=0; iGetObjectArrayElement(env, dstobjs, i)); + if((*env)->GetArrayLength(env, jDstPlanes[i])GetPrimitiveArrayCritical(env, jDstPlanes[i], + 0)); + dstPlanes[i]=&dstPlanes[i][dstOffsets[i]]; + } + bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); + + if(tjDecompressToYUVPlanes(handle, jpegBuf, (unsigned long)jpegSize, + dstPlanes, desiredWidth, dstStrides, desiredHeight, flags)==-1) + _throw(tjGetErrorStr()); + + bailout: + if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); + for(i=0; iReleasePrimitiveArrayCritical(env, jDstPlanes[i], dstPlanes[i], + 0); + } + if(dstStrides) + (*env)->ReleasePrimitiveArrayCritical(env, jDstStrides, dstStrides, 0); + if(dstOffsets) + (*env)->ReleasePrimitiveArrayCritical(env, jDstOffsets, dstOffsets, 0); + return; +} + +/* TurboJPEG 1.2.x: TJDecompressor::decompressToYUV() */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BI + (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst, + jint flags) +{ + tjhandle handle=0; + unsigned char *jpegBuf=NULL, *dstBuf=NULL; + int jpegSubsamp=-1, jpegWidth=0, jpegHeight=0; + + gethandle(); + + if((*env)->GetArrayLength(env, src)GetFieldID(env, _cls, "jpegSubsamp", "I")); + jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid); + bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I")); + jpegWidth=(int)(*env)->GetIntField(env, obj, _fid); + bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I")); + jpegHeight=(int)(*env)->GetIntField(env, obj, _fid); + if((*env)->GetArrayLength(env, dst) + <(jsize)tjBufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp)) _throw("Destination buffer is not large enough"); + bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); - if(tjDecompressToYUV2(handle, jpegBuf, (unsigned long)jpegSize, dstBuf, - desiredWidth, pad, desiredHeight, flags)==-1) - { - (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); - (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); - dstBuf=jpegBuf=NULL; + if(tjDecompressToYUV(handle, jpegBuf, (unsigned long)jpegSize, dstBuf, + flags)==-1) _throw(tjGetErrorStr()); - } bailout: if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); @@ -597,102 +835,114 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress return; } -JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BI - (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst, - jint flags) -{ - Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BIIII( - env, obj, src, jpegSize, dst, 0, 4, 0, flags); -} - -JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3BII_3BIIIIIII - (JNIEnv *env, jobject obj, jbyteArray src, jint pad, jint subsamp, - jbyteArray dst, jint x, jint y, jint width, jint pitch, jint height, - jint pf, jint flags) +static void TJDecompressor_decodeYUV + (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets, + jintArray jSrcStrides, jint subsamp, jarray dst, jint dstElementSize, + jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags) { tjhandle handle=0; jsize arraySize=0, actualPitch; - unsigned char *srcBuf=NULL, *dstBuf=NULL; + jbyteArray jSrcPlanes[3]={NULL, NULL, NULL}; + unsigned char *srcPlanes[3], *dstBuf=NULL; + int *srcOffsets=NULL, *srcStrides=NULL; + int nc=(subsamp==org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY? 1:3), i; gethandle(); - if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF) + if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || subsamp<0 + || subsamp>=org_libjpegturbo_turbojpeg_TJ_NUMSAMP) _throw("Invalid argument in decodeYUV()"); - if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) + if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF + || org_libjpegturbo_turbojpeg_TJ_NUMSAMP!=TJ_NUMSAMP) _throw("Mismatch between Java and C API"); - arraySize=tjBufSizeYUV2(width, pad, height, subsamp); - if((*env)->GetArrayLength(env, src)GetArrayLength(env, srcobjs)GetArrayLength(env, jSrcOffsets)GetArrayLength(env, jSrcStrides)GetArrayLength(env, dst)GetArrayLength(env, dst)*dstElementSizeGetPrimitiveArrayCritical(env, src, 0)); + bailif0(srcOffsets=(*env)->GetPrimitiveArrayCritical(env, jSrcOffsets, 0)); + bailif0(srcStrides=(*env)->GetPrimitiveArrayCritical(env, jSrcStrides, 0)); + for(i=0; iGetObjectArrayElement(env, srcobjs, i)); + if((*env)->GetArrayLength(env, jSrcPlanes[i])GetPrimitiveArrayCritical(env, jSrcPlanes[i], + 0)); + srcPlanes[i]=&srcPlanes[i][srcOffsets[i]]; + } bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); - if(tjDecodeYUV(handle, srcBuf, pad, subsamp, + if(tjDecodeYUVPlanes(handle, srcPlanes, srcStrides, subsamp, &dstBuf[y*actualPitch + x*tjPixelSize[pf]], width, pitch, height, pf, flags)==-1) - { - (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); - (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); - dstBuf=srcBuf=NULL; _throw(tjGetErrorStr()); - } bailout: if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); - if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); + for(i=0; iReleasePrimitiveArrayCritical(env, jSrcPlanes[i], srcPlanes[i], + 0); + } + if(srcStrides) + (*env)->ReleasePrimitiveArrayCritical(env, jSrcStrides, srcStrides, 0); + if(srcOffsets) + (*env)->ReleasePrimitiveArrayCritical(env, jSrcOffsets, srcOffsets, 0); return; } -JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3BII_3IIIIIIII - (JNIEnv *env, jobject obj, jbyteArray src, jint pad, jint subsamp, - jintArray dst, jint x, jint y, jint width, jint stride, jint height, - jint pf, jint flags) +/* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() byte destination */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3BIIIIIII + (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets, + jintArray jSrcStrides, jint subsamp, jbyteArray dst, jint x, jint y, + jint width, jint pitch, jint height, jint pf, jint flags) { - tjhandle handle=0; - jsize arraySize=0, actualStride; - unsigned char *srcBuf=NULL, *dstBuf=NULL; - - gethandle(); + TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides, + subsamp, dst, 1, x, y, width, pitch, height, pf, flags); +} +/* TurboJPEG 1.4.x: TJDecompressor::decodeYUV() int destination */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3IIIIIIII + (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets, + jintArray jSrcStrides, jint subsamp, jintArray dst, jint x, jint y, + jint width, jint stride, jint height, jint pf, jint flags) +{ if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF) _throw("Invalid argument in decodeYUV()"); - if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) - _throw("Mismatch between Java and C API"); if(tjPixelSize[pf]!=sizeof(jint)) _throw("Pixel format must be 32-bit when decoding to an integer buffer."); - arraySize=tjBufSizeYUV2(width, pad, height, subsamp); - if((*env)->GetArrayLength(env, src)GetArrayLength(env, dst)GetPrimitiveArrayCritical(env, src, 0)); - bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); - - if(tjDecodeYUV(handle, srcBuf, pad, subsamp, - &dstBuf[(y*actualStride + x)*sizeof(int)], width, stride*sizeof(jint), - height, pf, flags)==-1) - { - (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); - (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); - dstBuf=srcBuf=NULL; - _throw(tjGetErrorStr()); - } + TJDecompressor_decodeYUV(env, obj, srcobjs, jSrcOffsets, jSrcStrides, + subsamp, dst, sizeof(jint), x, y, width, stride*sizeof(jint), height, pf, + flags); bailout: - if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); - if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); return; } +/* TurboJPEG 1.2.x: TJTransformer::init() */ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init (JNIEnv *env, jobject obj) { @@ -704,7 +954,7 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init bailif0(cls=(*env)->GetObjectClass(env, obj)); bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J")); - (*env)->SetLongField(env, obj, fid, (jlong)handle); + (*env)->SetLongField(env, obj, fid, (size_t)handle); bailout: return; @@ -724,20 +974,20 @@ static int JNICustomFilter(short *coeffs, tjregion arrayRegion, JNICustomFilterParams *params=(JNICustomFilterParams *)transform->data; JNIEnv *env=params->env; jobject tobj=params->tobj, cfobj=params->cfobj; - jobject arrayRegionObj, planeRegionObj, bufobj, borobj; + jobject arrayRegionObj, planeRegionObj, bufobj, borobj; jclass cls; jmethodID mid; jfieldID fid; bailif0(bufobj=(*env)->NewDirectByteBuffer(env, coeffs, sizeof(short)*arrayRegion.w*arrayRegion.h)); bailif0(cls=(*env)->FindClass(env, "java/nio/ByteOrder")); - bailif0(mid=(*env)->GetStaticMethodID(env, cls, "nativeOrder", + bailif0(mid=(*env)->GetStaticMethodID(env, cls, "nativeOrder", "()Ljava/nio/ByteOrder;")); bailif0(borobj=(*env)->CallStaticObjectMethod(env, cls, mid)); bailif0(cls=(*env)->GetObjectClass(env, bufobj)); bailif0(mid=(*env)->GetMethodID(env, cls, "order", "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;")); (*env)->CallObjectMethod(env, bufobj, mid, borobj); - bailif0(mid=(*env)->GetMethodID(env, cls, "asShortBuffer", + bailif0(mid=(*env)->GetMethodID(env, cls, "asShortBuffer", "()Ljava/nio/ShortBuffer;")); bailif0(bufobj=(*env)->CallObjectMethod(env, bufobj, mid)); @@ -774,6 +1024,7 @@ static int JNICustomFilter(short *coeffs, tjregion arrayRegion, return -1; } +/* TurboJPEG 1.2.x: TJTransformer::transform() */ JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transform (JNIEnv *env, jobject obj, jbyteArray jsrcBuf, jint jpegSize, jobjectArray dstobjs, jobjectArray tobjs, jint flags) @@ -790,11 +1041,11 @@ JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transf if((*env)->GetArrayLength(env, jsrcBuf)GetFieldID(env, _cls, "srcWidth", "I")); + bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I")); jpegWidth=(int)(*env)->GetIntField(env, obj, _fid); - bailif0(_fid=(*env)->GetFieldID(env, _cls, "srcHeight", "I")); + bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I")); jpegHeight=(int)(*env)->GetIntField(env, obj, _fid); - bailif0(_fid=(*env)->GetFieldID(env, _cls, "srcSubsamp", "I")); + bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I")); jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid); n=(*env)->GetArrayLength(env, dstobjs); @@ -851,7 +1102,6 @@ JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transf } } - bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, jsrcBuf, 0)); for(i=0; iGetArrayLength(env, jdstBufs[i]) GetPrimitiveArrayCritical(env, jdstBufs[i], 0)); } + bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, jsrcBuf, 0)); + for(i=0; iGetPrimitiveArrayCritical(env, jdstBufs[i], 0)); if(tjTransform(handle, jpegBuf, jpegSize, n, dstBufs, dstSizes, t, flags|TJFLAG_NOREALLOC)==-1) - { - (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0); - jpegBuf=NULL; - for(i=0; iReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0); - dstBufs[i]=NULL; - } _throw(tjGetErrorStr()); + + for(i=0; iReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0); + dstBufs[i]=NULL; } + (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0); + jpegBuf=NULL; jdstSizes=(*env)->NewIntArray(env, n); bailif0(dstSizesi=(*env)->GetIntArrayElements(env, jdstSizes, 0)); for(i=0; iReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0); + if(dstSizesi) (*env)->ReleaseIntArrayElements(env, jdstSizes, dstSizesi, 0); if(dstBufs) { for(i=0; iReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0); if(jdstBufs) free(jdstBufs); if(dstSizes) free(dstSizes); - if(dstSizesi) (*env)->ReleaseIntArrayElements(env, jdstSizes, dstSizesi, 0); if(t) free(t); return jdstSizes; } +/* TurboJPEG 1.2.x: TJDecompressor::destroy() */ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy (JNIEnv *env, jobject obj) { diff --git a/turbojpeg-mapfile b/turbojpeg-mapfile index 7d174ca8..bd675519 100755 --- a/turbojpeg-mapfile +++ b/turbojpeg-mapfile @@ -42,8 +42,12 @@ TURBOJPEG_1.4 global: tjBufSizeYUV2; tjCompressFromYUV; + tjCompressFromYUVPlanes; tjDecodeYUV; + tjDecodeYUVPlanes; tjDecompressHeader3; tjDecompressToYUV2; + tjDecompressToYUVPlanes; tjEncodeYUV3; + tjEncodeYUVPlanes; } TURBOJPEG_1.2; diff --git a/turbojpeg-mapfile.jni b/turbojpeg-mapfile.jni index f9fc7e53..3370d1f2 100755 --- a/turbojpeg-mapfile.jni +++ b/turbojpeg-mapfile.jni @@ -68,15 +68,22 @@ TURBOJPEG_1.4 global: tjBufSizeYUV2; tjCompressFromYUV; + tjCompressFromYUVPlanes; tjDecodeYUV; + tjDecodeYUVPlanes; tjDecompressHeader3; tjDecompressToYUV2; + tjDecompressToYUVPlanes; tjEncodeYUV3; + tjEncodeYUVPlanes; Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII; - Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV___3BIIII_3BII; - Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIIIII_3BIII; - Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIIIII_3BIII; - Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BIIII; - Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3BII_3BIIIIIII; - Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3BII_3IIIIIIII; + Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV___3_3B_3II_3III_3BII; + Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIIIII_3_3B_3I_3III; + Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIIIII_3_3B_3I_3III; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3_3B_3II_3III; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3BIIIIIII; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV___3_3B_3I_3II_3IIIIIIII; + Java_org_libjpegturbo_turbojpeg_TJ_planeHeight__III; + Java_org_libjpegturbo_turbojpeg_TJ_planeSizeYUV__IIIII; + Java_org_libjpegturbo_turbojpeg_TJ_planeWidth__III; } TURBOJPEG_1.3; diff --git a/turbojpeg.c b/turbojpeg.c index faec0fa5..657be0b9 100644 --- a/turbojpeg.c +++ b/turbojpeg.c @@ -33,6 +33,7 @@ #include #include +#include #include #define JPEG_INTERNALS #include @@ -86,7 +87,7 @@ typedef struct _tjinstance struct jpeg_compress_struct cinfo; struct jpeg_decompress_struct dinfo; struct my_error_mgr jerr; - int init; + int init, headerRead; } tjinstance; static const int pixelsize[TJ_NUMSAMP]={3, 3, 3, 1, 3, 3}; @@ -163,6 +164,7 @@ static int setCompDefaults(struct jpeg_compress_struct *cinfo, int pixelFormat, int subsamp, int jpegQual, int flags) { int retval=0; + char *env=NULL; switch(pixelFormat) { @@ -206,6 +208,26 @@ static int setCompDefaults(struct jpeg_compress_struct *cinfo, cinfo->input_components=tjPixelSize[pixelFormat]; cinfo->use_moz_defaults = TRUE; jpeg_set_defaults(cinfo); + + if((env=getenv("TJ_OPTIMIZE"))!=NULL && strlen(env)>0 && !strcmp(env, "1")) + cinfo->optimize_coding=TRUE; + if((env=getenv("TJ_ARITHMETIC"))!=NULL && strlen(env)>0 && !strcmp(env, "1")) + cinfo->arith_code=TRUE; + if((env=getenv("TJ_RESTART"))!=NULL && strlen(env)>0) + { + int temp=-1; char tempc=0; + if(sscanf(env, "%d%c", &temp, &tempc)>=1 && temp>=0 && temp<=65535) + { + if(toupper(tempc)=='B') + { + cinfo->restart_interval=temp; + cinfo->restart_in_rows=0; + } + else + cinfo->restart_in_rows=temp; + } + } + if(jpegQual>=0) { jpeg_set_quality(cinfo, jpegQual, TRUE); @@ -586,15 +608,19 @@ DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height) DLLEXPORT unsigned long DLLCALL tjBufSizeYUV2(int width, int pad, int height, int subsamp) { - unsigned long retval=0; - int pw, ph, cw, ch; - if(width<1 || height<1 || pad<1 || !isPow2(pad) || subsamp<0 - || subsamp>=NUMSUBOPT) + int retval=0, nc, i; + + if(subsamp<0 || subsamp>=NUMSUBOPT) _throw("tjBufSizeYUV2(): Invalid argument"); - pw=PAD(width, tjMCUWidth[subsamp]/8); - ph=PAD(height, tjMCUHeight[subsamp]/8); - cw=pw*8/tjMCUWidth[subsamp]; ch=ph*8/tjMCUHeight[subsamp]; - retval=PAD(pw, pad)*ph + (subsamp==TJSAMP_GRAY? 0:PAD(cw, pad)*ch*2); + + nc=(subsamp==TJSAMP_GRAY? 1:3); + for(i=0; i=TJ_NUMSAMP) + _throw("tjPlaneWidth(): Invalid argument"); + nc=(subsamp==TJSAMP_GRAY? 1:3); + if(componentID<0 || componentID>=nc) + _throw("tjPlaneWidth(): Invalid argument"); + + pw=PAD(width, tjMCUWidth[subsamp]/8); + if(componentID==0) + retval=pw; + else + retval=pw*8/tjMCUWidth[subsamp]; + + bailout: + return retval; +} + + +DLLEXPORT int tjPlaneHeight(int componentID, int height, int subsamp) +{ + int ph, nc, retval=0; + + if(height<1 || subsamp<0 || subsamp>=TJ_NUMSAMP) + _throw("tjPlaneHeight(): Invalid argument"); + nc=(subsamp==TJSAMP_GRAY? 1:3); + if(componentID<0 || componentID>=nc) + _throw("tjPlaneHeight(): Invalid argument"); + + ph=PAD(height, tjMCUHeight[subsamp]/8); + if(componentID==0) + retval=ph; + else + retval=ph*8/tjMCUHeight[subsamp]; + + bailout: + return retval; +} + + +DLLEXPORT unsigned long DLLCALL tjPlaneSizeYUV(int componentID, int width, + int stride, int height, int subsamp) +{ + unsigned long retval=0; + int pw, ph; + + if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT) + _throw("tjPlaneSizeYUV(): Invalid argument"); + + pw=tjPlaneWidth(componentID, width, subsamp); + ph=tjPlaneHeight(componentID, height, subsamp); + + if(stride==0) stride=pw; + else stride=abs(stride); + + retval=stride*(ph-1)+pw; + + bailout: + return retval; +} + + DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf, int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf, unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags) @@ -711,17 +801,16 @@ DLLEXPORT int DLLCALL tjCompress(tjhandle handle, unsigned char *srcBuf, } -DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf, - int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf, - int pad, int subsamp, int flags) +DLLEXPORT int DLLCALL tjEncodeYUVPlanes(tjhandle handle, unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, unsigned char **dstPlanes, + int *strides, int subsamp, int flags) { int i, retval=0; JSAMPROW *row_pointer=NULL; JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS]; JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS]; JSAMPROW *outbuf[MAX_COMPONENTS]; - int row, pw, ph, cw[MAX_COMPONENTS], ch[MAX_COMPONENTS]; - JSAMPLE *ptr=dstBuf; - unsigned long yuvsize=0; + int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS]; + JSAMPLE *ptr; jpeg_component_info *compptr; #ifndef JCS_EXTENSIONS unsigned char *rgbBuf=NULL; @@ -736,12 +825,14 @@ DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf, } if((this->init&COMPRESS)==0) - _throw("tjEncodeYUV3(): Instance has not been initialized for compression"); + _throw("tjEncodeYUVPlanes(): Instance has not been initialized for compression"); if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0 - || pixelFormat>=TJ_NUMPF || dstBuf==NULL || pad<0 || !isPow2(pad) - || subsamp<0 || subsamp>=NUMSUBOPT) - _throw("tjEncodeYUV3(): Invalid argument"); + || pixelFormat>=TJ_NUMPF || !dstPlanes || !dstPlanes[0] || subsamp<0 + || subsamp>=NUMSUBOPT) + _throw("tjEncodeYUVPlanes(): Invalid argument"); + if(subsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2])) + _throw("tjEncodeYUVPlanes(): Invalid argument"); if(setjmp(this->jerr.setjmp_buffer)) { @@ -751,7 +842,7 @@ DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf, } if(pixelFormat==TJPF_CMYK) - _throw("tjEncodeYUV3(): Cannot generate YUV images from CMYK pixels"); + _throw("tjEncodeYUVPlanes(): Cannot generate YUV images from CMYK pixels"); if(pitch==0) pitch=width*tjPixelSize[pixelFormat]; @@ -759,7 +850,7 @@ DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf, if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK) { rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE); - if(!rgbBuf) _throw("tjEncodeYUV3(): Memory allocation failure"); + if(!rgbBuf) _throw("tjEncodeYUVPlanes(): Memory allocation failure"); srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf); pitch=width*RGB_PIXELSIZE; } @@ -772,7 +863,6 @@ DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf, else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); - yuvsize=tjBufSizeYUV2(width, pad, height, subsamp); if(setCompDefaults(cinfo, pixelFormat, subsamp, -1, flags)==-1) return -1; /* Execute only the parts of jpeg_start_compress() that we need. If we @@ -780,25 +870,25 @@ DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf, to write the file headers, which could overflow the output buffer if the YUV image were very small. */ if(cinfo->global_state!=CSTATE_START) - _throw("tjEncodeYUV3(): libjpeg API is in the wrong state"); + _throw("tjEncodeYUVPlanes(): libjpeg API is in the wrong state"); (*cinfo->err->reset_error_mgr)((j_common_ptr)cinfo); jinit_c_master_control(cinfo, FALSE); jinit_color_converter(cinfo); jinit_downsampler(cinfo); (*cinfo->cconvert->start_pass)(cinfo); - pw=PAD(width, cinfo->max_h_samp_factor); - ph=PAD(height, cinfo->max_v_samp_factor); + pw0=PAD(width, cinfo->max_h_samp_factor); + ph0=PAD(height, cinfo->max_v_samp_factor); - if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL) - _throw("tjEncodeYUV3(): Memory allocation failure"); + if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL) + _throw("tjEncodeYUVPlanes(): Memory allocation failure"); for(i=0; inum_components; i++) { @@ -806,9 +896,9 @@ DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf, _tmpbuf[i]=(JSAMPLE *)malloc( PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE) /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16); - if(!_tmpbuf[i]) _throw("tjEncodeYUV3(): Memory allocation failure"); + if(!_tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure"); tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor); - if(!tmpbuf[i]) _throw("tjEncodeYUV3(): Memory allocation failure"); + if(!tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure"); for(row=0; rowmax_v_samp_factor; row++) { unsigned char *_tmpbuf_aligned= @@ -819,9 +909,9 @@ DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf, } _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16) * compptr->v_samp_factor + 16); - if(!_tmpbuf2[i]) _throw("tjEncodeYUV3(): Memory allocation failure"); + if(!_tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure"); tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor); - if(!tmpbuf2[i]) _throw("tjEncodeYUV3(): Memory allocation failure"); + if(!tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure"); for(row=0; rowv_samp_factor; row++) { unsigned char *_tmpbuf2_aligned= @@ -829,20 +919,19 @@ DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf, tmpbuf2[i][row]=&_tmpbuf2_aligned[ PAD(compptr->width_in_blocks*DCTSIZE, 16) * row]; } - cw[i]=pw*compptr->h_samp_factor/cinfo->max_h_samp_factor; - ch[i]=ph*compptr->v_samp_factor/cinfo->max_v_samp_factor; - outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]); - if(!outbuf[i]) _throw("tjEncodeYUV3(): Memory allocation failure"); - for(row=0; rowh_samp_factor/cinfo->max_h_samp_factor; + ph[i]=ph0*compptr->v_samp_factor/cinfo->max_v_samp_factor; + outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]); + if(!outbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure"); + ptr=dstPlanes[i]; + for(row=0; rowmax_v_samp_factor) + for(row=0; rowmax_v_samp_factor) { (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0, cinfo->max_v_samp_factor); @@ -850,7 +939,7 @@ DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf, for(i=0, compptr=cinfo->comp_info; inum_components; i++, compptr++) jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i], row*compptr->v_samp_factor/cinfo->max_v_samp_factor, - compptr->v_samp_factor, cw[i]); + compptr->v_samp_factor, pw[i]); } cinfo->next_scanline+=height; jpeg_abort_compress(cinfo); @@ -872,6 +961,42 @@ DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf, return retval; } +DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf, + int pad, int subsamp, int flags) +{ + unsigned char *dstPlanes[3]; + int pw0, ph0, strides[3], retval=-1; + + if(width<=0 || height<=0 || dstBuf==NULL || pad<0 || !isPow2(pad) + || subsamp<0 || subsamp>=NUMSUBOPT) + _throw("tjEncodeYUV3(): Invalid argument"); + + pw0=tjPlaneWidth(0, width, subsamp); + ph0=tjPlaneHeight(0, height, subsamp); + dstPlanes[0]=dstBuf; + strides[0]=PAD(pw0, pad); + if(subsamp==TJSAMP_GRAY) + { + strides[1]=strides[2]=0; + dstPlanes[1]=dstPlanes[2]=NULL; + } + else + { + int pw1=tjPlaneWidth(1, width, subsamp); + int ph1=tjPlaneHeight(1, height, subsamp); + strides[1]=strides[2]=PAD(pw1, pad); + dstPlanes[1]=dstPlanes[0]+strides[0]*ph0; + dstPlanes[2]=dstPlanes[1]+strides[1]*ph1; + } + + return tjEncodeYUVPlanes(handle, srcBuf, width, pitch, height, pixelFormat, + dstPlanes, strides, subsamp, flags); + + bailout: + return retval; +} + DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf, int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf, int subsamp, int flags) @@ -889,14 +1014,14 @@ DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf, } -DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, unsigned char *srcBuf, - int width, int pad, int height, int subsamp, unsigned char **jpegBuf, - unsigned long *jpegSize, int jpegQual, int flags) +DLLEXPORT int DLLCALL tjCompressFromYUVPlanes(tjhandle handle, + unsigned char **srcPlanes, int width, int *strides, int height, int subsamp, + unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual, int flags) { int i, row, retval=0, alloc=1; JSAMPROW *inbuf[MAX_COMPONENTS]; - int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS], + int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS], tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS]; - JSAMPLE *_tmpbuf=NULL, *ptr=srcBuf; JSAMPROW *tmpbuf[MAX_COMPONENTS]; + JSAMPLE *_tmpbuf=NULL, *ptr; JSAMPROW *tmpbuf[MAX_COMPONENTS]; getcinstance(handle) @@ -906,12 +1031,14 @@ DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, unsigned char *srcBuf, } if((this->init&COMPRESS)==0) - _throw("tjCompressFromYUV(): Instance has not been initialized for compression"); + _throw("tjCompressFromYUVPlanes(): Instance has not been initialized for compression"); - if(srcBuf==NULL || width<=0 || pad<1 || height<=0 || subsamp<0 + if(!srcPlanes || !srcPlanes[0] || width<=0 || height<=0 || subsamp<0 || subsamp>=NUMSUBOPT || jpegBuf==NULL || jpegSize==NULL || jpegQual<0 || jpegQual>100) - _throw("tjCompressFromYUV(): Invalid argument"); + _throw("tjCompressFromYUVPlanes(): Invalid argument"); + if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2])) + _throw("tjCompressFromYUVPlanes(): Invalid argument"); if(setjmp(this->jerr.setjmp_buffer)) { @@ -943,30 +1070,31 @@ DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, unsigned char *srcBuf, int ih; iw[i]=compptr->width_in_blocks*DCTSIZE; ih=compptr->height_in_blocks*DCTSIZE; - cw[i]=PAD(cinfo->image_width, cinfo->max_h_samp_factor) + pw[i]=PAD(cinfo->image_width, cinfo->max_h_samp_factor) *compptr->h_samp_factor/cinfo->max_h_samp_factor; - ch[i]=PAD(cinfo->image_height, cinfo->max_v_samp_factor) + ph[i]=PAD(cinfo->image_height, cinfo->max_v_samp_factor) *compptr->v_samp_factor/cinfo->max_v_samp_factor; - if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1; + if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1; th[i]=compptr->v_samp_factor*DCTSIZE; tmpbufsize+=iw[i]*th[i]; - if((inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL) - _throw("tjCompressFromYUV(): Memory allocation failure"); - for(row=0; rownum_components; i++) { if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL) - _throw("tjCompressFromYUV(): Memory allocation failure"); + _throw("tjCompressFromYUVPlanes(): Memory allocation failure"); for(row=0; row=NUMSUBOPT) + _throw("tjCompressFromYUV(): Invalid argument"); + + pw0=tjPlaneWidth(0, width, subsamp); + ph0=tjPlaneHeight(0, height, subsamp); + srcPlanes[0]=srcBuf; + strides[0]=PAD(pw0, pad); + if(subsamp==TJSAMP_GRAY) + { + strides[1]=strides[2]=0; + srcPlanes[1]=srcPlanes[2]=NULL; + } + else + { + int pw1=tjPlaneWidth(1, width, subsamp); + int ph1=tjPlaneHeight(1, height, subsamp); + strides[1]=strides[2]=PAD(pw1, pad); + srcPlanes[1]=srcPlanes[0]+strides[0]*ph0; + srcPlanes[2]=srcPlanes[1]+strides[1]*ph1; + } + + return tjCompressFromYUVPlanes(handle, srcPlanes, width, strides, height, + subsamp, jpegBuf, jpegSize, jpegQual, flags); + + bailout: + return retval; +} + /* Decompressor */ @@ -1303,16 +1467,15 @@ void my_reset_marker_reader(j_decompress_ptr dinfo) { } -DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, unsigned char *srcBuf, - int pad, int subsamp, unsigned char *dstBuf, int width, int pitch, - int height, int pixelFormat, int flags) +DLLEXPORT int DLLCALL tjDecodeYUVPlanes(tjhandle handle, + unsigned char **srcPlanes, int *strides, int subsamp, unsigned char *dstBuf, + int width, int pitch, int height, int pixelFormat, int flags) { int i, retval=0; JSAMPROW *row_pointer=NULL; JSAMPLE *_tmpbuf[MAX_COMPONENTS]; JSAMPROW *tmpbuf[MAX_COMPONENTS], *inbuf[MAX_COMPONENTS]; - int row, pw, ph, cw[MAX_COMPONENTS], ch[MAX_COMPONENTS]; - JSAMPLE *ptr=srcBuf; - unsigned long yuvsize=0; + int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS]; + JSAMPLE *ptr; jpeg_component_info *compptr; #ifndef JCS_EXTENSIONS unsigned char *rgbBuf=NULL; @@ -1329,12 +1492,14 @@ DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, unsigned char *srcBuf, } if((this->init&DECOMPRESS)==0) - _throw("tjDecodeYUV(): Instance has not been initialized for decompression"); + _throw("tjDecodeYUVPlanes(): Instance has not been initialized for decompression"); - if(srcBuf==NULL || pad<0 || !isPow2(pad) || subsamp<0 || subsamp>=NUMSUBOPT + if(!srcPlanes || !srcPlanes[0] || subsamp<0 || subsamp>=NUMSUBOPT || dstBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF) - _throw("tjDecodeYUV(): Invalid argument"); + _throw("tjDecodeYUVPlanes(): Invalid argument"); + if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2])) + _throw("tjDecodeYUVPlanes(): Invalid argument"); if(setjmp(this->jerr.setjmp_buffer)) { @@ -1344,7 +1509,7 @@ DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, unsigned char *srcBuf, } if(pixelFormat==TJPF_CMYK) - _throw("tjDecodeYUV(): Cannot decode YUV images into CMYK pixels."); + _throw("tjDecodeYUVPlanes(): Cannot decode YUV images into CMYK pixels."); if(pitch==0) pitch=width*tjPixelSize[pixelFormat]; dinfo->image_width=width; @@ -1354,7 +1519,6 @@ DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, unsigned char *srcBuf, else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); - yuvsize=tjBufSizeYUV2(width, pad, height, subsamp); if(setDecodeDefaults(dinfo, pixelFormat, subsamp, flags)==-1) { retval=-1; goto bailout; @@ -1375,8 +1539,8 @@ DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, unsigned char *srcBuf, jinit_master_decompress(dinfo); (*dinfo->upsample->start_pass)(dinfo); - pw=PAD(width, dinfo->max_h_samp_factor); - ph=PAD(height, dinfo->max_v_samp_factor); + pw0=PAD(width, dinfo->max_h_samp_factor); + ph0=PAD(height, dinfo->max_v_samp_factor); if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat]; @@ -1388,30 +1552,30 @@ DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, unsigned char *srcBuf, RGB_PIXELSIZE!=tjPixelSize[pixelFormat])) { rgbBuf=(unsigned char *)malloc(width*height*3); - if(!rgbBuf) _throw("tjDecodeYUV(): Memory allocation failure"); + if(!rgbBuf) _throw("tjDecodeYUVPlanes(): Memory allocation failure"); _pitch=pitch; pitch=width*3; _dstBuf=dstBuf; dstBuf=rgbBuf; } #endif - if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL) - _throw("tjDecodeYUV(): Memory allocation failure"); + if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL) + _throw("tjDecodeYUVPlanes(): Memory allocation failure"); for(i=0; inum_components; i++) { compptr=&dinfo->comp_info[i]; _tmpbuf[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16) * compptr->v_samp_factor + 16); - if(!_tmpbuf[i]) _throw("tjDecodeYUV(): Memory allocation failure"); + if(!_tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure"); tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor); - if(!tmpbuf[i]) _throw("tjDecodeYUV(): Memory allocation failure"); + if(!tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure"); for(row=0; rowv_samp_factor; row++) { unsigned char *_tmpbuf_aligned= @@ -1419,27 +1583,25 @@ DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, unsigned char *srcBuf, tmpbuf[i][row]=&_tmpbuf_aligned[ PAD(compptr->width_in_blocks*DCTSIZE, 16) * row]; } - cw[i]=pw*compptr->h_samp_factor/dinfo->max_h_samp_factor; - ch[i]=ph*compptr->v_samp_factor/dinfo->max_v_samp_factor; - inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]); - if(!inbuf[i]) _throw("tjDecodeYUV(): Memory allocation failure"); - for(row=0; rowh_samp_factor/dinfo->max_h_samp_factor; + ph[i]=ph0*compptr->v_samp_factor/dinfo->max_v_samp_factor; + inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]); + if(!inbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure"); + ptr=srcPlanes[i]; + for(row=0; rowmax_v_samp_factor) + for(row=0; rowmax_v_samp_factor) { JDIMENSION inrow=0, outrow=0; for(i=0, compptr=dinfo->comp_info; inum_components; i++, compptr++) jcopy_sample_rows(inbuf[i], row*compptr->v_samp_factor/dinfo->max_v_samp_factor, tmpbuf[i], 0, - compptr->v_samp_factor, cw[i]); + compptr->v_samp_factor, pw[i]); (dinfo->upsample->upsample)(dinfo, tmpbuf, &inrow, dinfo->max_v_samp_factor, &row_pointer[row], &outrow, dinfo->max_v_samp_factor); @@ -1465,16 +1627,51 @@ DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, unsigned char *srcBuf, return retval; } +DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, unsigned char *srcBuf, + int pad, int subsamp, unsigned char *dstBuf, int width, int pitch, + int height, int pixelFormat, int flags) +{ + unsigned char *srcPlanes[3]; + int pw0, ph0, strides[3], retval=-1; -DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle, - unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf, - int width, int pad, int height, int flags) + if(srcBuf==NULL || pad<0 || !isPow2(pad) || subsamp<0 || subsamp>=NUMSUBOPT + || width<=0 || height<=0) + _throw("tjDecodeYUV(): Invalid argument"); + + pw0=tjPlaneWidth(0, width, subsamp); + ph0=tjPlaneHeight(0, height, subsamp); + srcPlanes[0]=srcBuf; + strides[0]=PAD(pw0, pad); + if(subsamp==TJSAMP_GRAY) + { + strides[1]=strides[2]=0; + srcPlanes[1]=srcPlanes[2]=NULL; + } + else + { + int pw1=tjPlaneWidth(1, width, subsamp); + int ph1=tjPlaneHeight(1, height, subsamp); + strides[1]=strides[2]=PAD(pw1, pad); + srcPlanes[1]=srcPlanes[0]+strides[0]*ph0; + srcPlanes[2]=srcPlanes[1]+strides[1]*ph1; + } + + return tjDecodeYUVPlanes(handle, srcPlanes, strides, subsamp, dstBuf, width, + pitch, height, pixelFormat, flags); + + bailout: + return retval; +} + +DLLEXPORT int DLLCALL tjDecompressToYUVPlanes(tjhandle handle, + unsigned char *jpegBuf, unsigned long jpegSize, unsigned char **dstPlanes, + int width, int *strides, int height, int flags) { int i, sfi, row, retval=0; JSAMPROW *outbuf[MAX_COMPONENTS]; int jpegwidth, jpegheight, jpegSubsamp, scaledw, scaledh; - int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS], + int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS], tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS]; - JSAMPLE *_tmpbuf=NULL, *ptr=dstBuf; JSAMPROW *tmpbuf[MAX_COMPONENTS]; + JSAMPLE *_tmpbuf=NULL, *ptr; JSAMPROW *tmpbuf[MAX_COMPONENTS]; int dctsize; getdinstance(handle); @@ -1485,11 +1682,11 @@ DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle, } if((this->init&DECOMPRESS)==0) - _throw("tjDecompressToYUV2(): Instance has not been initialized for decompression"); + _throw("tjDecompressToYUVPlanes(): Instance has not been initialized for decompression"); - if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pad<1 - || !isPow2(pad) || height<0) - _throw("tjDecompressToYUV2(): Invalid argument"); + if(jpegBuf==NULL || jpegSize<=0 || !dstPlanes || !dstPlanes[0] || width<0 + || height<0) + _throw("tjDecompressToYUVPlanes(): Invalid argument"); if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); @@ -1502,11 +1699,18 @@ DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle, goto bailout; } - jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); - jpeg_read_header(dinfo, TRUE); + if(!this->headerRead) + { + jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); + jpeg_read_header(dinfo, TRUE); + } + this->headerRead=0; jpegSubsamp=getSubsamp(dinfo); if(jpegSubsamp<0) - _throw("tjDecompressToYUV2(): Could not determine subsampling type for JPEG image"); + _throw("tjDecompressToYUVPlanes(): Could not determine subsampling type for JPEG image"); + + if(jpegSubsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2])) + _throw("tjDecompressToYUVPlanes(): Invalid argument"); jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height; if(width==0) width=jpegwidth; @@ -1519,9 +1723,9 @@ DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle, break; } if(scaledw>width || scaledh>height) - _throw("tjDecompressToYUV2(): Could not scale down to desired image dimensions"); + _throw("tjDecompressToYUVPlanes(): Could not scale down to desired image dimensions"); if(dinfo->num_components>3) - _throw("tjDecompressToYUV2(): JPEG image must have 3 or fewer components"); + _throw("tjDecompressToYUVPlanes(): JPEG image must have 3 or fewer components"); width=scaledw; height=scaledh; dinfo->scale_num=sf[i].num; @@ -1537,30 +1741,31 @@ DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle, int ih; iw[i]=compptr->width_in_blocks*dctsize; ih=compptr->height_in_blocks*dctsize; - cw[i]=PAD(dinfo->output_width, dinfo->max_h_samp_factor) + pw[i]=PAD(dinfo->output_width, dinfo->max_h_samp_factor) *compptr->h_samp_factor/dinfo->max_h_samp_factor; - ch[i]=PAD(dinfo->output_height, dinfo->max_v_samp_factor) + ph[i]=PAD(dinfo->output_height, dinfo->max_v_samp_factor) *compptr->v_samp_factor/dinfo->max_v_samp_factor; - if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1; + if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1; th[i]=compptr->v_samp_factor*dctsize; tmpbufsize+=iw[i]*th[i]; - if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL) - _throw("tjDecompressToYUV2(): Memory allocation failure"); - for(row=0; rownum_components; i++) { if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL) - _throw("tjDecompressToYUV2(): Memory allocation failure"); + _throw("tjDecompressToYUVPlanes(): Memory allocation failure"); for(row=0; rownum_components; i++) { - for(j=0; jimage_width; jpegheight=dinfo->image_height; + if(width==0) width=jpegwidth; + if(height==0) height=jpegheight; + + for(i=0; iwidth || scaledh>height) + _throw("tjDecompressToYUV2(): Could not scale down to desired image dimensions"); + + pw0=tjPlaneWidth(0, width, jpegSubsamp); + ph0=tjPlaneHeight(0, height, jpegSubsamp); + dstPlanes[0]=dstBuf; + strides[0]=PAD(pw0, pad); + if(jpegSubsamp==TJSAMP_GRAY) + { + strides[1]=strides[2]=0; + dstPlanes[1]=dstPlanes[2]=NULL; + } + else + { + int pw1=tjPlaneWidth(1, width, jpegSubsamp); + int ph1=tjPlaneHeight(1, height, jpegSubsamp); + strides[1]=strides[2]=PAD(pw1, pad); + dstPlanes[1]=dstPlanes[0]+strides[0]*ph0; + dstPlanes[2]=dstPlanes[1]+strides[1]*ph1; + } + + this->headerRead=1; + return tjDecompressToYUVPlanes(handle, jpegBuf, jpegSize, dstPlanes, width, + strides, height, flags); + + bailout: + return retval; + +} + DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle, unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf, int flags) diff --git a/turbojpeg.h b/turbojpeg.h index 818ca6e0..1ada65a2 100644 --- a/turbojpeg.h +++ b/turbojpeg.h @@ -42,6 +42,35 @@ * TurboJPEG API. This API provides an interface for generating, decoding, and * transforming planar YUV and JPEG images in memory. * + * @anchor YUVnotes + * YUV Image Format Notes + * ---------------------- + * Technically, the JPEG format uses the YCbCr colorspace (which is technically + * not a colorspace but a color transform), but per the convention of the + * digital video community, the TurboJPEG API uses "YUV" to refer to an image + * format consisting of Y, Cb, and Cr image planes. + * + * Each plane is simply a 2D array of bytes, each byte representing the value + * of one of the components (Y, Cb, or Cr) at a particular location in the + * image. The width and height of each plane are determined by the image + * width, height, and level of chrominance subsampling. The luminance plane + * width is the image width padded to the nearest multiple of the horizontal + * subsampling factor (2 in the case of 4:2:0 and 4:2:2, 4 in the case of + * 4:1:1, 1 in the case of 4:4:4 or grayscale.) Similarly, the luminance plane + * height is the image height padded to the nearest multiple of the vertical + * subsampling factor (2 in the case of 4:2:0 or 4:4:0, 1 in the case of 4:4:4 + * or grayscale.) This is irrespective of any additional padding that may be + * specified as an argument to the various YUV functions. The chrominance + * plane width is equal to the luminance plane width divided by the horizontal + * subsampling factor, and the chrominance plane height is equal to the + * luminance plane height divided by the vertical subsampling factor. + * + * For example, if the source image is 35 x 35 pixels and 4:2:2 subsampling is + * used, then the luminance plane would be 36 x 35 bytes, and each of the + * chrominance planes would be 18 x 35 bytes. If you specify a line padding of + * 4 bytes on top of this, then the luminance plane would be 36 x 35 bytes, and + * each of the chrominance planes would be 20 x 35 bytes. + * * @{ */ @@ -59,10 +88,6 @@ * to produce a smaller image with little perceptible loss of image clarity * (the human eye is more sensitive to small changes in brightness than to * small changes in color.) This is called "chrominance subsampling". - *

    - * NOTE: Technically, the JPEG format uses the YCbCr colorspace, but per the - * convention of the digital video community, the TurboJPEG API uses "YUV" to - * refer to an image format consisting of Y, Cb, and Cr image planes. */ enum TJSAMP { @@ -89,7 +114,8 @@ enum TJSAMP /** * 4:4:0 chrominance subsampling. The JPEG or YUV image will contain one * chrominance component for every 1x2 block of pixels in the source image. - * Note that 4:4:0 subsampling is not fully accelerated in libjpeg-turbo. + * + * @note 4:4:0 subsampling is not fully accelerated in libjpeg-turbo. */ TJSAMP_440, /** @@ -99,8 +125,9 @@ enum TJSAMP * same size as those compressed with 4:2:0 subsampling, and in the * aggregate, both subsampling methods produce approximately the same * perceptual quality. However, 4:1:1 is better able to reproduce sharp - * horizontal features. Note that 4:1:1 subsampling is not fully accelerated - * in libjpeg-turbo. + * horizontal features. + * + * @note 4:1:1 subsampling is not fully accelerated in libjpeg-turbo. */ TJSAMP_411 }; @@ -521,26 +548,29 @@ typedef struct tjtransform * to be applied in the frequency domain. * * @param coeffs pointer to an array of transformed DCT coefficients. (NOTE: - * this pointer is not guaranteed to be valid once the callback - * returns, so applications wishing to hand off the DCT coefficients - * to another function or library should make a copy of them within - * the body of the callback.) + * this pointer is not guaranteed to be valid once the callback returns, so + * applications wishing to hand off the DCT coefficients to another function + * or library should make a copy of them within the body of the callback.) + * * @param arrayRegion #tjregion structure containing the width and height of - * the array pointed to by coeffs as well as its offset - * relative to the component plane. TurboJPEG implementations may - * choose to split each component plane into multiple DCT coefficient - * arrays and call the callback function once for each array. + * the array pointed to by coeffs as well as its offset relative to + * the component plane. TurboJPEG implementations may choose to split each + * component plane into multiple DCT coefficient arrays and call the callback + * function once for each array. + * * @param planeRegion #tjregion structure containing the width and height of - * the component plane to which coeffs belongs + * the component plane to which coeffs belongs + * * @param componentID ID number of the component plane to which - * coeffs belongs (Y, Cb, and Cr have, respectively, ID's of - * 0, 1, and 2 in typical JPEG images.) + * coeffs belongs (Y, Cb, and Cr have, respectively, ID's of 0, 1, + * and 2 in typical JPEG images.) + * * @param transformID ID number of the transformed image to which - * coeffs belongs. This is the same as the index of the - * transform in the transforms array that was passed to - * #tjTransform(). + * coeffs belongs. This is the same as the index of the transform + * in the transforms array that was passed to #tjTransform(). + * * @param transform a pointer to a #tjtransform structure that specifies the - * parameters and/or cropping region for this transform + * parameters and/or cropping region for this transform * * @return 0 if the callback was successful, or -1 if an error occurred. */ @@ -587,46 +617,58 @@ DLLEXPORT tjhandle DLLCALL tjInitCompress(void); * Compress an RGB, grayscale, or CMYK image into a JPEG image. * * @param handle a handle to a TurboJPEG compressor or transformer instance + * * @param srcBuf pointer to an image buffer containing RGB, grayscale, or - * CMYK pixels to be compressed + * CMYK pixels to be compressed + * * @param width width (in pixels) of the source image - * @param pitch bytes per line of the source image. Normally, this should be - * width * #tjPixelSize[pixelFormat] if the image is unpadded, - * or #TJPAD(width * #tjPixelSize[pixelFormat]) if each line of - * the image is padded to the nearest 32-bit boundary, as is the case - * for Windows bitmaps. You can also be clever and use this parameter - * to skip lines, etc. Setting this parameter to 0 is the equivalent of - * setting it to width * #tjPixelSize[pixelFormat]. + * + * @param pitch bytes per line in the source image. Normally, this should be + * width * #tjPixelSize[pixelFormat] if the image is unpadded, or + * #TJPAD(width * #tjPixelSize[pixelFormat]) if each line of the image + * is padded to the nearest 32-bit boundary, as is the case for Windows + * bitmaps. You can also be clever and use this parameter to skip lines, etc. + * Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * * @param height height (in pixels) of the source image + * * @param pixelFormat pixel format of the source image (see @ref TJPF - * "Pixel formats".) + * "Pixel formats".) + * * @param jpegBuf address of a pointer to an image buffer that will receive the - * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer - * to accommodate the size of the JPEG image. Thus, you can choose to: - * -# pre-allocate the JPEG buffer with an arbitrary size using - * #tjAlloc() and let TurboJPEG grow the buffer as needed, - * -# set *jpegBuf to NULL to tell TurboJPEG to allocate the - * buffer for you, or - * -# pre-allocate the buffer to a "worst case" size determined by - * calling #tjBufSize(). This should ensure that the buffer never has - * to be re-allocated (setting #TJFLAG_NOREALLOC guarantees this.) - * . - * If you choose option 1, *jpegSize should be set to the - * size of your pre-allocated buffer. In any case, unless you have - * set #TJFLAG_NOREALLOC, you should always check *jpegBuf upon - * return from this function, as it may have changed. + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer + * to accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tjAlloc() and + * let TurboJPEG grow the buffer as needed, + * -# set *jpegBuf to NULL to tell TurboJPEG to allocate the buffer + * for you, or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tjBufSize(). This should ensure that the buffer never has to be + * re-allocated (setting #TJFLAG_NOREALLOC guarantees this.) + * . + * If you choose option 1, *jpegSize should be set to the size of your + * pre-allocated buffer. In any case, unless you have set #TJFLAG_NOREALLOC, + * you should always check *jpegBuf upon return from this function, as + * it may have changed. + * * @param jpegSize pointer to an unsigned long variable that holds the size of - * the JPEG image buffer. If *jpegBuf points to a - * pre-allocated buffer, then *jpegSize should be set to the - * size of the buffer. Upon return, *jpegSize will contain the - * size of the JPEG image (in bytes.) + * the JPEG image buffer. If *jpegBuf points to a pre-allocated + * buffer, then *jpegSize should be set to the size of the buffer. + * Upon return, *jpegSize will contain the size of the JPEG image (in + * bytes.) If *jpegBuf points to a JPEG image buffer that is being + * reused from a previous call to one of the JPEG compression functions, then + * *jpegSize is ignored. + * * @param jpegSubsamp the level of chrominance subsampling to be used when - * generating the JPEG image (see @ref TJSAMP - * "Chrominance subsampling options".) + * generating the JPEG image (see @ref TJSAMP + * "Chrominance subsampling options".) + * * @param jpegQual the image quality of the generated JPEG image (1 = worst, - 100 = best) + * 100 = best) + * * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP - * "flags". + * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) */ @@ -636,54 +678,61 @@ DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf, /** - * Compress a YUV planar image into a JPEG image. Note that, if the width or - * height of the YUV image is not an even multiple of the MCU block size - * (see #tjMCUWidth and #tjMCUHeight), then an intermediate buffer copy will be - * performed within TurboJPEG. + * Compress a YUV planar image into a JPEG image. * * @param handle a handle to a TurboJPEG compressor or transformer instance - * @param srcBuf pointer to an image buffer containing a YUV planar image - * to be compressed. The Y, U (Cb), and V (Cr) image planes should be - * stored sequentially in the buffer, and the size of each plane - * is determined by the specified width, height, padding, and level of - * chrominance subsampling. If the chrominance components are - * subsampled along the horizontal dimension, then the width of the - * luminance plane should be padded to the nearest multiple of 2 (same - * goes for the height of the luminance plane, if the chrominance - * components are subsampled along the vertical dimension.) This is - * irrespective of any additional padding specified in the pad - * parameter. - * @param width width (in pixels) of the source image + * + * @param srcBuf pointer to an image buffer containing a YUV planar image to be + * compressed. The size of this buffer should match the value returned by + * #tjBufSizeYUV2() for the given image width, height, padding, and level of + * chrominance subsampling. The Y, U (Cb), and V (Cr) image planes should be + * stored sequentially in the source buffer (refer to @ref YUVnotes + * "YUV Image Format Notes".) + * + * @param width width (in pixels) of the source image. If the width is not an + * even multiple of the MCU block width (see #tjMCUWidth), then an intermediate + * buffer copy will be performed within TurboJPEG. + * * @param pad the line padding used in the source image. For instance, if each - * line in each plane of the YUV image is padded to the nearest multiple - * of 4 bytes, then pad should be set to 4. - * @param height height (in pixels) of the source image + * line in each plane of the YUV image is padded to the nearest multiple of 4 + * bytes, then pad should be set to 4. + * + * @param height height (in pixels) of the source image. If the height is not + * an even multiple of the MCU block height (see #tjMCUHeight), then an + * intermediate buffer copy will be performed within TurboJPEG. + * * @param subsamp the level of chrominance subsampling used in the source - * image (see @ref TJSAMP "Chrominance subsampling options".) + * image (see @ref TJSAMP "Chrominance subsampling options".) + * * @param jpegBuf address of a pointer to an image buffer that will receive the - * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer - * to accommodate the size of the JPEG image. Thus, you can choose to: - * -# pre-allocate the JPEG buffer with an arbitrary size using - * #tjAlloc() and let TurboJPEG grow the buffer as needed, - * -# set *jpegBuf to NULL to tell TurboJPEG to allocate the - * buffer for you, or - * -# pre-allocate the buffer to a "worst case" size determined by - * calling #tjBufSize(). This should ensure that the buffer never has - * to be re-allocated (setting #TJFLAG_NOREALLOC guarantees this.) - * . - * If you choose option 1, *jpegSize should be set to the - * size of your pre-allocated buffer. In any case, unless you have - * set #TJFLAG_NOREALLOC, you should always check *jpegBuf upon - * return from this function, as it may have changed. + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tjAlloc() and + * let TurboJPEG grow the buffer as needed, + * -# set *jpegBuf to NULL to tell TurboJPEG to allocate the buffer + * for you, or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tjBufSize(). This should ensure that the buffer never has to be + * re-allocated (setting #TJFLAG_NOREALLOC guarantees this.) + * . + * If you choose option 1, *jpegSize should be set to the size of your + * pre-allocated buffer. In any case, unless you have set #TJFLAG_NOREALLOC, + * you should always check *jpegBuf upon return from this function, as + * it may have changed. + * * @param jpegSize pointer to an unsigned long variable that holds the size of - * the JPEG image buffer. If *jpegBuf points to a - * pre-allocated buffer, then *jpegSize should be set to the - * size of the buffer. Upon return, *jpegSize will contain the - * size of the JPEG image (in bytes.) + * the JPEG image buffer. If *jpegBuf points to a pre-allocated + * buffer, then *jpegSize should be set to the size of the buffer. + * Upon return, *jpegSize will contain the size of the JPEG image (in + * bytes.) If *jpegBuf points to a JPEG image buffer that is being + * reused from a previous call to one of the JPEG compression functions, then + * *jpegSize is ignored. + * * @param jpegQual the image quality of the generated JPEG image (1 = worst, - 100 = best) + * 100 = best) + * * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP - * "flags". + * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) */ @@ -692,6 +741,76 @@ DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, unsigned char *srcBuf, unsigned long *jpegSize, int jpegQual, int flags); +/** + * Compress a set of Y, U (Cb), and V (Cr) image planes into a JPEG image. + * + * @param handle a handle to a TurboJPEG compressor or transformer instance + * + * @param srcPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if compressing a grayscale image) that contain a YUV + * image to be compressed. These planes can be contiguous or non-contiguous in + * memory. The size of each plane should match the value returned by + * #tjPlaneSizeYUV() for the given image width, height, strides, and level of + * chrominance subsampling. Refer to @ref YUVnotes "YUV Image Format Notes" + * for more details. + * + * @param width width (in pixels) of the source image. If the width is not an + * even multiple of the MCU block width (see #tjMCUWidth), then an intermediate + * buffer copy will be performed within TurboJPEG. + * + * @param strides an array of integers, each specifying the number of bytes per + * line in the corresponding plane of the YUV source image. Setting the stride + * for any plane to 0 is the same as setting it to the plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If strides is NULL, then + * the strides for all planes will be set to their respective plane widths. + * You can adjust the strides in order to specify an arbitrary amount of line + * padding in each plane or to create a JPEG image from a subregion of a larger + * YUV planar image. + * + * @param height height (in pixels) of the source image. If the height is not + * an even multiple of the MCU block height (see #tjMCUHeight), then an + * intermediate buffer copy will be performed within TurboJPEG. + * + * @param subsamp the level of chrominance subsampling used in the source + * image (see @ref TJSAMP "Chrominance subsampling options".) + * + * @param jpegBuf address of a pointer to an image buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tjAlloc() and + * let TurboJPEG grow the buffer as needed, + * -# set *jpegBuf to NULL to tell TurboJPEG to allocate the buffer + * for you, or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tjBufSize(). This should ensure that the buffer never has to be + * re-allocated (setting #TJFLAG_NOREALLOC guarantees this.) + * . + * If you choose option 1, *jpegSize should be set to the size of your + * pre-allocated buffer. In any case, unless you have set #TJFLAG_NOREALLOC, + * you should always check *jpegBuf upon return from this function, as + * it may have changed. + * + * @param jpegSize pointer to an unsigned long variable that holds the size of + * the JPEG image buffer. If *jpegBuf points to a pre-allocated + * buffer, then *jpegSize should be set to the size of the buffer. + * Upon return, *jpegSize will contain the size of the JPEG image (in + * bytes.) If *jpegBuf points to a JPEG image buffer that is being + * reused from a previous call to one of the JPEG compression functions, then + * *jpegSize is ignored. + * + * @param jpegQual the image quality of the generated JPEG image (1 = worst, + * 100 = best) + * + * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP + * "flags" + * + * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) +*/ +DLLEXPORT int DLLCALL tjCompressFromYUVPlanes(tjhandle handle, + unsigned char **srcPlanes, int width, int *strides, int height, int subsamp, + unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual, int flags); + + /** * The maximum size of the buffer (in bytes) required to hold a JPEG image with * the given parameters. The number of bytes returned by this function is @@ -703,11 +822,13 @@ DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, unsigned char *srcBuf, * size of a JPEG image prior to compression, the corner case has to be * handled. * - * @param width width of the image (in pixels) - * @param height height of the image (in pixels) + * @param width width (in pixels) of the image + * + * @param height height (in pixels) of the image + * * @param jpegSubsamp the level of chrominance subsampling to be used when - * generating the JPEG image (see @ref TJSAMP - * "Chrominance subsampling options".) + * generating the JPEG image (see @ref TJSAMP + * "Chrominance subsampling options".) * * @return the maximum size of the buffer (in bytes) required to hold the * image, or -1 if the arguments are out of bounds. @@ -720,12 +841,15 @@ DLLEXPORT unsigned long DLLCALL tjBufSize(int width, int height, * The size of the buffer (in bytes) required to hold a YUV planar image with * the given parameters. * - * @param width width of the image (in pixels) + * @param width width (in pixels) of the image + * * @param pad the width of each line in each plane of the image is padded to - * the nearest multiple of this number of bytes (must be a power of 2.) - * @param height height of the image (in pixels) + * the nearest multiple of this number of bytes (must be a power of 2.) + * + * @param height height (in pixels) of the image + * * @param subsamp level of chrominance subsampling in the image (see - * @ref TJSAMP "Chrominance subsampling options".) + * @ref TJSAMP "Chrominance subsampling options".) * * @return the size of the buffer (in bytes) required to hold the image, or * -1 if the arguments are out of bounds. @@ -734,52 +858,110 @@ DLLEXPORT unsigned long DLLCALL tjBufSizeYUV2(int width, int pad, int height, int subsamp); +/** + * The size of the buffer (in bytes) required to hold a YUV image plane with + * the given parameters. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param width width (in pixels) of the YUV image. NOTE: this is the width of + * the whole image, not the plane width. + * + * @param stride bytes per line in the image plane. Setting this to 0 is the + * equivalent of setting it to the plane width. + * + * @param height height (in pixels) of the YUV image. NOTE: this is the height + * of the whole image, not the plane height. + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the size of the buffer (in bytes) required to hold the YUV image + * plane, or -1 if the arguments are out of bounds. + */ +DLLEXPORT unsigned long DLLCALL tjPlaneSizeYUV(int componentID, int width, + int stride, int height, int subsamp); + + +/** + * The plane width of a YUV image plane with the given parameters. Refer to + * @ref YUVnotes "YUV Image Format Notes" for a description of plane width. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param width width (in pixels) of the YUV image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the plane width of a YUV image plane with the given parameters, or + * -1 if the arguments are out of bounds. + */ +DLLEXPORT int tjPlaneWidth(int componentID, int width, int subsamp); + + +/** + * The plane height of a YUV image plane with the given parameters. Refer to + * @ref YUVnotes "YUV Image Format Notes" for a description of plane height. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param height height (in pixels) of the YUV image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the plane height of a YUV image plane with the given parameters, or + * -1 if the arguments are out of bounds. + */ +DLLEXPORT int tjPlaneHeight(int componentID, int height, int subsamp); + + /** * Encode an RGB or grayscale image into a YUV planar image. This function * uses the accelerated color conversion routines in the underlying * codec but does not execute any of the other steps in the JPEG compression - * process. The Y, U (Cb), and V (Cr) image planes are stored sequentially - * into the destination buffer, and the size of each plane is determined by the - * width and height of the source image, as well as the specified padding and - * level of chrominance subsampling. If the chrominance components are - * subsampled along the horizontal dimension, then the width of the luminance - * plane is padded to the nearest multiple of 2 in the output image (same goes - * for the height of the luminance plane, if the chrominance components are - * subsampled along the vertical dimension.) - *

    - * NOTE: Technically, the JPEG format uses the YCbCr colorspace, but per the - * convention of the digital video community, the TurboJPEG API uses "YUV" to - * refer to an image format consisting of Y, Cb, and Cr image planes. + * process. * * @param handle a handle to a TurboJPEG compressor or transformer instance + * * @param srcBuf pointer to an image buffer containing RGB or grayscale pixels - * to be encoded + * to be encoded + * * @param width width (in pixels) of the source image - * @param pitch bytes per line of the source image. Normally, this should be - * width * #tjPixelSize[pixelFormat] if the image is unpadded, - * or #TJPAD(width * #tjPixelSize[pixelFormat]) if each line of - * the image is padded to the nearest 32-bit boundary, as is the case - * for Windows bitmaps. You can also be clever and use this parameter - * to skip lines, etc. Setting this parameter to 0 is the equivalent of - * setting it to width * #tjPixelSize[pixelFormat]. + * + * @param pitch bytes per line in the source image. Normally, this should be + * width * #tjPixelSize[pixelFormat] if the image is unpadded, or + * #TJPAD(width * #tjPixelSize[pixelFormat]) if each line of the image + * is padded to the nearest 32-bit boundary, as is the case for Windows + * bitmaps. You can also be clever and use this parameter to skip lines, etc. + * Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * * @param height height (in pixels) of the source image + * * @param pixelFormat pixel format of the source image (see @ref TJPF - * "Pixel formats".) + * "Pixel formats".) + * * @param dstBuf pointer to an image buffer that will receive the YUV image. - * Use #tjBufSizeYUV2() to determine the appropriate size for this - * buffer based on the image width, height, padding, and level of - * chrominance subsampling. + * Use #tjBufSizeYUV2() to determine the appropriate size for this buffer based + * on the image width, height, padding, and level of chrominance subsampling. + * The Y, U (Cb), and V (Cr) image planes will be stored sequentially in the + * buffer (refer to @ref YUVnotes "YUV Image Format Notes".) + * * @param pad the width of each line in each plane of the YUV image will be - * padded to the nearest multiple of this number of bytes (must be a - * power of 2.) To generate images suitable for X Video, pad - * should be set to 4. + * padded to the nearest multiple of this number of bytes (must be a power of + * 2.) To generate images suitable for X Video, pad should be set to + * 4. + * * @param subsamp the level of chrominance subsampling to be used when - * generating the YUV image (see @ref TJSAMP - * "Chrominance subsampling options".) To generate images suitable for - * X Video, subsamp should be set to @ref TJSAMP_420. This - * produces an image compatible with the I420 (AKA "YUV420P") format. + * generating the YUV image (see @ref TJSAMP + * "Chrominance subsampling options".) To generate images suitable for X + * Video, subsamp should be set to @ref TJSAMP_420. This produces an + * image compatible with the I420 (AKA "YUV420P") format. + * * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP - * "flags". + * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) */ @@ -788,6 +970,64 @@ DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *dstBuf, int pad, int subsamp, int flags); +/** + * Encode an RGB or grayscale image into separate Y, U (Cb), and V (Cr) image + * planes. This function uses the accelerated color conversion routines in the + * underlying codec but does not execute any of the other steps in the JPEG + * compression process. + * + * @param handle a handle to a TurboJPEG compressor or transformer instance + * + * @param srcBuf pointer to an image buffer containing RGB or grayscale pixels + * to be encoded + * + * @param width width (in pixels) of the source image + * + * @param pitch bytes per line in the source image. Normally, this should be + * width * #tjPixelSize[pixelFormat] if the image is unpadded, or + * #TJPAD(width * #tjPixelSize[pixelFormat]) if each line of the image + * is padded to the nearest 32-bit boundary, as is the case for Windows + * bitmaps. You can also be clever and use this parameter to skip lines, etc. + * Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param dstPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if generating a grayscale image) that will receive the + * encoded image. These planes can be contiguous or non-contiguous in memory. + * Use #tjPlaneSizeYUV() to determine the appropriate size for each plane based + * on the image width, height, strides, and level of chrominance subsampling. + * Refer to @ref YUVnotes "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * line in the corresponding plane of the output image. Setting the stride for + * any plane to 0 is the same as setting it to the plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If strides is NULL, then + * the strides for all planes will be set to their respective plane widths. + * You can adjust the strides in order to add an arbitrary amount of line + * padding to each plane or to encode an RGB or grayscale image into a + * subregion of a larger YUV planar image. + * + * @param subsamp the level of chrominance subsampling to be used when + * generating the YUV image (see @ref TJSAMP + * "Chrominance subsampling options".) To generate images suitable for X + * Video, subsamp should be set to @ref TJSAMP_420. This produces an + * image compatible with the I420 (AKA "YUV420P") format. + * + * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP + * "flags" + * + * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) +*/ +DLLEXPORT int DLLCALL tjEncodeYUVPlanes(tjhandle handle, + unsigned char *srcBuf, int width, int pitch, int height, int pixelFormat, + unsigned char **dstPlanes, int *strides, int subsamp, int flags); + + /** * Create a TurboJPEG decompressor instance. * @@ -801,18 +1041,24 @@ DLLEXPORT tjhandle DLLCALL tjInitDecompress(void); * Retrieve information about a JPEG image without decompressing it. * * @param handle a handle to a TurboJPEG decompressor or transformer instance + * * @param jpegBuf pointer to a buffer containing a JPEG image + * * @param jpegSize size of the JPEG image (in bytes) + * * @param width pointer to an integer variable that will receive the width (in - * pixels) of the JPEG image + * pixels) of the JPEG image + * * @param height pointer to an integer variable that will receive the height - * (in pixels) of the JPEG image + * (in pixels) of the JPEG image + * * @param jpegSubsamp pointer to an integer variable that will receive the - * level of chrominance subsampling used when compressing the JPEG image - * (see @ref TJSAMP "Chrominance subsampling options".) + * level of chrominance subsampling used when the JPEG image was compressed + * (see @ref TJSAMP "Chrominance subsampling options".) + * * @param jpegColorspace pointer to an integer variable that will receive one - * of the JPEG colorspace constants, indicating the colorspace of the - * JPEG image (see @ref TJCS "JPEG colorspaces".) + * of the JPEG colorspace constants, indicating the colorspace of the JPEG + * image (see @ref TJCS "JPEG colorspaces".) * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) */ @@ -826,7 +1072,7 @@ DLLEXPORT int DLLCALL tjDecompressHeader3(tjhandle handle, * this implementation of TurboJPEG supports. * * @param numscalingfactors pointer to an integer variable that will receive - * the number of elements in the list + * the number of elements in the list * * @return a pointer to a list of fractional scaling factors, or NULL if an * error is encountered (see #tjGetErrorStr().) @@ -838,42 +1084,48 @@ DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors); * Decompress a JPEG image to an RGB, grayscale, or CMYK image. * * @param handle a handle to a TurboJPEG decompressor or transformer instance + * * @param jpegBuf pointer to a buffer containing the JPEG image to decompress + * * @param jpegSize size of the JPEG image (in bytes) + * * @param dstBuf pointer to an image buffer that will receive the decompressed - * image. This buffer should normally be pitch * scaledHeight - * bytes in size, where scaledHeight can be determined by - * calling #TJSCALED() with the JPEG image height and one of the scaling - * factors returned by #tjGetScalingFactors(). The dstBuf - * pointer may also be used to decompress into a specific region of a - * larger buffer. + * image. This buffer should normally be pitch * scaledHeight bytes + * in size, where scaledHeight can be determined by calling + * #TJSCALED() with the JPEG image height and one of the scaling factors + * returned by #tjGetScalingFactors(). The dstBuf pointer may also be + * used to decompress into a specific region of a larger buffer. + * * @param width desired width (in pixels) of the destination image. If this is - * different than the width of the JPEG image being decompressed, then - * TurboJPEG will use scaling in the JPEG decompressor to generate the - * largest possible image that will fit within the desired width. If - * width is set to 0, then only the height will be considered - * when determining the scaled image size. - * @param pitch bytes per line of the destination image. Normally, this is - * scaledWidth * #tjPixelSize[pixelFormat] if the decompressed - * image is unpadded, else #TJPAD(scaledWidth * - * #tjPixelSize[pixelFormat]) if each line of the decompressed - * image is padded to the nearest 32-bit boundary, as is the case for - * Windows bitmaps. (NOTE: scaledWidth can be determined by - * calling #TJSCALED() with the JPEG image width and one of the scaling - * factors returned by #tjGetScalingFactors().) You can also be clever - * and use the pitch parameter to skip lines, etc. Setting this - * parameter to 0 is the equivalent of setting it to - * scaledWidth * #tjPixelSize[pixelFormat]. + * different than the width of the JPEG image being decompressed, then + * TurboJPEG will use scaling in the JPEG decompressor to generate the largest + * possible image that will fit within the desired width. If width is + * set to 0, then only the height will be considered when determining the + * scaled image size. + * + * @param pitch bytes per line in the destination image. Normally, this is + * scaledWidth * #tjPixelSize[pixelFormat] if the decompressed image + * is unpadded, else #TJPAD(scaledWidth * #tjPixelSize[pixelFormat]) + * if each line of the decompressed image is padded to the nearest 32-bit + * boundary, as is the case for Windows bitmaps. (NOTE: scaledWidth + * can be determined by calling #TJSCALED() with the JPEG image width and one + * of the scaling factors returned by #tjGetScalingFactors().) You can also be + * clever and use the pitch parameter to skip lines, etc. Setting this + * parameter to 0 is the equivalent of setting it to + * scaledWidth * #tjPixelSize[pixelFormat]. + * * @param height desired height (in pixels) of the destination image. If this - * is different than the height of the JPEG image being decompressed, - * then TurboJPEG will use scaling in the JPEG decompressor to generate - * the largest possible image that will fit within the desired height. - * If height is set to 0, then only the width will be - * considered when determining the scaled image size. + * is different than the height of the JPEG image being decompressed, then + * TurboJPEG will use scaling in the JPEG decompressor to generate the largest + * possible image that will fit within the desired height. If height + * is set to 0, then only the width will be considered when determining the + * scaled image size. + * * @param pixelFormat pixel format of the destination image (see @ref - * TJPF "Pixel formats".) + * TJPF "Pixel formats".) + * * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP - * "flags". + * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) */ @@ -885,41 +1137,45 @@ DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, /** * Decompress a JPEG image to a YUV planar image. This function performs JPEG * decompression but leaves out the color conversion step, so a planar YUV - * image is generated instead of an RGB image. The structure of the planes in - * this image is the same as in the images generated by #tjEncodeYUV3(). Note - * that, if the width or height of the JPEG image is not an even multiple of - * the MCU block size (see #tjMCUWidth and #tjMCUHeight), then an intermediate - * buffer copy will be performed within TurboJPEG. - *

    - * NOTE: Technically, the JPEG format uses the YCbCr colorspace, but per the - * convention of the digital video community, the TurboJPEG API uses "YUV" to - * refer to an image format consisting of Y, Cb, and Cr image planes. + * image is generated instead of an RGB image. * * @param handle a handle to a TurboJPEG decompressor or transformer instance + * * @param jpegBuf pointer to a buffer containing the JPEG image to decompress + * * @param jpegSize size of the JPEG image (in bytes) + * * @param dstBuf pointer to an image buffer that will receive the YUV image. - * Use #tjBufSizeYUV2() to determine the appropriate size for this - * buffer based on the image width, height, padding, and level of - * subsampling. + * Use #tjBufSizeYUV2() to determine the appropriate size for this buffer based + * on the image width, height, padding, and level of subsampling. The Y, + * U (Cb), and V (Cr) image planes will be stored sequentially in the buffer + * (refer to @ref YUVnotes "YUV Image Format Notes".) + * * @param width desired width (in pixels) of the YUV image. If this is - * different than the width of the JPEG image being decompressed, then - * TurboJPEG will use scaling in the JPEG decompressor to generate the - * largest possible image that will fit within the desired width. If - * width is set to 0, then only the height will be considered - * when determining the scaled image size. + * different than the width of the JPEG image being decompressed, then + * TurboJPEG will use scaling in the JPEG decompressor to generate the largest + * possible image that will fit within the desired width. If width is + * set to 0, then only the height will be considered when determining the + * scaled image size. If the scaled width is not an even multiple of the MCU + * block width (see #tjMCUWidth), then an intermediate buffer copy will be + * performed within TurboJPEG. + * * @param pad the width of each line in each plane of the YUV image will be - * padded to the nearest multiple of this number of bytes (must be a - * power of 2.) To generate images suitable for X Video, pad - * should be set to 4. + * padded to the nearest multiple of this number of bytes (must be a power of + * 2.) To generate images suitable for X Video, pad should be set to + * 4. + * * @param height desired height (in pixels) of the YUV image. If this is - * different than the height of the JPEG image being decompressed, then - * TurboJPEG will use scaling in the JPEG decompressor to generate the - * largest possible image that will fit within the desired height. If - * height is set to 0, then only the width will be considered - * when determining the scaled image size. + * different than the height of the JPEG image being decompressed, then + * TurboJPEG will use scaling in the JPEG decompressor to generate the largest + * possible image that will fit within the desired height. If height + * is set to 0, then only the width will be considered when determining the + * scaled image size. If the scaled height is not an even multiple of the MCU + * block height (see #tjMCUHeight), then an intermediate buffer copy will be + * performed within TurboJPEG. + * * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP - * "flags". + * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) */ @@ -928,52 +1184,106 @@ DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle, int width, int pad, int height, int flags); +/** + * Decompress a JPEG image into separate Y, U (Cb), and V (Cr) image + * planes. This function performs JPEG decompression but leaves out the color + * conversion step, so a planar YUV image is generated instead of an RGB image. + * + * @param handle a handle to a TurboJPEG decompressor or transformer instance + * + * @param jpegBuf pointer to a buffer containing the JPEG image to decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if decompressing a grayscale image) that will receive + * the YUV image. These planes can be contiguous or non-contiguous in memory. + * Use #tjPlaneSizeYUV() to determine the appropriate size for each plane based + * on the scaled image width, scaled image height, strides, and level of + * chrominance subsampling. Refer to @ref YUVnotes "YUV Image Format Notes" + * for more details. + * + * @param width desired width (in pixels) of the YUV image. If this is + * different than the width of the JPEG image being decompressed, then + * TurboJPEG will use scaling in the JPEG decompressor to generate the largest + * possible image that will fit within the desired width. If width is + * set to 0, then only the height will be considered when determining the + * scaled image size. If the scaled width is not an even multiple of the MCU + * block width (see #tjMCUWidth), then an intermediate buffer copy will be + * performed within TurboJPEG. + * + * @param strides an array of integers, each specifying the number of bytes per + * line in the corresponding plane of the output image. Setting the stride for + * any plane to 0 is the same as setting it to the scaled plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If strides is NULL, then + * the strides for all planes will be set to their respective scaled plane + * widths. You can adjust the strides in order to add an arbitrary amount of + * line padding to each plane or to decompress the JPEG image into a subregion + * of a larger YUV planar image. + * + * @param height desired height (in pixels) of the YUV image. If this is + * different than the height of the JPEG image being decompressed, then + * TurboJPEG will use scaling in the JPEG decompressor to generate the largest + * possible image that will fit within the desired height. If height + * is set to 0, then only the width will be considered when determining the + * scaled image size. If the scaled height is not an even multiple of the MCU + * block height (see #tjMCUHeight), then an intermediate buffer copy will be + * performed within TurboJPEG. + * + * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP + * "flags" + * + * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) + */ +DLLEXPORT int DLLCALL tjDecompressToYUVPlanes(tjhandle handle, + unsigned char *jpegBuf, unsigned long jpegSize, unsigned char **dstPlanes, + int width, int *strides, int height, int flags); + + /** * Decode a YUV planar image into an RGB or grayscale image. This function * uses the accelerated color conversion routines in the underlying * codec but does not execute any of the other steps in the JPEG decompression - * process. The Y, U (Cb), and V (Cr) image planes should be stored - * sequentially in the source buffer, and the size of each plane is determined - * by the width and height of the source image, as well as the specified - * padding and level of chrominance subsampling. If the chrominance components - * are subsampled along the horizontal dimension, then the width of the - * luminance plane should be padded to the nearest multiple of 2 in the input - * image (same goes for the height of the luminance plane, if the chrominance - * components are subsampled along the vertical dimension.) - *

    - * NOTE: Technically, the JPEG format uses the YCbCr colorspace, but per the - * convention of the digital video community, the TurboJPEG API uses "YUV" to - * refer to an image format consisting of Y, Cb, and Cr image planes. + * process. * * @param handle a handle to a TurboJPEG decompressor or transformer instance + * * @param srcBuf pointer to an image buffer containing a YUV planar image to be - * decoded. The size of this buffer should match the value returned - * by #tjBufSizeYUV2() for the given image width, height, padding, and - * level of chrominance subsampling. + * decoded. The size of this buffer should match the value returned by + * #tjBufSizeYUV2() for the given image width, height, padding, and level of + * chrominance subsampling. The Y, U (Cb), and V (Cr) image planes should be + * stored sequentially in the source buffer (refer to @ref YUVnotes + * "YUV Image Format Notes".) + * * @param pad Use this parameter to specify that the width of each line in each - * plane of the YUV source image is padded to the nearest multiple of - * this number of bytes (must be a power of 2.) + * plane of the YUV source image is padded to the nearest multiple of this + * number of bytes (must be a power of 2.) + * * @param subsamp the level of chrominance subsampling used in the YUV source - * image (see @ref TJSAMP "Chrominance subsampling options".) + * image (see @ref TJSAMP "Chrominance subsampling options".) + * * @param dstBuf pointer to an image buffer that will receive the decoded - * image. This buffer should normally be pitch * height - * bytes in size, but the dstBuf pointer can also be used to - * decode into a specific region of a larger buffer. + * image. This buffer should normally be pitch * height bytes in + * size, but the dstBuf pointer can also be used to decode into a + * specific region of a larger buffer. + * * @param width width (in pixels) of the source and destination images - * @param pitch bytes per line of the destination image. Normally, this should - * be width * #tjPixelSize[pixelFormat] if the destination - * image is unpadded, or #TJPAD(width * - * #tjPixelSize[pixelFormat]) if each line of the destination - * image should be padded to the nearest 32-bit boundary, as is the case - * for Windows bitmaps. You can also be clever and use the pitch - * parameter to skip lines, etc. Setting this parameter to 0 is the - * equivalent of setting it to width * - * #tjPixelSize[pixelFormat]. + * + * @param pitch bytes per line in the destination image. Normally, this should + * be width * #tjPixelSize[pixelFormat] if the destination image is + * unpadded, or #TJPAD(width * #tjPixelSize[pixelFormat]) if each line + * of the destination image should be padded to the nearest 32-bit boundary, as + * is the case for Windows bitmaps. You can also be clever and use the pitch + * parameter to skip lines, etc. Setting this parameter to 0 is the equivalent + * of setting it to width * #tjPixelSize[pixelFormat]. + * * @param height height (in pixels) of the source and destination images + * * @param pixelFormat pixel format of the destination image (see @ref TJPF - * "Pixel formats".) + * "Pixel formats".) + * * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP - * "flags". + * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) */ @@ -982,6 +1292,63 @@ DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, unsigned char *srcBuf, int height, int pixelFormat, int flags); +/** + * Decode a set of Y, U (Cb), and V (Cr) image planes into an RGB or grayscale + * image. This function uses the accelerated color conversion routines in the + * underlying codec but does not execute any of the other steps in the JPEG + * decompression process. + * + * @param handle a handle to a TurboJPEG decompressor or transformer instance + * + * @param srcPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if decoding a grayscale image) that contain a YUV image + * to be decoded. These planes can be contiguous or non-contiguous in memory. + * The size of each plane should match the value returned by #tjPlaneSizeYUV() + * for the given image width, height, strides, and level of chrominance + * subsampling. Refer to @ref YUVnotes "YUV Image Format Notes" for more + * details. + * + * @param strides an array of integers, each specifying the number of bytes per + * line in the corresponding plane of the YUV source image. Setting the stride + * for any plane to 0 is the same as setting it to the plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If strides is NULL, then + * the strides for all planes will be set to their respective plane widths. + * You can adjust the strides in order to specify an arbitrary amount of line + * padding in each plane or to decode a subregion of a larger YUV planar image. + * + * @param subsamp the level of chrominance subsampling used in the YUV source + * image (see @ref TJSAMP "Chrominance subsampling options".) + * + * @param dstBuf pointer to an image buffer that will receive the decoded + * image. This buffer should normally be pitch * height bytes in + * size, but the dstBuf pointer can also be used to decode into a + * specific region of a larger buffer. + * + * @param width width (in pixels) of the source and destination images + * + * @param pitch bytes per line in the destination image. Normally, this should + * be width * #tjPixelSize[pixelFormat] if the destination image is + * unpadded, or #TJPAD(width * #tjPixelSize[pixelFormat]) if each line + * of the destination image should be padded to the nearest 32-bit boundary, as + * is the case for Windows bitmaps. You can also be clever and use the pitch + * parameter to skip lines, etc. Setting this parameter to 0 is the equivalent + * of setting it to width * #tjPixelSize[pixelFormat]. + * + * @param height height (in pixels) of the source and destination images + * + * @param pixelFormat pixel format of the destination image (see @ref TJPF + * "Pixel formats".) + * + * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP + * "flags" + * + * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) + */ +DLLEXPORT int DLLCALL tjDecodeYUVPlanes(tjhandle handle, + unsigned char **srcPlanes, int *strides, int subsamp, unsigned char *dstBuf, + int width, int pitch, int height, int pixelFormat, int flags); + + /** * Create a new TurboJPEG transformer instance. * @@ -993,9 +1360,9 @@ DLLEXPORT tjhandle DLLCALL tjInitTransform(void); /** * Losslessly transform a JPEG image into another JPEG image. Lossless - * transforms work by moving the raw coefficients from one JPEG image structure - * to another without altering the values of the coefficients. While this is - * typically faster than decompressing the image, transforming it, and + * transforms work by moving the raw DCT coefficients from one JPEG image + * structure to another without altering the values of the coefficients. While + * this is typically faster than decompressing the image, transforming it, and * re-compressing it, lossless transforms are not free. Each lossless * transform requires reading and performing Huffman decoding on all of the * coefficients in the source image, regardless of the size of the destination @@ -1005,38 +1372,44 @@ DLLEXPORT tjhandle DLLCALL tjInitTransform(void); * source coefficients multiple times. * * @param handle a handle to a TurboJPEG transformer instance - * @param jpegBuf pointer to a buffer containing the JPEG image to transform - * @param jpegSize size of the JPEG image (in bytes) + * + * @param jpegBuf pointer to a buffer containing the JPEG source image to + * transform + * + * @param jpegSize size of the JPEG source image (in bytes) + * * @param n the number of transformed JPEG images to generate + * * @param dstBufs pointer to an array of n image buffers. dstBufs[i] - * will receive a JPEG image that has been transformed using the - * parameters in transforms[i]. TurboJPEG has the ability to - * reallocate the JPEG buffer to accommodate the size of the JPEG image. - * Thus, you can choose to: - * -# pre-allocate the JPEG buffer with an arbitrary size using - * #tjAlloc() and let TurboJPEG grow the buffer as needed, - * -# set dstBufs[i] to NULL to tell TurboJPEG to allocate the - * buffer for you, or - * -# pre-allocate the buffer to a "worst case" size determined by - * calling #tjBufSize() with the transformed or cropped width and - * height. This should ensure that the buffer never has to be - * re-allocated (setting #TJFLAG_NOREALLOC guarantees this.) - * . - * If you choose option 1, dstSizes[i] should be set to - * the size of your pre-allocated buffer. In any case, unless you have - * set #TJFLAG_NOREALLOC, you should always check dstBufs[i] - * upon return from this function, as it may have changed. + * will receive a JPEG image that has been transformed using the parameters in + * transforms[i]. TurboJPEG has the ability to reallocate the JPEG + * buffer to accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tjAlloc() and + * let TurboJPEG grow the buffer as needed, + * -# set dstBufs[i] to NULL to tell TurboJPEG to allocate the buffer + * for you, or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tjBufSize() with the transformed or cropped width and height. This should + * ensure that the buffer never has to be re-allocated (setting + * #TJFLAG_NOREALLOC guarantees this.) + * . + * If you choose option 1, dstSizes[i] should be set to the size of + * your pre-allocated buffer. In any case, unless you have set + * #TJFLAG_NOREALLOC, you should always check dstBufs[i] upon return + * from this function, as it may have changed. + * * @param dstSizes pointer to an array of n unsigned long variables that will - * receive the actual sizes (in bytes) of each transformed JPEG image. - * If dstBufs[i] points to a pre-allocated buffer, then - * dstSizes[i] should be set to the size of the buffer. Upon - * return, dstSizes[i] will contain the size of the JPEG image - * (in bytes.) + * receive the actual sizes (in bytes) of each transformed JPEG image. If + * dstBufs[i] points to a pre-allocated buffer, then + * dstSizes[i] should be set to the size of the buffer. Upon return, + * dstSizes[i] will contain the size of the JPEG image (in bytes.) + * * @param transforms pointer to an array of n #tjtransform structures, each of - * which specifies the transform parameters and/or cropping region for - * the corresponding transformed output image. + * which specifies the transform parameters and/or cropping region for the + * corresponding transformed output image. + * * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP - * "flags". + * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) */ @@ -1049,7 +1422,7 @@ DLLEXPORT int DLLCALL tjTransform(tjhandle handle, unsigned char *jpegBuf, * Destroy a TurboJPEG compressor, decompressor, or transformer instance. * * @param handle a handle to a TurboJPEG compressor, decompressor or - * transformer instance + * transformer instance * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) */ @@ -1065,7 +1438,7 @@ DLLEXPORT int DLLCALL tjDestroy(tjhandle handle); * @param bytes the number of bytes to allocate * * @return a pointer to a newly-allocated buffer with the specified number of - * bytes + * bytes. * * @sa tjFree() */ diff --git a/win/jconfig.h.in b/win/jconfig.h.in index 6865fafe..8783900e 100644 --- a/win/jconfig.h.in +++ b/win/jconfig.h.in @@ -7,6 +7,17 @@ #cmakedefine D_ARITH_CODING_SUPPORTED #cmakedefine MEM_SRCDST_SUPPORTED +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE @BITS_IN_JSAMPLE@ /* use 8 or 12 */ + #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT /* #define void char */