Compare commits

...

188 Commits

Author SHA1 Message Date
DRC
a51ada6706 Use new e-mail alias
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@185 632fc199-4ca6-4c93-a231-07263d6284db
2010-05-11 00:39:45 +00:00
DRC
ef663e333e Only disable filesystem redirection in the 64-bit installers
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@184 632fc199-4ca6-4c93-a231-07263d6284db
2010-05-10 23:39:22 +00:00
DRC
be09b20a40 Handle cases in which MinGW inexplicably builds the DLL as libjpeg-0.dll instead of libjpeg-62.dll
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@183 632fc199-4ca6-4c93-a231-07263d6284db
2010-05-10 22:20:14 +00:00
DRC
9ca2364694 Use "make nsi" instead of "make dist" to be consistent with MinGW build
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@182 632fc199-4ca6-4c93-a231-07263d6284db
2010-05-10 22:19:24 +00:00
DRC
3dc1bc2ded Create separate packages for Win64 binaries
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@181 632fc199-4ca6-4c93-a231-07263d6284db
2010-05-10 22:18:10 +00:00
DRC
1a2219ec26 git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@180 632fc199-4ca6-4c93-a231-07263d6284db 2010-05-10 20:03:36 +00:00
DRC
b6f097f729 xmm6-xmm15 must also be preserved by the callee; Win64 should fully work now
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@179 632fc199-4ca6-4c93-a231-07263d6284db
2010-04-23 15:41:34 +00:00
DRC
d3e320fee7 Win64 should fully work now
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@178 632fc199-4ca6-4c93-a231-07263d6284db
2010-04-21 17:20:12 +00:00
DRC
830d5fccf4 Use 64-bit holding buffer on Win64 for increased performance
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@177 632fc199-4ca6-4c93-a231-07263d6284db
2010-04-20 21:13:26 +00:00
DRC
4132b1d552 Updated (C)
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@176 632fc199-4ca6-4c93-a231-07263d6284db
2010-04-20 20:54:03 +00:00
DRC
f9bdeb62e2 Not sure why the cjpeg/djpeg image loaders got disabled, but re-enable them
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@175 632fc199-4ca6-4c93-a231-07263d6284db
2010-04-20 19:16:06 +00:00
DRC
e728ed7a36 Win64 (mostly) works now
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@174 632fc199-4ca6-4c93-a231-07263d6284db
2010-04-20 19:15:09 +00:00
DRC
a644fb05a7 Use correct filenames in headers
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@173 632fc199-4ca6-4c93-a231-07263d6284db
2010-04-20 18:20:13 +00:00
DRC
86d8c0aa26 0.0.93
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@172 632fc199-4ca6-4c93-a231-07263d6284db
2010-04-20 18:12:38 +00:00
DRC
fb096fff78 Only have to use 32-bit mov for r14, since it is populated from the stack
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@171 632fc199-4ca6-4c93-a231-07263d6284db
2010-04-19 18:58:07 +00:00
DRC
14ecb539df Attempt to fix Win64 issues
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@170 632fc199-4ca6-4c93-a231-07263d6284db
2010-04-17 21:57:25 +00:00
DRC
09271951d9 0.0.92
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@169 632fc199-4ca6-4c93-a231-07263d6284db
2010-04-13 07:56:24 +00:00
DRC
7bac07bf12 Added FreeBSD build instructions
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@168 632fc199-4ca6-4c93-a231-07263d6284db
2010-04-10 05:53:35 +00:00
DRC
0f413b2207 Fix x86-64 build on FreeBSD systems
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@167 632fc199-4ca6-4c93-a231-07263d6284db
2010-04-06 20:05:39 +00:00
DRC
97f8ec4b60 I'm not sure why, but this was necessary in order to return the 32-bit performance to the 0.0.90 baseline
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@165 632fc199-4ca6-4c93-a231-07263d6284db
2010-03-20 22:38:53 +00:00
DRC
1e6b5b4884 Clarify license description
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@164 632fc199-4ca6-4c93-a231-07263d6284db
2010-03-20 20:00:51 +00:00
DRC
ae19bf6f15 Add ChangeLog to repository
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@163 632fc199-4ca6-4c93-a231-07263d6284db
2010-03-15 11:40:31 +00:00
DRC
e885a8bf41 Fix data corruption issues when decompressing large JPEG images and/or using buffered I/O. Specifically, decode_mcu_fast() can potentially process more than 1 MCU, so make sure there is enough space in the buffer to accommodate this case. Otherwise, the buffer pointer goes negative, and bad mojo ensues. Also, the fast decoder's method of handling unread markers doesn't make libjpeg's restart handler happy, so disable fast decode when restarts are used.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@162 632fc199-4ca6-4c93-a231-07263d6284db
2010-03-15 11:34:58 +00:00
DRC
0b7d4ed792 Include ChangeLog.txt in dist
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@161 632fc199-4ca6-4c93-a231-07263d6284db
2010-03-03 09:37:58 +00:00
DRC
10a094f0e6 Bump version number
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@160 632fc199-4ca6-4c93-a231-07263d6284db
2010-03-03 09:36:31 +00:00
DRC
f8b77c44f1 Don't allow code path to be forced on a system that doesn't support it
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@159 632fc199-4ca6-4c93-a231-07263d6284db
2010-03-03 08:46:29 +00:00
DRC
048990944f Bleepin' Windows uses LLP64, not LP64
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@158 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-26 23:01:19 +00:00
DRC
d3c7eff53d Oops. Debian users might like documentation as well.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@157 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-25 20:14:10 +00:00
DRC
0248dd9aeb Clarify the DLL hell problem
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@154 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-25 06:21:12 +00:00
DRC
7e0b499ee7 Install jpeg62.dll in SDK directory, not Windows system directory. Also, check whether SDK is already installed prior to re-installing
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@153 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-25 05:52:44 +00:00
DRC
f19caa5e67 Ensure static libs are built with PIC
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@152 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-24 21:27:32 +00:00
DRC
0a1f68edeb Visual C++ libraries can't be made to work with MinGW because of the dependency on msvcr90.dll, so build a separate installer for MinGW libraries
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@151 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-24 07:24:26 +00:00
DRC
8f870c297d 4.0 is significantly slower than 4.1+
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@150 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-24 00:30:00 +00:00
DRC
f66a2b08a2 Get rid of cjpeg/djpeg-specific #defines
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@149 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-23 23:54:28 +00:00
DRC
485cd80811 We don't actually need to use GCC 4.0 to do a backward compatible build, and it slows things down relative to GCC 4.2
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@148 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-23 23:23:42 +00:00
DRC
a9a7b22443 Fix Windows package script to accommodate new output directory for VC build
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@147 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-23 22:56:05 +00:00
DRC
3cd2e503c6 Fix compiler warning about ending struct with a comma
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@146 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-23 21:43:21 +00:00
DRC
fe7936c603 Make sure CFLAGS, CXXFLAGS, LDFLAGS, and host_alias are unset to get a 32-bit build
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@145 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-23 20:17:48 +00:00
DRC
252dbc9fad Oops. Didn't mean to commit the debug statement
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@144 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-23 10:39:07 +00:00
DRC
5df6c2372d For some unknown reason, the sym link and the actual file get flipped around whenever you do 'make install'. Make sure the script handles both cases.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@143 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-23 10:22:33 +00:00
DRC
ca3cebbaef Compile properly with C++
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@142 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-23 08:12:38 +00:00
DRC
4425702a6a Oops. Missing test image
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@141 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-22 22:57:45 +00:00
DRC
968c8bbc00 Fix 'make dist' since we added new test images
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@140 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-22 22:50:13 +00:00
DRC
8f0d62cb92 Added additional documentation for flags
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@139 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-22 08:35:19 +00:00
DRC
0c6a271f97 Make TJ_FORCE* options work correctly
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@138 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-22 08:34:44 +00:00
DRC
3bddd467c4 A bit better solution for 64-bit cleanliness
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@137 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-22 06:14:05 +00:00
DRC
4df84bf859 Clarify Win64 issue
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@136 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-22 04:55:23 +00:00
DRC
748fda3834 Use the C library DLL only with jpeg62.dll where it is needed. Build turbojpeg.dll with the static C library to maintain backward compatibility with TurboJPEG/IPP
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@135 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-22 04:51:09 +00:00
DRC
aa91179eac Speed up make testclean
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@134 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-22 04:12:06 +00:00
DRC
03c3c9be67 Added note about this being an outdated document
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@133 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-21 15:45:00 +00:00
DRC
c3f4ac0b6e Add note about texinfo dependency in NASM build
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@132 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-19 21:51:26 +00:00
DRC
a93881b109 Remove debug output
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@131 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-19 07:01:23 +00:00
DRC
4924e49ad0 test depends on jpegut as well
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@130 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-19 07:00:30 +00:00
DRC
687244b90e Unfortunately, we have to use the DLL version of the C library to avoid crashes in cjpeg
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@129 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-19 06:59:18 +00:00
DRC
9abc855552 Oops. DLL object was misnamed and thus wasn't getting removed on 'make clean'
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@128 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-19 06:56:53 +00:00
DRC
10d15cbe44 Improve unit tests
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@127 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-19 06:56:03 +00:00
DRC
0fd8be5d0c Improve unit tests
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@126 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-19 05:12:39 +00:00
DRC
26b208d8b7 MinGW64 requires that the functions be prefixed with an underscore. Visual C++ apparently doesn't
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@125 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-18 13:14:29 +00:00
DRC
8b014d7f5d First attempt at Win64 support
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@124 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-18 13:03:41 +00:00
DRC
ea1978896e dumpbuf() should have void return type
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@123 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-18 05:12:58 +00:00
DRC
c9327685dd Oops. Leftover bugs from the 64-bit port (cause seg fault when using JDCT_FLOAT or JDCT_IFAST when decompressing)
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@122 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-18 04:14:14 +00:00
DRC
65d05c1d92 Exit with non-zero status if an error is encountered
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@121 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-18 00:40:17 +00:00
DRC
ca5e7d184e Sun Studio recipes
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@120 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-17 02:25:06 +00:00
DRC
b9b1ca30ca Build Sun packages
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@119 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-17 02:24:02 +00:00
DRC
10e75a71da Make sure existing .deb file is removed prior to building new one
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@118 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-17 01:08:37 +00:00
DRC
051dd5a4ab Replace clunky doexit() mechanism with a better means of error trapping
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@117 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-17 01:07:46 +00:00
DRC
6afd256e98 Oops. Need to use %dir to list directories
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@116 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-17 00:56:59 +00:00
DRC
d86e4d914c Build libturbojpeg.so using mapfile on Solaris
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@115 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-16 22:40:26 +00:00
DRC
1e2f298f94 Set default optimization flags to -xO5 if using Sun Studio
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@114 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-16 22:35:25 +00:00
DRC
8a26fdea23 Fix build with Sun Studio
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@113 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-16 22:34:12 +00:00
DRC
23071bcba5 Install additional documentation
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@112 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-16 05:54:00 +00:00
DRC
68fef83ed9 Split build instructions into a new file and add SDK usage notes to README-turbo.txt
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@111 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-16 05:29:10 +00:00
DRC
2f272d519f Make sure directories under /opt/libjpeg-turbo get deleted when uninstalling RPM
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@110 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-16 05:04:46 +00:00
DRC
6f8c66880e Build TurboJPEG/OSS with a version script to prevent any non-global symbols from being accessible (this is to protect against potential namespace conflicts when preloading it into an application via VirtualGL.)
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@109 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-16 05:03:51 +00:00
DRC
45ff6e2745 Create Windows installer
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@108 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 17:10:36 +00:00
DRC
fb18e856e4 Keep dllexport symbols out of static lib
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@107 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 17:07:46 +00:00
DRC
315123fa3e Add mechanism for building universal (i386/x86-64) binaries on Snow Leopard
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@106 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 16:14:26 +00:00
DRC
6a3477c29f Use more appropriate temp. directory name
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@105 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 15:16:58 +00:00
DRC
6533b6e023 Add mechanism for creating Mac packages
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@104 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 14:57:18 +00:00
DRC
268ef884d8 Use a cleaner method of arg checking that works with set -u
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@103 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 13:32:09 +00:00
DRC
4614871092 Instructions for Tiger-compatible build on Leopard/Snow Leopard
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@102 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 13:27:17 +00:00
DRC
feb9dce665 Oops. This should have been included with r100
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@101 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 12:08:46 +00:00
DRC
52a19f25d5 Add mechanism for creating DEB packages
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@100 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 12:06:27 +00:00
DRC
f26914b93a Actually, we only need to 'make dist-gzip' prior to building the SRPM
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@99 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 11:36:46 +00:00
DRC
079b4346bc Add mechanism for creating RPMs
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@98 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 11:32:23 +00:00
DRC
6f52592267 Should really use $(srcdir) here
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@97 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 11:10:08 +00:00
DRC
8ff1f254f3 Change default prefix to /opt/libjpeg-turbo
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@96 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 11:08:57 +00:00
DRC
211de3b963 Don't need Visual C++ project file
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@95 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 11:07:33 +00:00
DRC
ec84a6bdbf Change package name & version
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@94 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 11:05:53 +00:00
DRC
0a945a1770 Make sure 'make dist' includes everything we want (and nothing we don't)
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@93 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 11:04:51 +00:00
DRC
6aa6a0a768 More missing files from jpeg-6b
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@92 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-15 10:49:01 +00:00
Thomas G. Lane
5ead57a34a The Independent JPEG Group's JPEG software v6b 2015-07-27 13:43:00 -05:00
Thomas G. Lane
489583f516 The Independent JPEG Group's JPEG software v6a 2015-07-29 15:32:35 -05:00
Thomas G. Lane
bc79e0680a The Independent JPEG Group's JPEG software v6 2015-07-29 15:31:30 -05:00
Thomas G. Lane
a8b67c4fbb The Independent JPEG Group's JPEG software v5b 2015-07-29 15:30:19 -05:00
Thomas G. Lane
9ba2f5ed36 The Independent JPEG Group's JPEG software v5a 2015-07-29 15:29:17 -05:00
Thomas G. Lane
36a4ccccd3 The Independent JPEG Group's JPEG software v5 2015-07-29 15:28:00 -05:00
DRC
4d5fc18f58 Reflect the fact that CFLAGS=CXXFLAGS=-O3 by default
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@91 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-14 08:02:55 +00:00
DRC
e7b699d653 Set CFLAGS=CXXFLAGS=-O3 if using GCC and the flags are not already set
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@90 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-14 07:39:07 +00:00
DRC
327184fbee builddir isn't always defined
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@89 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-14 02:15:52 +00:00
DRC
ce1546eb90 License info + updated performance claims
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@88 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-13 23:06:03 +00:00
DRC
971d851844 Enable (i.e. fix) VPATH and out-of-tree builds
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@87 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-13 22:55:05 +00:00
DRC
bd17e2a5d6 Instructions for cross compiling MinGW libs on Cygwin
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@86 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-12 23:24:21 +00:00
DRC
101f09a3d1 Build instructions
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@85 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-12 22:52:37 +00:00
DRC
bf0fab9aa1 MinGW uses autoconf 2.56
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@84 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-12 22:22:01 +00:00
DRC
f4253a7cdd Visual C++ build
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@83 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-12 09:37:20 +00:00
DRC
34d59e71d6 Clean up test detritus
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@82 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-12 06:27:34 +00:00
DRC
60fa0600c0 Re-add relevant files and tests from libjpeg v6b
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@81 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-12 06:01:49 +00:00
DRC
60cddeb849 Restore --without-simd option for testing purposes
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@80 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-12 05:37:07 +00:00
DRC
21d66837a0 Do not build libturbojpeg as a versioned library
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@79 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-12 04:34:41 +00:00
DRC
411dcf5666 Oops. Still need to #define WITH_SIMD
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@78 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-12 04:28:29 +00:00
DRC
87581b8188 Make SIMD build compulsory (otherwise, what's the point?)
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@77 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-11 06:57:57 +00:00
DRC
1bf1a14d71 Build shared libraries by default; Include libturbojpeg in distribution
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@76 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-11 06:39:32 +00:00
DRC
4f4428185b Oops. Use EGREP instead of GREP, because GREP is not available in earlier versions of autotools
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@75 632fc199-4ca6-4c93-a231-07263d6284db
2010-02-05 09:19:13 +00:00
DRC
2a46aeece8 Fix build problems on Solaris 10
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@74 632fc199-4ca6-4c93-a231-07263d6284db
2010-01-29 07:14:57 +00:00
DRC
83e9cd5e36 Enable 64-bit libjpeg/SIMD build on Solaris
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@73 632fc199-4ca6-4c93-a231-07263d6284db
2010-01-28 23:57:53 +00:00
DRC
a1e9878b31 Use the correct version to name the shared library, and if the shared library build is enabled, allow the headers to be installed
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@72 632fc199-4ca6-4c93-a231-07263d6284db
2010-01-28 22:18:41 +00:00
DRC
0c0f304e8d Allow building libjpeg.so if --enable-shared is passed to configure (but disable shared library build by default)
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@71 632fc199-4ca6-4c93-a231-07263d6284db
2010-01-28 05:34:53 +00:00
Adam Tkac
e54fb0bf95 [Bugfix] Mark stack as non-executable in NASM code.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@70 632fc199-4ca6-4c93-a231-07263d6284db
2010-01-27 10:10:23 +00:00
Pierre Ossman
1536192e92 Update the svn:ignore lists for the new build system.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@69 632fc199-4ca6-4c93-a231-07263d6284db
2009-12-23 09:24:42 +00:00
DRC
321ad51314 Enable 64-bit build on Snow Leopard
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@68 632fc199-4ca6-4c93-a231-07263d6284db
2009-10-08 09:41:39 +00:00
DRC
132b5fdd6d Work around alignment issue with OS X linker which was causing problems on Leopard and Snow Leopard
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@67 632fc199-4ca6-4c93-a231-07263d6284db
2009-10-08 09:04:56 +00:00
DRC
fc5dc4fa19 Some systems (notably OS X Leopard) have fls() already, so rename ours to avoid conflict
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@66 632fc199-4ca6-4c93-a231-07263d6284db
2009-10-01 22:26:14 +00:00
DRC
021da085a7 Not all platforms define __WORDSIZE
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@65 632fc199-4ca6-4c93-a231-07263d6284db
2009-09-28 08:19:40 +00:00
DRC
e2816648d8 Greatly improve performance of Huffman decoding
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@64 632fc199-4ca6-4c93-a231-07263d6284db
2009-09-28 00:33:02 +00:00
DRC
6c0e1fc72e Significantly improve grayscale performance
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@63 632fc199-4ca6-4c93-a231-07263d6284db
2009-09-24 06:18:25 +00:00
Adam Tkac
0ba6826d20 Merge unified_buildsys branch to trunk (r3892 - r3898)
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@62 632fc199-4ca6-4c93-a231-07263d6284db
2009-09-14 13:07:14 +00:00
DRC
a21a01c60d Update (C) notice and fix line feed in usage instructions
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@61 632fc199-4ca6-4c93-a231-07263d6284db
2009-09-03 01:35:12 +00:00
Peter Åstrand
353332b015 Corrected last patch: Use jsimd_none.c instead of jsimd_i386.c on
VC/Windows at this point. 



git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@60 632fc199-4ca6-4c93-a231-07263d6284db
2009-08-19 14:20:46 +00:00
Peter Åstrand
adfd23393c Windows build fixes:
* Use jsimd_i386.c instead of the attic jsimd.c

* Corrected include of jsimd.h in jsimd_i386.c. 



git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@59 632fc199-4ca6-4c93-a231-07263d6284db
2009-08-19 13:53:48 +00:00
DRC
dae4474117 Unfortunately, the previous enhancements made an invalid assumption about the code sizes, which caused "DCT out of range" errors in the decoder. Was able to fix 64-bit without losing any performance, but unfortunately had to revert 32-bit back to its previous behavior for now.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@58 632fc199-4ca6-4c93-a231-07263d6284db
2009-08-06 08:58:48 +00:00
DRC
8ece7fef15 Update copyrights to indicate files modified with colorspace extensions
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@57 632fc199-4ca6-4c93-a231-07263d6284db
2009-08-06 08:32:00 +00:00
DRC
62aaa7e7c1 Oops. Clean up a couple of remaining 32-bit memory accesses
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@56 632fc199-4ca6-4c93-a231-07263d6284db
2009-08-06 07:51:26 +00:00
DRC
8443e529e9 Improve compression performance by 15-20%
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@55 632fc199-4ca6-4c93-a231-07263d6284db
2009-07-30 08:35:06 +00:00
Pierre Ossman
5d20b7e662 Make our Makefile.am a bit easier to convert to a standalone one by
indicating which headers are the public ones.


git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@54 632fc199-4ca6-4c93-a231-07263d6284db
2009-07-10 12:59:14 +00:00
Pierre Ossman
79ecd1b16e Make sure bmp.h gets distributed.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@53 632fc199-4ca6-4c93-a231-07263d6284db
2009-07-10 12:56:00 +00:00
Pierre Ossman
f1418c76a8 Make sure the indirectly used assembly files get packaged.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@52 632fc199-4ca6-4c93-a231-07263d6284db
2009-07-10 12:47:13 +00:00
Pierre Ossman
9a6b8dca7e Make x86_64 SIMD code PIC friendly
Use RIP relative addressing as that works in both PIC and non-PIC mode.


git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@51 632fc199-4ca6-4c93-a231-07263d6284db
2009-06-29 12:58:48 +00:00
Pierre Ossman
db838bdb73 Ignore test tools and files generated by them
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@50 632fc199-4ca6-4c93-a231-07263d6284db
2009-06-29 11:24:50 +00:00
Pierre Ossman
ba82ddf6ca Clean up SIMD glue code
The SIMD glue code has gotten a bit #ifdef heavy so clean it up by having
one file for each possible SIMD arch. This also allows a simplification of
the x86_64 code as SSE/SSE2 is always known to exist on that arch.


git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@49 632fc199-4ca6-4c93-a231-07263d6284db
2009-06-29 11:20:42 +00:00
Pierre Ossman
1aea5fa182 Remove unused variable.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@48 632fc199-4ca6-4c93-a231-07263d6284db
2009-06-26 14:10:33 +00:00
Pierre Ossman
afa937e62b Improve the messages for the SIMD configuration test now that we support
more than one arch.


git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@47 632fc199-4ca6-4c93-a231-07263d6284db
2009-06-26 14:09:47 +00:00
DRC
73de982473 Add back in cjpeg and djpeg utilities for testing purposes
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@46 632fc199-4ca6-4c93-a231-07263d6284db
2009-06-25 20:41:17 +00:00
DRC
cdc8ac3eb1 64-bit SIMD acceleration
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@45 632fc199-4ca6-4c93-a231-07263d6284db
2009-06-25 20:38:31 +00:00
DRC
3a63184474 Fix dependencies for merged upsampling code
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@44 632fc199-4ca6-4c93-a231-07263d6284db
2009-06-25 20:33:51 +00:00
DRC
61e51f98e2 Test fast upsampling
"4:1:1 = 4:2:0"


git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@43 632fc199-4ca6-4c93-a231-07263d6284db
2009-04-05 21:53:20 +00:00
DRC
720e161083 Add colorspace extensions to merged upsampling routines
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@42 632fc199-4ca6-4c93-a231-07263d6284db
2009-04-05 21:51:25 +00:00
DRC
e673a1764a Remove unnecessary code
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@41 632fc199-4ca6-4c93-a231-07263d6284db
2009-04-05 21:47:40 +00:00
DRC
16ed1f5387 Oops. jcolsamp.inc should be included from j[c|d]clr[mmx|ss2].asm so it received the effect of the redefined RGB_* macros
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@40 632fc199-4ca6-4c93-a231-07263d6284db
2009-04-04 15:25:45 +00:00
DRC
a2d19e1981 Oops. jcolsamp.inc needs to be included from j[c|d]clr[mmx|ss2].asm so that it receives the effect of the redefined RGB_* macros
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@39 632fc199-4ca6-4c93-a231-07263d6284db
2009-04-04 15:22:14 +00:00
Adam Tkac
6e8b69d35f Don't install test programs, build them only.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@38 632fc199-4ca6-4c93-a231-07263d6284db
2009-04-03 14:54:40 +00:00
Adam Tkac
6e075fcfae Check if C++ compiler is present.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@37 632fc199-4ca6-4c93-a231-07263d6284db
2009-04-03 14:47:50 +00:00
DRC
2e7b76b28c Include low-level unit tests borrowed from VirtualGL
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@36 632fc199-4ca6-4c93-a231-07263d6284db
2009-04-03 12:04:24 +00:00
DRC
f25c071eb7 Implement new colorspaces to allow directly compressing from/decompressing to RGB/RGBX/BGR/BGRX/XBGR/XRGB without conversion
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@35 632fc199-4ca6-4c93-a231-07263d6284db
2009-04-03 12:00:51 +00:00
DRC
59c1a252d5 Add environment variables to force MMX/SSE2 code path selection
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@34 632fc199-4ca6-4c93-a231-07263d6284db
2009-04-03 11:27:17 +00:00
DRC
c7fbf2961a Fix build for RGB_PIXELSIZE==4
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@33 632fc199-4ca6-4c93-a231-07263d6284db
2009-04-01 20:02:14 +00:00
DRC
3cba8db08f Eliminate backward incompatibility that required empty_output_buffer() to handle cases in which the buffer wasn't 100% full
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@32 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-16 23:58:30 +00:00
Pierre Ossman
3a65ef478b Work around subdirectory bug in older automake.
Older versions of automake doesn't properly support no-recursive make.
Reimplement the build system by having a local Makefile.am in the
simd/ directory.


git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@31 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-16 13:34:18 +00:00
DRC
8629988742 Fix broken buffered I/O (to make cjpeg work)
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@30 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-14 01:21:13 +00:00
Adam Tkac
d07a0a6479 Make source compilable via GNU autotools which are part of RHEL 5.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@29 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-13 13:58:44 +00:00
Adam Tkac
6a8b33d3cd Revert r3657 (import of autogenerated) files.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@28 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-13 13:44:18 +00:00
Pierre Ossman
995a3e14ee Add new simd files to Visual Studio project file.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@27 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-13 12:24:28 +00:00
Pierre Ossman
dc5db14a33 Move variable init around a bit to please crappy compilers.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@26 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-13 12:17:26 +00:00
Pierre Ossman
b28e287f93 Don't mix LOCAL() and qualifiers.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@25 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-13 12:16:51 +00:00
DRC
99313388cc Include Huffman codec optimizations borrowed from TurboJPEG
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@24 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-12 17:24:27 +00:00
Adam Tkac
0747ad2b12 Import autogenerated files for unix/ and common/ subdirs to make source
compilable without GNU autotools.



git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@23 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-11 11:14:37 +00:00
Pierre Ossman
eea7215525 Add SSE2 SIMD implementation of computationally intensive routines.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@22 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-09 13:34:17 +00:00
MIYASAKA Masaru
a2e6a9dd47 IJG R6b with x86SIMD V1.02
Independent JPEG Group's JPEG software release 6b
with x86 SIMD extension for IJG JPEG library version 1.02
2015-07-29 16:36:25 -05:00
Pierre Ossman
018fc42974 Add SSE SIMD implementation of computationally intensive routines.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@21 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-09 13:31:56 +00:00
Pierre Ossman
7311830680 Most SIMD implementations need 16 byte alignment
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@20 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-09 13:30:47 +00:00
Pierre Ossman
35c4719638 Make sure the work space memory is properly aligned
We use the heap allocators to avoid having more than one implementation
of the alignment logic.


git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@19 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-09 13:29:37 +00:00
Pierre Ossman
65d0317346 Add 3DNow SIMD implementation of computationally intensive routines.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@18 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-09 13:28:10 +00:00
Pierre Ossman
5eb84ff97f Add MMX SIMD implementation of computationally intensive routines.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@17 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-09 13:25:30 +00:00
Pierre Ossman
dedc42e268 "Optimise" quantization step by replacing the division by a multiplication.
This has no measurable difference right now but makes it possible to do
SIMD implementations of this stage.


git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@16 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-09 13:23:04 +00:00
Pierre Ossman
2ae181c7b8 Implement x86 SIMD framework
Add NASM support and stub routine for detecting SIMD extensions.


git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@15 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-09 13:21:27 +00:00
Pierre Ossman
59a3938b2e Framework for supporting SIMD acceleration
Designed to impose minimal changes on the "normal" code.


git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@14 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-09 13:15:56 +00:00
Pierre Ossman
49dcbfbf13 Split up the forward DCT routine into three stages
Divide it into sample conversion, DCT and quantization in order to
easily provide alternative implementations of each stage.


git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@13 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-09 10:37:20 +00:00
Pierre Ossman
5557fd2217 Improve memory allocater alignment handling
Fix some broken assumptions and allow any alignment, not just those
associated with C types.


git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@12 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-09 10:34:53 +00:00
Pierre Ossman
2fb0831aeb Ignore generated configuration header.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@11 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-09 10:33:17 +00:00
Pierre Ossman
ba0ce39b70 Explain the config header voodoo.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@10 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-06 15:30:42 +00:00
Pierre Ossman
b22e883a5f Don't test for GNU malloc as we don't need it (or even check the result
of the test).


git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@9 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-06 15:00:56 +00:00
Peter Åstrand
aa026fbf36 Renamed README_TightVNC.txt as README_TigerVNC.txt
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@8 632fc199-4ca6-4c93-a231-07263d6284db
2009-03-03 12:04:47 +00:00
Peter Åstrand
8a418b2bb8 Rebrand the source as TigerVNC. It is my hope that this patch is
minimal but still complete. The rebranding was done using a script:

find trunk -name .svn -prune -o -type f -exec rep.sh \{\} \;
pushd trunk
svn revert doc/TODO doc/registered-codes.txt doc/ft-protocol-problems.txt doc/rfbtight.tex
perl -pi -e 's|tightvnc|tigervnc|g' unix/configure.ac win/configure.ac unix/README

With rep.sh looking like:

perl -pi -e 's|TightVNC|TigerVNC|g' "$@"
perl -pi -e 's|www\.tightvnc\.com/bugs\.html|www\.tigervnc\.org|g' "$@"
perl -pi -e 's|www\.tightvnc\.com|www\.tigervnc\.org|g' "$@"
perl -pi -e 's|devteam\@tightvnc\.com|tigervnc-devel\@lists\.sourceforge\.net|g' "$@"
perl -pi -e 's|TigerVNC Team|TightVNC Team|g' "$@"
perl -pi -e 's|TigerVNC Group|TightVNC Group|g' "$@"
perl -pi -e 's|TigerVNC protocol|TightVNC protocol|g' "$@"
perl -pi -e 's|TigerVNC-specific|TightVNC-specific|g' "$@"
perl -pi -e 's|Vendor signatures: standard VNC/RealVNC, TridiaVNC, and TigerVNC|Vendor signatures: standard VNC/RealVNC, TridiaVNC, and TightVNC|g' "$@"
perl -pi -e 's|TigerVNC vendor|TightVNC vendor|g' "$@"
perl -pi -e 's|TigerVNC extension|TightVNC extension|g' "$@"
perl -pi -e 's|protocolTigerVNC|protocolTightVNC|g' "$@"
perl -pi -e 's|TigerVNC additions were|TightVNC additions were|g' "$@"
perl -pi -e 's|TigerVNC 1\.2|TightVNC 1\.2|g' "$@"
perl -pi -e 's|TigerVNC authentication type|TightVNC authentication type|g' "$@"



git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@7 632fc199-4ca6-4c93-a231-07263d6284db
2009-02-27 10:12:14 +00:00
Peter Åstrand
5f33883e0e Ignoring Autotools and build files.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@6 632fc199-4ca6-4c93-a231-07263d6284db
2008-12-10 08:50:48 +00:00
Peter Åstrand
213a72aaea This should be the final modification to restore a working Visual
Studio build. A static jconfig.h has been re-added, but in a separate
directory, to avoid clash with jconfig.h generated by configure
script. Also, jconfig.h now includes the inline macro. jpeg.dsp has
been modified to search in the "win" subdir, to find jconfig.h. 

This patch is in spirit similar to r121. 



git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@5 632fc199-4ca6-4c93-a231-07263d6284db
2008-12-02 09:56:26 +00:00
Adam Tkac
da5a1fe760 [Bugfix] Include man files and more jpeg libraries in tarball
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@3 632fc199-4ca6-4c93-a231-07263d6284db
2008-10-22 11:19:25 +00:00
Constantin Kaplinsky
0ca44258fc Merged changes from branches/1.5-xserver (revision range 2432:2631) back to trunk.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@2 632fc199-4ca6-4c93-a231-07263d6284db
2008-09-28 05:08:48 +00:00
Constantin Kaplinsky
c87530727a Migrating to new directory structure adopted from the RealVNC's source tree. More changes will follow.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@1 632fc199-4ca6-4c93-a231-07263d6284db
2006-05-25 05:01:55 +00:00
263 changed files with 68448 additions and 21293 deletions

326
BUILDING.txt Normal file
View File

@@ -0,0 +1,326 @@
*******************************************************************************
** Building on Unix Platforms, Cygwin, and MinGW
*******************************************************************************
==================
Build Requirements
==================
-- autoconf 2.56 or later
* If using MinGW, this can be obtained by installing the MSYS DTK
-- automake 1.7 or later
* If using MinGW, this can be obtained by installing the MSYS DTK
-- libtool 1.4 or later
* If using MinGW, this can be obtained by installing the MSYS DTK
-- NASM
* 0.98 or later is required for a 32-bit build
* NASM 2.05 or later is required for a 64-bit build
* NASM 2.07 or later is required for a 64-bit build on OS/X (10.6 "Snow
Leopard" or later.) This can be obtained from MacPorts
(http://www.macports.org/).
The NASM 2.05 RPMs do not work on older Linux systems, such as Enterprise
Linux 4. On such systems, you can easily build and install NASM 2.05
from the source RPM by executing the following as root:
ARCH=`uname -m`
wget http://www.nasm.us/pub/nasm/releasebuilds/2.05.01/nasm-2.05.01-1.src.rpm
rpmbuild --rebuild nasm-2.05.01-1.src.rpm
rpm -Uvh /usr/src/redhat/RPMS/$ARCH/nasm-2.05.01-1.$ARCH.rpm
NOTE: NASM build will fail if texinfo is not installed.
-- GCC v4.1 or later recommended for best performance
======================
Building libjpeg-turbo
======================
The following procedure will build libjpeg-turbo on Linux, 32-bit OS X, and
Solaris/x86 systems (on Solaris, this generates a 32-bit library. See below
for 64-bit build instructions.)
cd libjpeg-turbo
autoreconf -fiv
sh ./configure
make
NOTE: Running autoreconf is only necessary if building libjpeg-turbo from the
SVN repository.
This will generate the following files under .libs/
libjpeg.a
Static link library for libjpeg-turbo
libjpeg.so.62.0.0 (Linux, Solaris)
libjpeg.62.dylib (OS X)
libjpeg-62.dll (MinGW)
cygjpeg-62.dll (Cygwin)
Shared library for libjpeg-turbo
libjpeg.so (Linux, Solaris)
libjpeg.dylib (OS X)
libjpeg.dll.a (Cygwin, MinGW)
Development stub for libjpeg-turbo shared library
libturbojpeg.a
Static link library for TurboJPEG/OSS
libturbojpeg.so (Linux, Solaris)
libturbojpeg.dylib (OS X)
Shared library and development stub for TurboJPEG/OSS
libturbojpeg.dll (MinGW)
cygturbojpeg.dll (Cygwin)
Shared library for TurboJPEG/OSS
libturbojpeg.dll.a (Cygwin, MinGW)
Development stub for TurboJPEG/OSS shared library
========================
Installing libjpeg-turbo
========================
If you intend to install these libraries and the associated header files, then
replace 'make' in the instructions above with
make install prefix={base dir} libdir={library directory}
For example,
make install prefix=/usr/local libdir=/usr/local/lib64
will install the header files in /usr/local/include and the library files in
/usr/local/lib64. If 'prefix' and 'libdir' are not specified, then the default
is to install the header files in /opt/libjpeg-turbo/include and the library
files in /opt/libjpeg-turbo/lib.
NOTE: You can specify a prefix of /usr and a libdir of, for instance,
/usr/lib64 to overwrite the system's version of libjpeg. If you do this,
however, then be sure to BACK UP YOUR SYSTEM'S INSTALLATION OF LIBJPEG before
overwriting it. It is recommended that you instead install libjpeg-turbo into
a non-system directory and manipulate the LD_LIBRARY_PATH or create sym links
to force applications to use libjpeg-turbo instead of libjpeg. See
README-turbo.txt for more information.
=============
Build Recipes
=============
32-bit Library Build on 64-bit Linux
------------------------------------
Add
--host i686-pc-linux-gnu CFLAGS='-O3 -m32' CXXFLAGS='-O3 -m32'
to the configure command line.
64-bit Library Build on 64-bit OS/X
-----------------------------------
Add
--host x86_64-apple-darwin10.0.0 NASM=/opt/local/bin/nasm
to the configure command line. NASM 2.07 or later from MacPorts must be
installed.
32-bit Library Build on 64-bit OS/X
-----------------------------------
Add
CFLAGS='-O3 -m32' CXXFLAGS='-O3 -m32' LDFLAGS=-m32
to the configure command line.
32-bit Backward-Compatible Library Build on 64-bit OS/X
-------------------------------------------------------
Add
CFLAGS='-isysroot /Developer/SDKs/MacOSX10.4u.sdk \
-mmacosx-version-min=10.4 -O3 -m32' \
CXXFLAGS='-isysroot /Developer/SDKs/MacOSX10.4u.sdk \
-mmacosx-version-min=10.4 -O3 -m32' \
LDFLAGS='-isysroot /Developer/SDKs/MacOSX10.4u.sdk \
-mmacosx-version-min=10.4 -m32'
to the configure command line. The OS X 10.4 SDK must be installed.
64-bit Library Build on 64-bit Solaris
--------------------------------------
Add
--host x86_64-pc-solaris CFLAGS='-O3 -m64' CXXFLAGS='-O3 -m64' LDFLAGS=-m64
to the configure command line.
64-bit Library Build on 64-bit FreeBSD
--------------------------------------
Add
--host x86_64-unknown-freebsd
to the configure command line. NASM 2.07 or later from FreeBSD ports must be
installed.
32-bit Library Build on 64-bit FreeBSD
--------------------------------------
Add
--host i386-unknown-freebsd CC='gcc -B /usr/lib32' CXX='g++ -B/usr/lib32' \
CFLAGS='-O3 -m32' CXXFLAGS='-O3 -m32' LDFLAGS='-B/usr/lib32'
to the configure command line. NASM 2.07 or later from FreeBSD ports must be
installed.
MinGW Build on Cygwin
---------------------
Add
--host mingw32
to the configure command line. This will produce libraries which do not
depend on cygwin1.dll or other Cygwin DLL's.
Sun Studio
----------
Add
CC=cc CXX=CC
to the configure command line. libjpeg-turbo will automatically be built with
the maximum optimization level (-xO5) unless you override CFLAGS and CXXFLAGS.
To build a 64-bit version of libjpeg-turbo using Sun Studio, add
--host x86_64-pc-solaris CC=cc CXX=CC CFLAGS='-xO5 -m64' \
CXXFLAGS='-xO5 -m64' LDFLAGS=-m64
to the configure command line.
*******************************************************************************
** Building on Windows (Visual C++)
*******************************************************************************
==================
Build Requirements
==================
-- GNU Make v3.7 or later
* Can be found in MSYS (http://www.mingw.org/download.shtml) or
Cygwin (http://www.cygwin.com/)
-- Windows SDK for Windows Server 2008 and .NET Framework 3.5 (or a later
version)
http://msdn.microsoft.com/en-us/windows/dd146047.aspx
* The Windows SDK includes both 32-bit and 64-bit Visual C++ compilers and
everything necessary to build libjpeg-turbo. If you do not already have
Visual C++ installed, then this is the recommended solution. Also tested
with Microsoft Visual C++ 2008 Express Edition (both are free downloads.)
* Add the compiler and SDK binary directories (for instance,
c:\Program Files\Microsoft Visual Studio 9.0\VC\BIN;
c:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE;
c:\Program Files\Microsoft SDKs\Windows\v6.1\bin)
to the system or user PATH environment variable prior to building
libjpeg-turbo.
* Add the compiler and SDK include directories (for instance,
c:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE;
c:\Program Files\Microsoft SDKs\Windows\v6.1\include)
to the system or user INCLUDE environment variable prior to building
libjpeg-turbo.
* Add the compiler library directory (for instance,
c:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;
c:\Program Files\Microsoft SDKs\Windows\v6.1\lib)
to the system or user LIB environment variable prior to building
libjpeg-turbo.
-- NASM (http://www.nasm.us/) 0.98 or later
======================
Building libjpeg-turbo
======================
cd libjpeg-turbo
make -f win/Makefile
This will generate the following files under libjpeg-turbo\windows\:
jpeg-static.lib Static link library for libjpeg-turbo
jpeg62.dll Shared library for libjpeg-turbo
jpeg.lib Development stub for libjpeg-turbo shared library
turbojpeg-static.lib Static link library for TurboJPEG/OSS
turbojpeg.dll Shared library for TurboJPEG/OSS
turbojpeg.lib Development stub for TurboJPEG/OSS shared library
If a 64-bit Windows platform is detected, then the build system will attempt
to build a 64-bit version of libjpeg-turbo. You can override this by running
make -f win/Makefile WIN64=no
*******************************************************************************
** Creating Release Packages
*******************************************************************************
The following commands can be used to create various types of release packages:
make rpm
Create RedHat-style binary RPM package. Requires RPM v4 or later.
make srpm
This runs 'make dist' to create a pristine source tarball, then creates a
RedHat-style source RPM package from the tarball. Requires RPM v4 or later.
make deb
Create Debian-style binary package. Requires dpkg.
make dmg
Create Macintosh package/disk image. This requires the PackageMaker
application, which must be installed in /Developer/Applications/Utilities.
make udmg
On 64-bit OS X (10.6 "Snow Leopard" or later), this creates a version of the
Macintosh package/disk image which contains universal i386/x86-64 binaries.
The 32-bit fork of these binaries is backward compatible with OS X 10.4 and
later, whereas the 64-bit fork is compatible with OS X 10.6 and later. OS X
10.4 compatibility SDK required.
make nsi
When using MinGW, this creates a Win32 installer for the GCC version of the
libjpeg-turbo SDK. This requires the Nullsoft Install System
(http://nsis.sourceforge.net/.) makensis.exe should be in your PATH.
make -f win/Makefile nsi
This creates a Win32 installer for the Visual C++ version of the
libjpeg-turbo SDK. This requires the Nullsoft Install System
(http://nsis.sourceforge.net/.) makensis.exe should be in your PATH.

146
CHANGELOG
View File

@@ -1,146 +0,0 @@
CHANGELOG for Independent JPEG Group's JPEG software
Version 4A 18-Feb-93
--------------------
Substantial speedup for grayscale output from color JPEG file (suppress
processing of chrominance components). Lesser speedups in Huffman decoding
and in compression quantization.
Can switch stdin/stdout to binary mode with either fdopen() or setmode();
this allows use of one-file command line style on a wider range of systems.
Also added -outfile switch so that makefile test scripts don't have to depend
on the command line style.
New makefile.icc for Code Builder; makefile.sas is updated for SAS C 6.x.
Hook added to allow surrounding application to read and write COM (comment)
blocks.
Bugfixes (DOS only): jmemdos.c code for accessing expanded memory only worked
if struct fields are packed on byte boundaries. This is not true by default
for Microsoft C. Furthermore, Microsoft C needs an _fheapmin() call to clean
up the far heap correctly.
Version 4 10-Dec-92
--------------------
Revised user interface: switches now use names instead of single letters.
(Old switch letters are acceptable abbreviations of new switch names, EXCEPT
for djpeg's old -g, -D, -1 switches.) cjpeg has several new switches.
Provision for smoothing the input image added to cjpeg. This helps a lot with
converting dithered GIFs to JPEG.
Decoder upsampling now uses interpolation instead of pixel replication; this
improves rendering of sharp colored edges.
The decompressor will now try to continue after detecting an error in the
compressed data, instead of just aborting. If the input file has restart
markers, full synchronization will usually be regained at the next undamaged
restart marker. (But you're still out of luck if any of the header markers
are corrupt.)
Substantial improvements in speed; DCT accuracy improved too.
Numerous minor changes to improve portability. egetopt.c, which was by far
the worst portability problem, is gone altogether.
A few bugfixes, sigh (mostly affecting DOS implementations only).
Bugfix: on DOS machines, cjpeg -o would fail on grayscale input files.
Bugfix: one-pass quantization to more than 64 color levels would fail on
16-bit-int machines. This could only happen with quantized grayscale output.
A couple of changes affect code that calls the JPEG subroutine library:
1. The parameter struct tag names are now capitalized (Compress_info_struct,
Compress_methods_struct, Decompress_info_struct, Decompress_methods_struct,
and External_methods_struct). This makes it easier to live with brain-damaged
compilers with short identifier lengths. (All identifiers used in the JPEG
code are now unique within the first 16 characters.)
2. If you are not calling jselerror(), you need to initialize three new fields
in the emethods structure, typically as follows:
e_methods.num_warnings = 0; /* no warnings emitted yet */
e_methods.first_warning_level = 0; /* display first corrupt-data warning */
e_methods.more_warning_level = 3; /* but suppress additional ones */
These fields control handling of corrupt-data warnings.
Version 3 17-Mar-92
--------------------
Memory manager is finally capable of swapping to temp files. There are
separate versions of jmemsys.c for no temp files (same behavior as older
versions), simple temp files with or without tmpfile(), and a DOS-specific
version (including special code for EMS and XMS). This is probably much more
system-dependent than any of the older code; some bugs may surface here.
Hooks added for user interface to install progress monitoring routine
(percent-done bar, etc). See comments with dummy progress_monitor
routines in jcdeflts.c, jddeflts.c.
Two-pass color quantization (finally!). This is now the default method when
quantizing; say '-1' to djpeg for quick-and-ugly 1-pass method. There is
a test file for checking 2-pass quantization and GIF output.
Fixed bug in jcopy_block_row that broke cjpeg -o option and djpeg -b option
on MSDOS machines.
Miscellaneous small speedups; notably, DCT computation rearranged so that
GCC "inline" feature is no longer needed for good code quality.
File config.c renamed ckconfig.c to avoid name conflict with /etc/config
on Unix systems.
Added example.c to document usage of JPEG subroutines better.
Memory manager now knows how to release all storage during error exit ---
avoids memory leak when using JPEG as subroutines. This implies a couple
small changes to the subroutine interface: the old free_defaults subroutines
are no longer needed, but if you have a replacement error_exit method then it
must call the new free_all method. Also, jselvirtmem renamed to jselmemmgr.
Code for reading Targa files with 32-bit pixels was incorrect.
Colorspace conversion slightly faster and more accurate; because of
this, old "test" files will no longer match bit-for-bit.
Version 2 13-Dec-91
--------------------
Documentation improved a little --- there are man pages now.
Installation instructions moved from README to a separate file SETUP.
New program config.c is provided to help you get the configuration options
right. This should make installation a lot more foolproof.
Sense of djpeg -D switch reversed: dithering is now ON by default.
RLE image file support added (thanks to Mike Lijewski).
Targa image file support added (thanks to Lee Crocker).
PPM input now accepts all PPM and PGM files.
Bug fix: on machines where 'int' is 16 bits, high-Q-setting JPEG files
were not decoded correctly.
Numerous changes to improve portability. There should be few or no compiler
warnings now.
Makefiles cleaned up; defaults now appropriate for production use rather than
debugging.
Subroutine interface cleaned up. If you wrote code based on version 1's
jcmain/jdmain, you'll need to change it, but it should get a little shorter
and simpler.
Version 1 7-Oct-91
--------------------
Initial public release.

15
ChangeLog.txt Normal file
View File

@@ -0,0 +1,15 @@
Significant changes since 0.0.91
================================
[1] Fixed x86-64 build on FreeBSD systems
[2] Added support for Windows 64-bit systems
Significant changes since 0.0.90
================================
[1] Added documentation to .deb packages
[2] 2968313: Fixed data corruption issues when decompressing large JPEG images
and/or using buffered I/O with the libjpeg-turbo decompressor

504
LGPL.txt Normal file
View File

@@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

53
LICENSE.txt Normal file
View File

@@ -0,0 +1,53 @@
wxWindows Library Licence, Version 3.1
======================================
Copyright (C) 1998-2005 Julian Smart, Robert Roebling et al
Everyone is permitted to copy and distribute verbatim copies
of this licence document, but changing it is not allowed.
WXWINDOWS LIBRARY LICENCE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public Licence as published by
the Free Software Foundation; either version 2 of the Licence, or (at
your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
General Public Licence for more details.
You should have received a copy of the GNU Library General Public Licence
along with this software, usually in a file named COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA.
EXCEPTION NOTICE
1. As a special exception, the copyright holders of this library give
permission for additional uses of the text contained in this release of
the library as licenced under the wxWindows Library Licence, applying
either version 3.1 of the Licence, or (at your option) any later version of
the Licence as published by the copyright holders of version
3.1 of the Licence document.
2. The exception is that you may use, copy, link, modify and distribute
under your own terms, binary object code versions of works based
on the Library.
3. If you copy code from files distributed under the terms of the GNU
General Public Licence or the GNU Library General Public Licence into a
copy of this library, as this licence permits, the exception does not
apply to the code that you add in this way. To avoid misleading anyone as
to the status of such modified files, you must delete this exception
notice from such code and/or adjust the licensing conditions notice
accordingly.
4. If you write modifications of your own for this library, it is your
choice whether to permit this exception to apply to your modifications.
If you do not wish that, you must delete the exception notice from such
code and/or adjust the licensing conditions notice accordingly.

177
Makefile.am Normal file
View File

@@ -0,0 +1,177 @@
lib_LTLIBRARIES = libjpeg.la libturbojpeg.la
libjpeg_la_LDFLAGS = -version-number 62:0:0 -no-undefined
libturbojpeg_la_LDFLAGS = -avoid-version -no-undefined
include_HEADERS = jerror.h jmorecfg.h jpeglib.h turbojpeg.h
nodist_include_HEADERS = jconfig.h
HDRS = jchuff.h jdct.h jdhuff.h jerror.h jinclude.h jmemsys.h jmorecfg.h \
jpegint.h jpeglib.h jversion.h jsimd.h jsimddct.h
libjpeg_la_SOURCES = $(HDRS) jcapimin.c jcapistd.c jccoefct.c jccolor.c \
jcdctmgr.c jchuff.c jcinit.c jcmainct.c jcmarker.c jcmaster.c \
jcomapi.c jcparam.c jcphuff.c jcprepct.c jcsample.c jctrans.c \
jdapimin.c jdapistd.c jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c \
jddctmgr.c jdhuff.c jdinput.c jdmainct.c jdmarker.c jdmaster.c \
jdmerge.c jdphuff.c jdpostct.c jdsample.c jdtrans.c jerror.c \
jfdctflt.c jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c \
jidctred.c jquant1.c jquant2.c jutils.c jmemmgr.c jmemnobs.c
libturbojpeg_la_SOURCES = $(libjpeg_la_SOURCES) turbojpegl.c turbojpeg.h \
turbojpeg-mapfile
if VERSION_SCRIPT
libturbojpeg_la_LDFLAGS += $(VERSION_SCRIPT_FLAG)$(srcdir)/turbojpeg-mapfile
endif
if WITH_SIMD
SUBDIRS = simd
libjpeg_la_LIBADD = simd/libsimd.la
libturbojpeg_la_LIBADD = simd/libsimd.la
else
libjpeg_la_SOURCES += jsimd_none.c
endif
TSTHDRS = rrutil.h rrtimer.h
noinst_PROGRAMS = jpgtest jpegut cjpeg djpeg jpegtran rdjpgcom wrjpgcom
jpgtest_SOURCES = $(TSTHDRS) jpgtest.cxx bmp.h bmp.c
jpgtest_LDADD = libturbojpeg.la
jpegut_SOURCES = $(TSTHDRS) jpegut.c bmp.h bmp.c
jpegut_LDADD = libturbojpeg.la
cjpeg_SOURCES = cdjpeg.h cderror.h cdjpeg.c cjpeg.c rdbmp.c rdgif.c \
rdppm.c rdswitch.c rdtarga.c
cjpeg_LDADD = libjpeg.la
cjpeg_CFLAGS = -DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED \
-DTARGA_SUPPORTED
djpeg_SOURCES = cdjpeg.h cderror.h cdjpeg.c djpeg.c rdcolmap.c rdswitch.c \
wrbmp.c wrgif.c wrppm.c wrtarga.c
djpeg_LDADD = libjpeg.la
djpeg_CFLAGS = -DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED \
-DTARGA_SUPPORTED
jpegtran_SOURCES = jpegtran.c rdswitch.c cdjpeg.c transupp.c transupp.h
jpegtran_LDADD = libjpeg.la
rdjpgcom_SOURCES = rdjpgcom.c
rdjpgcom_LDADD = libjpeg.la
wrjpgcom_SOURCES = wrjpgcom.c
wrjpgcom_LDADD = libjpeg.la
DISTMANS= cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 wrjpgcom.1
DOCS= README install.doc usage.doc wizard.doc example.c libjpeg.doc \
structure.doc coderules.doc filelist.doc jconfig.doc change.log \
README-turbo.txt rdrle.c wrrle.c LICENSE.txt LGPL.txt BUILDING.txt \
ChangeLog.txt
TESTFILES= testorig.jpg testorig.ppm testimg.bmp testimgflt.jpg \
testimgfst.jpg testimgint.jpg testimgp.jpg testimgfst.ppm testimgint.ppm
EXTRA_DIST = win release $(DOCS) $(DISTMANS) $(TESTFILES)
dist-hook:
rm -rf `find $(distdir) -name .svn`
test: testclean cjpeg djpeg jpegtran jpegut
./jpegut
./cjpeg -dct int -outfile testoutint.jpg $(srcdir)/testorig.ppm
./cjpeg -dct fast -opt -outfile testoutfst.jpg $(srcdir)/testorig.ppm
./cjpeg -dct float -outfile testoutflt.jpg $(srcdir)/testorig.ppm
cmp $(srcdir)/testimgint.jpg testoutint.jpg
cmp $(srcdir)/testimgfst.jpg testoutfst.jpg
cmp $(srcdir)/testimgflt.jpg testoutflt.jpg
./djpeg -dct int -fast -ppm -outfile testoutint.ppm $(srcdir)/testorig.jpg
./djpeg -dct fast -ppm -outfile testoutfst.ppm $(srcdir)/testorig.jpg
./djpeg -dct float -ppm -outfile testoutflt.ppm $(srcdir)/testorig.jpg
cmp $(srcdir)/testimgint.ppm testoutint.ppm
cmp $(srcdir)/testimgfst.ppm testoutfst.ppm
cmp $(srcdir)/testorig.ppm testoutflt.ppm
./djpeg -dct int -bmp -colors 256 -outfile testout.bmp $(srcdir)/testorig.jpg
cmp $(srcdir)/testimg.bmp testout.bmp
./cjpeg -dct int -progressive -outfile testoutp.jpg $(srcdir)/testorig.ppm
cmp $(srcdir)/testimgp.jpg testoutp.jpg
./jpegtran -outfile testoutt.jpg testoutp.jpg
cmp $(srcdir)/testimgint.jpg testoutt.jpg
testclean:
$(RM) testout*
$(RM) *_GRAYQ[0-9]*.bmp
$(RM) *_GRAYQ[0-9]*.ppm
$(RM) *_GRAYQ[0-9]*.jpg
$(RM) *_420Q[0-9]*.bmp
$(RM) *_420Q[0-9]*.ppm
$(RM) *_420Q[0-9]*.jpg
$(RM) *_422Q[0-9]*.bmp
$(RM) *_422Q[0-9]*.ppm
$(RM) *_422Q[0-9]*.jpg
$(RM) *_444Q[0-9]*.bmp
$(RM) *_444Q[0-9]*.ppm
$(RM) *_444Q[0-9]*.jpg
rpm: all
sh $(srcdir)/release/makerpm ${PACKAGE_NAME} ${VERSION} ${BUILD} \
${RPMARCH} ${srcdir}
srpm: dist-gzip
sh $(srcdir)/release/makesrpm ${PACKAGE_NAME} ${VERSION} ${BUILD} ${srcdir}
deb: all
sh $(srcdir)/release/makedpkg ${PACKAGE_NAME} ${VERSION} ${BUILD} \
${DEBARCH} ${srcdir}
if X86_64
udmg: all
sh $(srcdir)/release/makemacpkg ${PACKAGE_NAME} ${VERSION} ${BUILD} \
${srcdir} universal
endif
dmg: all
sh $(srcdir)/release/makemacpkg ${PACKAGE_NAME} ${VERSION} ${BUILD} ${srcdir}
if X86_64
sunpkg: all
sh $(srcdir)/release/makesunpkg ${PACKAGE_NAME} ${VERSION} ${BUILD} \
${DEBARCH} ${srcdir} $(CC) $(CXX) combined
nsi: all
makensis -nocd -DVERSION=$(VERSION) -DAPPNAME=libjpeg-turbo-gcc64 \
-DWLIBDIR=.libs -DWSRCDIR=$(srcdir) -DWBLDDIR=. -DWHDRDIR=. -DWIN64 \
-DPLATFORM="GCC 64-bit" -DGCC $(srcdir)/release/libjpeg-turbo.nsi
else
sunpkg: all
sh $(srcdir)/release/makesunpkg ${PACKAGE_NAME} ${VERSION} ${BUILD} \
${DEBARCH} ${srcdir} $(CC) $(CXX)
nsi: all
makensis -nocd -DVERSION=$(VERSION) -DAPPNAME=libjpeg-turbo-gcc \
-DWLIBDIR=.libs -DWSRCDIR=$(srcdir) -DWBLDDIR=. -DWHDRDIR=. \
-DPLATFORM="GCC" -DGCC $(srcdir)/release/libjpeg-turbo.nsi
endif

613
README
View File

@@ -1,335 +1,140 @@
libjpeg-turbo note: This is the legacy document from the original libjpeg v6b
release, which is included for reference. The Internet addresses given below
are likely non-functional. For more information about the libjpeg project,
please see http://www.ijg.org. For more information about libjpeg-turbo,
please see http://libjpeg-turbo.virtualgl.org.
The Independent JPEG Group's JPEG software
==========================================
README for release 4A of 18-Feb-93
==================================
README for release 6b of 27-Mar-1998
====================================
This distribution contains a BETA TEST release of the Independent JPEG
This distribution contains the sixth public release of the Independent JPEG
Group's free JPEG software. You are welcome to redistribute this software and
to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
For installation instructions, see file SETUP.
For usage instructions, see file USAGE (or the cjpeg.1 and djpeg.1 manual
pages; but USAGE contains a "hints" section not found in the manual pages).
Useful information can also be found in the JPEG FAQ (Frequently Asked
Questions) article; see ARCHIVE LOCATIONS below to obtain the FAQ article.
This software is still undergoing revision. Updated versions may be obtained
by FTP or UUCP to UUNET and other archive sites; see ARCHIVE LOCATIONS below
for details.
Serious users of this software (particularly those incorporating it into
larger programs) should contact jpeg-info@uunet.uu.net to be added to our
electronic mailing list. Mailing list members are notified of updates and
have a chance to participate in technical discussions, etc.
larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to
our electronic mailing list. Mailing list members are notified of updates
and have a chance to participate in technical discussions, etc.
This software is the work of Tom Lane, Philip Gladstone, Luis Ortiz, Lee
Crocker, George Phillips, Ge' Weijers, and other members of the Independent
JPEG Group.
This software is the work of Tom Lane, Philip Gladstone, Jim Boucher,
Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi,
Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG
Group.
IJG is not affiliated with the official ISO JPEG standards committee.
DISCLAIMER
==========
DOCUMENTATION ROADMAP
=====================
THIS SOFTWARE IS NOT COMPLETE NOR FULLY DEBUGGED. It is not guaranteed to be
useful for anything, nor to be compatible with subsequent releases, nor to be
an accurate implementation of the JPEG standard. (See LEGAL ISSUES for even
more disclaimers.)
This file contains the following sections:
Despite that, we believe that this software is pretty good, and if you find
any problems with it, we'd like to know about them. Please report problems
by e-mail to jpeg-info@uunet.uu.net.
OVERVIEW General description of JPEG and the IJG software.
LEGAL ISSUES Copyright, lack of warranty, terms of distribution.
REFERENCES Where to learn more about JPEG.
ARCHIVE LOCATIONS Where to find newer versions of this software.
RELATED SOFTWARE Other stuff you should get.
FILE FORMAT WARS Software *not* to get.
TO DO Plans for future IJG releases.
Other documentation files in the distribution are:
User documentation:
install.doc How to configure and install the IJG software.
usage.doc Usage instructions for cjpeg, djpeg, jpegtran,
rdjpgcom, and wrjpgcom.
*.1 Unix-style man pages for programs (same info as usage.doc).
wizard.doc Advanced usage instructions for JPEG wizards only.
change.log Version-to-version change highlights.
Programmer and internal documentation:
libjpeg.doc How to use the JPEG library in your own programs.
example.c Sample code for calling the JPEG library.
structure.doc Overview of the JPEG library's internal structure.
filelist.doc Road map of IJG files.
coderules.doc Coding style rules --- please read if you contribute code.
Please read at least the files install.doc and usage.doc. Useful information
can also be found in the JPEG FAQ (Frequently Asked Questions) article. See
ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
If you want to understand how the JPEG code works, we suggest reading one or
more of the REFERENCES, then looking at the documentation files (in roughly
the order listed) before diving into the code.
WHAT'S HERE
===========
OVERVIEW
========
This distribution contains C software to implement JPEG image compression and
This package contains C software to implement JPEG image compression and
decompression. JPEG (pronounced "jay-peg") is a standardized compression
method for full-color and gray-scale images. JPEG is intended for compressing
"real-world" scenes; cartoons and other non-realistic images are not its
strong suit. JPEG is lossy, meaning that the output image is not necessarily
identical to the input image. Hence you must not use JPEG if you have to have
identical output bits. However, on typical images of real-world scenes, very
good compression levels can be obtained with no visible change, and amazingly
high compression levels are possible if you can tolerate a low-quality image.
For more details, see the references, or just experiment with various
compression settings.
"real-world" scenes; line drawings, cartoons and other non-realistic images
are not its strong suit. JPEG is lossy, meaning that the output image is not
exactly identical to the input image. Hence you must not use JPEG if you
have to have identical output bits. However, on typical photographic images,
very good compression levels can be obtained with no visible change, and
remarkably high compression levels are possible if you can tolerate a
low-quality image. For more details, see the references, or just experiment
with various compression settings.
The software implements JPEG baseline and extended-sequential compression
processes. Provision is made for supporting all variants of these processes,
although some uncommon parameter settings aren't implemented yet. For legal
reasons, we are not distributing code for the arithmetic-coding process; see
LEGAL ISSUES. At present we have made no provision for supporting the
progressive, hierarchical, or lossless processes defined in the standard.
This software implements JPEG baseline, extended-sequential, and progressive
compression processes. Provision is made for supporting all variants of these
processes, although some uncommon parameter settings aren't implemented yet.
For legal reasons, we are not distributing code for the arithmetic-coding
variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting
the hierarchical or lossless processes defined in the standard.
We provide a set of library routines for reading and writing JPEG image files,
plus two sample applications "cjpeg" and "djpeg", which use the library to
perform conversion between JPEG and some other popular image file formats.
The library is intended to be reused in other applications.
In order to support file conversion and viewing software, we have included
considerable functionality beyond the bare JPEG coding/decoding capability;
for example, the color quantization modules are not strictly part of JPEG
decoding, but they are essential for output to colormapped file formats or
colormapped displays. These extra functions can be compiled out if not
required for a particular application.
colormapped displays. These extra functions can be compiled out of the
library if not required for a particular application. We have also included
"jpegtran", a utility for lossless transcoding between different JPEG
processes, and "rdjpgcom" and "wrjpgcom", two simple applications for
inserting and extracting textual comments in JFIF files.
The emphasis in designing this software has been on achieving portability and
flexibility, while also making it fast enough to be useful. In particular,
the software is not intended to be read as a tutorial on JPEG. (See the
REFERENCES section for introductory material.) While we hope that the entire
package will someday be industrial-strength code, much remains to be done in
performance tuning and in improving the capabilities of individual modules.
REFERENCES section for introductory material.) Rather, it is intended to
be reliable, portable, industrial-strength code. We do not claim to have
achieved that goal in every aspect of the software, but we strive for it.
This software can be used on several levels:
* As canned software for JPEG compression and decompression. Just edit the
Makefile and configuration files as needed (see file SETUP), compile and go.
Members of the Independent JPEG Group will improve the out-of-the-box
functionality and speed as time goes on.
* As the basis for other JPEG programs. For example, you could incorporate
the decompressor into a general image viewing package by replacing the
output module with write-to-screen functions. For an implementation on
specific hardware, you might want to replace some of the inner loops with
assembly code. For a non-command-line-driven system, you might want a
different user interface. (Members of the group will be producing Macintosh
and Amiga versions with more appropriate user interfaces, for example.)
* As a toolkit for experimentation with JPEG and JPEG-like algorithms. Most
of the individual decisions you might want to mess with are packaged up into
separate modules. For example, the details of color-space conversion and
subsampling techniques are each localized in one compressor and one
decompressor module. You'd probably also want to extend the user interface
to give you more detailed control over the JPEG compression parameters.
In particular, we welcome the use of this software as a component of commercial
products; no royalty is required.
ARCHIVE LOCATIONS
=================
[Version 4A is a beta-test release and will not be publicly archived.
The following paragraphs refer to the most recent official release.]
The "official" archive site for this software is ftp.uu.net (Internet
address 137.39.1.9 or 192.48.96.9). The most recent released version can
always be found there in directory graphics/jpeg. This particular version
will be archived as jpegsrc.v4.tar.Z. If you are on the Internet, you can
retrieve files from UUNET by anonymous FTP. If you don't have FTP access,
UUNET's archives are also available via UUCP; contact postmaster@uunet.uu.net
for information on retrieving files that way.
Numerous Internet sites maintain copies of the UUNET files; in particular,
you can probably find a copy at any site that archives comp.sources.misc
submissions. However, only ftp.uu.net is guaranteed to have the latest
official version.
You can also obtain this software from CompuServe, in the GRAPHSUPPORT forum
(GO PICS), library 15; this version will be file jpsrc4.zip. Again,
CompuServe is not guaranteed to have the very latest version.
The JPEG FAQ (Frequently Asked Questions) article is a useful source of
general information about JPEG. It is updated constantly and therefore
is not included in this distribution. The FAQ is posted every two weeks
to Usenet newsgroups comp.graphics, news.answers, and other groups. You
can always obtain the latest version from the news.answers archive at
rtfm.mit.edu (18.172.1.27). By FTP, fetch /pub/usenet/news.answers/jpeg-faq.
If you don't have FTP, send e-mail to mail-server@rtfm.mit.edu with body
"send usenet/news.answers/jpeg-faq".
SUPPORTING SOFTWARE
===================
You will probably want Jef Poskanzer's PBMPLUS image software, which provides
many useful operations on PPM-format image files. In particular, it can
convert PPM images to and from a wide range of other formats. You can FTP
this free software from export.lcs.mit.edu (contrib/pbmplus*.tar.Z) or
ftp.ee.lbl.gov (pbmplus*.tar.Z). Unfortunately PBMPLUS is not nearly as
portable as the JPEG software is; you are likely to have difficulty making it
work on any non-Unix machine.
If you are using X Windows you might want to use the xv or xloadimage viewers
to save yourself the trouble of converting PPM to some other format. Both of
these can be found in the contrib directory at export.lcs.mit.edu. Actually,
xv version 2.00 and up incorporates our software and thus can read and write
JPEG files directly. (NOTE: since xv internally reduces all images to 8
bits/pixel, a JPEG file written by xv will not be very high quality; and xv
cannot fully exploit a 24-bit display. These problems are expected to go away
in the next xv release, planned for early 1993. In the meantime, use
xloadimage for 24-bit displays.)
For DOS machines, Lee Crocker's free Piclab program is a useful companion to
the JPEG software. The latest version, currently 1.91, is available by FTP
from SIMTEL20 and its various mirror sites, file <msdos.graphics>piclb191.zip.
CompuServe also has it, in the same library as the JPEG software.
SOFTWARE THAT'S NO HELP AT ALL
==============================
Handmade Software's shareware PC program GIF2JPG produces files that are
totally incompatible with our programs. They use a proprietary format that is
an amalgam of GIF and JPEG representations. However, you can force GIF2JPG
to produce compatible files with its -j switch, and their decompression
program JPG2GIF can read our files (at least ones produced with our default
option settings).
Some commercial JPEG implementations are also incompatible as of this writing,
especially programs released before summer 1991. The root of the problem is
that the ISO JPEG committee failed to specify a concrete file format. Some
vendors "filled in the blanks" on their own, creating proprietary formats that
no one else could read. (For example, none of the early commercial JPEG
implementations for the Macintosh were able to exchange compressed files.)
The file format we have adopted is called JFIF (see REFERENCES). This format
has been agreed to by a number of major commercial JPEG vendors, and we expect
that it will become the de facto standard. JFIF is a minimal representation;
work is also going forward to incorporate JPEG compression into the TIFF 6.0
standard, for use in "high end" applications that need to record a lot of
additional data about an image. We intend to support TIFF 6.0 in the future.
We hope that these two formats will be sufficient and that other, incompatible
JPEG file formats will not proliferate.
Indeed, part of the reason for developing and releasing this free software is
to help force rapid convergence to de facto standards for JPEG file formats.
SUPPORT STANDARD, NON-PROPRIETARY FORMATS: demand JFIF or TIFF 6.0!
USING JPEG AS A SUBROUTINE IN A LARGER PROGRAM
==============================================
You can readily incorporate the JPEG compression and decompression routines in
a larger program. The file example.c provides a skeleton of the interface
routines you'll need for this purpose. Essentially, you replace jcmain.c (for
compression) and/or jdmain.c (for decompression) with your own code. Note
that the fewer JPEG options you allow the user to twiddle, the less code you
need; all the default options are set up automatically. (Alternately, if you
know a lot about JPEG or have a special application, you may want to twiddle
the default options even more extensively than jcmain/jdmain do.)
Most likely, you will want the uncompressed image to come from memory (for
compression) or go to memory or the screen (for decompression). For this
purpose you must provide image reading or writing routines that match the
interface used by the image file I/O modules (jrdXXX or jwrXXX); again,
example.c shows a skeleton of what is required. In this situation, you
won't need any of the non-JPEG image file I/O modules used by cjpeg and djpeg.
By default, any error detected inside the JPEG routines will cause a message
to be printed on stderr, followed by exit(). You can override this behavior
by supplying your own message-printing and/or error-exit routines; again,
example.c shows how.
We recommend you create libjpeg.a as shown in the Makefile, then link that
with your surrounding program. (If your linker is at all reasonable, only the
code you actually need will get loaded.) Include the files jconfig.h and
jpegdata.h in C files that need to call the JPEG routines.
CAUTION: some people have tried to compile JPEG and their surrounding code
with different compilers, e.g., cc for JPEG and c++ or gcc for the rest. This
is a Real Bad Move and you will deserve what happens to you if you try it.
(Hint: the parameter structures can get laid out differently with no warning.)
Read our "architecture" file for more info. If it seems to you that the
software structure doesn't accommodate what you want to do, please contact
the authors.
Beginning with version 3, we will endeavor to hold the interface described by
example.c constant, so that you can plug in updated versions of the JPEG code
just by recompiling. However, we can't guarantee this, especially if you
choose to twiddle any JPEG options not listed in example.c. Check the
CHANGELOG when installing any new version, and compare example.c against the
prior version. Recompile your calling software (don't just relink), as we may
add or subtract fields in the parameter structures.
REFERENCES
==========
We highly recommend reading one or more of these references before trying to
understand the innards of any JPEG software.
The best short technical introduction to the JPEG compression algorithm is
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
(Adjacent articles in that issue discuss MPEG motion picture compression,
applications of JPEG, and related topics.) If you don't have the CACM issue
handy, a PostScript file containing a revised version of the article is
available at ftp.uu.net, graphics/jpeg/wallace.ps.Z. The file (actually a
preprint for an article to appear in IEEE Trans. Consumer Electronics) omits
the sample images that appeared in CACM, but it includes corrections and some
added material. Note: the Wallace article is copyright ACM and IEEE, and it
may not be used for commercial purposes.
A somewhat less technical, more leisurely introduction to JPEG can be found in
"The Data Compression Book" by Mark Nelson, published by M&T Books (Redwood
City, CA), 1991, ISBN 1-55851-216-0. This book provides good explanations and
example C code for a multitude of compression methods including JPEG. It is
an excellent source if you are comfortable reading C code but don't know much
about data compression in general. The book's JPEG sample code is far from
industrial-strength, but when you are ready to look at a full implementation,
you've got one here...
A new textbook about JPEG is "JPEG Still Image Data Compression Standard" by
William B. Pennebaker and Joan L. Mitchell, published by Van Nostrand
Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95. This book includes the
complete text of the ISO JPEG standards (DIS 10918-1 and draft DIS 10918-2).
This is by far the most complete exposition of JPEG in existence, and I highly
recommend it. If you read the entire book, you will probably know more about
JPEG than I do.
The JPEG standard itself is not available electronically; you must order a
paper copy through ISO. (Unless you are concerned about having a certified
official copy, I recommend buying the Pennebaker and Mitchell book instead;
it's much cheaper and includes a great deal of useful explanatory material.)
In the US, copies of the standard may be ordered from ANSI Sales at (212)
642-4900. It's not cheap: as of 1992, Part 1 is $95 and Part 2 is $47, plus
7% shipping/handling. The standard is divided into two parts, Part 1 being
the actual specification, while Part 2 covers compliance testing methods.
As of early 1992, Part 1 has Draft International Standard status. It is
titled "Digital Compression and Coding of Continuous-tone Still Images, Part
1: Requirements and guidelines" and has document number ISO/IEC DIS 10918-1.
Part 2 is still at Committee Draft status. It is titled "Digital Compression
and Coding of Continuous-tone Still Images, Part 2: Compliance testing" and
has document number ISO/IEC CD 10918-2. (NOTE: I'm told that the final
version of Part 2 will differ considerably from the CD draft.)
The JPEG standard does not specify all details of an interchangeable file
format. For the omitted details we follow the "JFIF" conventions, revision
1.02. A copy of the JFIF spec is available from:
Literature Department
C-Cube Microsystems, Inc.
399A West Trimble Road
San Jose, CA 95131
(408) 944-6300
A PostScript version of this document is available at ftp.uu.net, file
graphics/jpeg/jfif.ps.Z. It can also be obtained by e-mail from the C-Cube
mail server, netlib@c3.pla.ca.us. Send the message "send jfif_ps from jpeg"
to the server to obtain the JFIF document; send the message "help" if you have
trouble.
The TIFF 6.0 file format specification can be obtained by FTP from sgi.com
(192.48.153.1), file graphics/tiff/TIFF6.ps.Z; or you can order a printed copy
from Aldus Corp. at (206) 628-6593. It should be noted that the TIFF 6.0 spec
of 3-June-92 has a number of serious problems in its JPEG features. A
clarification note will probably be needed to ensure that TIFF JPEG files are
compatible across different implementations. The IJG does not intend to
support TIFF 6.0 until these problems are resolved.
If you want to understand this implementation, start by reading the
"architecture" documentation file. Please read "codingrules" if you want to
contribute any code.
We welcome the use of this software as a component of commercial products.
No royalty is required, but we do ask for an acknowledgement in product
documentation, as described under LEGAL ISSUES.
LEGAL ISSUES
============
In plain English:
1. We don't promise that this software works. (But if you find any bugs,
please let us know!)
2. You can use this software for whatever you want. You don't have to pay us.
3. You may not pretend that you wrote this software. If you use it in a
program, you must acknowledge somewhere in your documentation that
you've used the IJG code.
In legalese:
The authors make NO WARRANTY or representation, either express or implied,
with respect to this software, its quality, accuracy, merchantability, or
fitness for a particular purpose. This software is provided "AS IS", and you,
its user, assume the entire risk as to its quality and accuracy.
This software is copyright (C) 1991, 1992, Thomas G. Lane.
This software is copyright (C) 1991-1998, Thomas G. Lane.
All Rights Reserved except as specified below.
Permission is hereby granted to use, copy, modify, and distribute this
@@ -346,6 +151,10 @@ the Independent JPEG Group".
full responsibility for any undesirable consequences; the authors accept
NO LIABILITY for damages of any kind.
These conditions apply to any software derived from or based on the IJG code,
not just to the unmodified library. If you use our work, you ought to
acknowledge us.
Permission is NOT granted for the use of any IJG author's name or company name
in advertising or publicity relating to this software or products derived from
it. This software may be referred to only as "the Independent JPEG Group's
@@ -362,21 +171,30 @@ ansi2knr.c is NOT covered by the above copyright and conditions, but instead
by the usual distribution terms of the Free Software Foundation; principally,
that you must include source code if you redistribute it. (See the file
ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part
of any program generated from the JPEG code, this does not limit you more than
of any program generated from the IJG code, this does not limit you more than
the foregoing paragraphs do.
The Unix configuration script "configure" was produced with GNU Autoconf.
It is copyright by the Free Software Foundation but is freely distributable.
The same holds for its supporting scripts (config.guess, config.sub,
ltconfig, ltmain.sh). Another support script, install-sh, is copyright
by M.I.T. but is also freely distributable.
It appears that the arithmetic coding option of the JPEG spec is covered by
patents owned by IBM and AT&T, as well as a pending Japanese patent of
Mitsubishi. Hence arithmetic coding cannot legally be used without obtaining
one or more licenses. For this reason, support for arithmetic coding has been
removed from the free JPEG software. (Since arithmetic coding provides only a
marginal gain over the unpatented Huffman mode, it is unlikely that very many
implementors will support it. If you do obtain the necessary licenses,
contact jpeg-info@uunet.uu.net for a copy of our arithmetic coding modules.)
patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot
legally be used without obtaining one or more licenses. For this reason,
support for arithmetic coding has been removed from the free JPEG software.
(Since arithmetic coding provides only a marginal gain over the unpatented
Huffman mode, it is unlikely that very many implementations will support it.)
So far as we are aware, there are no patent restrictions on the remaining
code.
The IJG distribution formerly included code to read and write GIF files.
To avoid entanglement with the Unisys LZW patent, GIF reading support has
been removed altogether, and the GIF writer has been simplified to produce
"uncompressed GIFs". This technique does not use the LZW algorithm; the
resulting GIF files are larger than usual, but are readable by all standard
GIF decoders.
We are required to state that
"The Graphics Interchange Format(c) is the Copyright property of
@@ -384,22 +202,191 @@ We are required to state that
CompuServe Incorporated."
REFERENCES
==========
We highly recommend reading one or more of these references before trying to
understand the innards of the JPEG software.
The best short technical introduction to the JPEG compression algorithm is
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
(Adjacent articles in that issue discuss MPEG motion picture compression,
applications of JPEG, and related topics.) If you don't have the CACM issue
handy, a PostScript file containing a revised version of Wallace's article is
available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually
a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
omits the sample images that appeared in CACM, but it includes corrections
and some added material. Note: the Wallace article is copyright ACM and IEEE,
and it may not be used for commercial purposes.
A somewhat less technical, more leisurely introduction to JPEG can be found in
"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by
M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides
good explanations and example C code for a multitude of compression methods
including JPEG. It is an excellent source if you are comfortable reading C
code but don't know much about data compression in general. The book's JPEG
sample code is far from industrial-strength, but when you are ready to look
at a full implementation, you've got one here...
The best full description of JPEG is the textbook "JPEG Still Image Data
Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published
by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp.
The book includes the complete text of the ISO JPEG standards (DIS 10918-1
and draft DIS 10918-2). This is by far the most complete exposition of JPEG
in existence, and we highly recommend it.
The JPEG standard itself is not available electronically; you must order a
paper copy through ISO or ITU. (Unless you feel a need to own a certified
official copy, we recommend buying the Pennebaker and Mitchell book instead;
it's much cheaper and includes a great deal of useful explanatory material.)
In the USA, copies of the standard may be ordered from ANSI Sales at (212)
642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI
doesn't take credit card orders, but Global does.) It's not cheap: as of
1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7%
shipping/handling. The standard is divided into two parts, Part 1 being the
actual specification, while Part 2 covers compliance testing methods. Part 1
is titled "Digital Compression and Coding of Continuous-tone Still Images,
Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS
10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of
Continuous-tone Still Images, Part 2: Compliance testing" and has document
numbers ISO/IEC IS 10918-2, ITU-T T.83.
Some extensions to the original JPEG standard are defined in JPEG Part 3,
a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG
currently does not support any Part 3 extensions.
The JPEG standard does not specify all details of an interchangeable file
format. For the omitted details we follow the "JFIF" conventions, revision
1.02. A copy of the JFIF spec is available from:
Literature Department
C-Cube Microsystems, Inc.
1778 McCarthy Blvd.
Milpitas, CA 95035
phone (408) 944-6300, fax (408) 944-6314
A PostScript version of this document is available by FTP at
ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text
version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing
the figures.
The TIFF 6.0 file format specification can be obtained by FTP from
ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme
found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
(Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or
from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision
of the TIFF spec will replace the 6.0 JPEG design with the Note's design.
Although IJG's own code does not support TIFF/JPEG, the free libtiff library
uses our library to implement TIFF/JPEG per the Note. libtiff is available
from ftp://ftp.sgi.com/graphics/tiff/.
ARCHIVE LOCATIONS
=================
The "official" archive site for this software is ftp.uu.net (Internet
address 192.48.96.9). The most recent released version can always be found
there in directory graphics/jpeg. This particular version will be archived
as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have
direct Internet access, UUNET's archives are also available via UUCP; contact
help@uunet.uu.net for information on retrieving files that way.
Numerous Internet sites maintain copies of the UUNET files. However, only
ftp.uu.net is guaranteed to have the latest official version.
You can also obtain this software in DOS-compatible "zip" archive format from
the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or
on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12
"JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net
release.
The JPEG FAQ (Frequently Asked Questions) article is a useful source of
general information about JPEG. It is updated constantly and therefore is
not included in this distribution. The FAQ is posted every two weeks to
Usenet newsgroups comp.graphics.misc, news.answers, and other groups.
It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/
and other news.answers archive sites, including the official news.answers
archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
with body
send usenet/news.answers/jpeg-faq/part1
send usenet/news.answers/jpeg-faq/part2
RELATED SOFTWARE
================
Numerous viewing and image manipulation programs now support JPEG. (Quite a
few of them use this library to do so.) The JPEG FAQ described above lists
some of the more popular free and shareware viewers, and tells where to
obtain them on Internet.
If you are on a Unix machine, we highly recommend Jef Poskanzer's free
PBMPLUS software, which provides many useful operations on PPM-format image
files. In particular, it can convert PPM images to and from a wide range of
other formats, thus making cjpeg/djpeg considerably more useful. The latest
version is distributed by the NetPBM group, and is available from numerous
sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/.
Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is;
you are likely to have difficulty making it work on any non-Unix machine.
A different free JPEG implementation, written by the PVRG group at Stanford,
is available from ftp://havefun.stanford.edu/pub/jpeg/. This program
is designed for research and experimentation rather than production use;
it is slower, harder to use, and less portable than the IJG code, but it
is easier to read and modify. Also, the PVRG code supports lossless JPEG,
which we do not. (On the other hand, it doesn't do progressive JPEG.)
FILE FORMAT WARS
================
Some JPEG programs produce files that are not compatible with our library.
The root of the problem is that the ISO JPEG committee failed to specify a
concrete file format. Some vendors "filled in the blanks" on their own,
creating proprietary formats that no one else could read. (For example, none
of the early commercial JPEG implementations for the Macintosh were able to
exchange compressed files.)
The file format we have adopted is called JFIF (see REFERENCES). This format
has been agreed to by a number of major commercial JPEG vendors, and it has
become the de facto standard. JFIF is a minimal or "low end" representation.
We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF
Technical Note #2) for "high end" applications that need to record a lot of
additional data about an image. TIFF/JPEG is fairly new and not yet widely
supported, unfortunately.
The upcoming JPEG Part 3 standard defines a file format called SPIFF.
SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should
be able to read the most common variant of SPIFF. SPIFF has some technical
advantages over JFIF, but its major claim to fame is simply that it is an
official standard rather than an informal one. At this point it is unclear
whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto
standard. IJG intends to support SPIFF once the standard is frozen, but we
have not decided whether it should become our default output format or not.
(In any case, our decoder will remain capable of reading JFIF indefinitely.)
Various proprietary file formats incorporating JPEG compression also exist.
We have little or no sympathy for the existence of these formats. Indeed,
one of the original reasons for developing this free software was to help
force convergence on common, open format standards for JPEG files. Don't
use a proprietary file format!
TO DO
=====
The next major release will probably be a significant rewrite to allow use of
this code in conjunction with Sam Leffler's free TIFF library (assuming the
bugs in the TIFF 6.0 specification get resolved).
The major thrust for v7 will probably be improvement of visual quality.
The current method for scaling the quantization tables is known not to be
very good at low Q values. We also intend to investigate block boundary
smoothing, "poor man's variable quantization", and other means of improving
quality-vs-file-size performance without sacrificing compatibility.
Many of the modules need fleshing out to provide more complete
implementations, or to provide faster paths for common cases.
Speeding things up is still high on our priority list.
In future versions, we are considering supporting some of the upcoming JPEG
Part 3 extensions --- principally, variable quantization and the SPIFF file
format.
We'd appreciate it if people would compile and check out the code on as wide a
variety of systems as possible, and report any portability problems
encountered (with solutions, if possible). Checks of file compatibility with
other JPEG implementations would also be of interest. Finally, we would
appreciate code profiles showing where the most time is spent, especially on
unusual systems.
As always, speeding things up is of great interest.
Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.

201
README-turbo.txt Executable file
View File

@@ -0,0 +1,201 @@
*******************************************************************************
** Background
*******************************************************************************
libjpeg-turbo is a high-speed version of libjpeg for x86 and x86-64 processors
which uses SIMD instructions (MMX, SSE2, etc.) to accelerate baseline JPEG
compression and decompression. libjpeg-turbo is generally 2-4x as fast
as the unmodified version of libjpeg, all else being equal.
libjpeg-turbo was originally based on libjpeg/SIMD by Miyasaka Masaru, but
the TigerVNC and VirtualGL projects made numerous enhancements to the codec,
including improved support for Mac OS X, 64-bit support, support for 32-bit
and big endian pixel formats, accelerated Huffman encoding/decoding, and
various bug fixes. The goal was to produce a fully open source codec that
could replace the partially closed source TurboJPEG/IPP codec used by VirtualGL
and TurboVNC. libjpeg-turbo generally performs in the range of 80-120% of
TurboJPEG/IPP. It is faster in some areas but slower in others.
It was decided to split libjpeg-turbo into a separate SDK so that other
projects could take advantage of this technology. The libjpeg-turbo shared
libraries can be used as drop-in replacements for libjpeg on most systems.
*******************************************************************************
** License
*******************************************************************************
Some of the optimizations to the Huffman encoder/decoder were borrowed from
VirtualGL, and thus the libjpeg-turbo distribution, as a whole, falls under the
wxWindows Library Licence, Version 3.1. A copy of this license can be found in
this directory under LICENSE.txt. The wxWindows Library License is based on
the LGPL but includes provisions which allow the Library to be statically
linked into proprietary libraries and applications without requiring the
resulting binaries to be distributed under the terms of the LGPL.
The rest of the source code, apart from these modifications, falls under a less
restrictive, BSD-style license (see README.)
*******************************************************************************
** Using libjpeg-turbo
*******************************************************************************
=============================
Replacing libjpeg at Run Time
=============================
If a Unix application is dynamically linked with libjpeg, then you can replace
libjpeg with libjpeg-turbo at run time by manipulating the LD_LIBRARY_PATH.
For instance:
[Using libjpeg]
> time cjpeg <vgl_5674_0098.ppm >vgl_5674_0098.jpg
real 0m0.392s
user 0m0.074s
sys 0m0.020s
[Using libjpeg-turbo]
> export LD_LIBRARY_PATH=/opt/libjpeg-turbo/{lib}:$LD_LIBRARY_PATH
> time cjpeg <vgl_5674_0098.ppm >vgl_5674_0098.jpg
real 0m0.109s
user 0m0.029s
sys 0m0.010s
NOTE: {lib} can be lib, lib32, lib64, or lib/amd64, depending on the O/S and
architecture.
System administrators can also replace the libjpeg sym links in /usr/{lib} with
links to the libjpeg dynamic library located in /opt/libjpeg-turbo/{lib}. This
will effectively accelerate every dynamically linked libjpeg application on the
system.
The Windows distribution of the libjpeg-turbo SDK installs jpeg62.dll into
c:\libjpeg-turbo\bin, and the PATH environment variable can be modified such
that this directory is searched before any others that might contain
jpeg62.dll. However, if jpeg62.dll also exists in an application's install
directory, then Windows will load the application's version of it first. Thus,
if an application ships with jpeg62.dll, then back up the application's version
of jpeg62.dll and copy c:\libjpeg-turbo\bin\jpeg62.dll into the application's
install directory to accelerate it.
The version of jpeg62.dll distributed in the libjpeg-turbo SDK requires the
Visual C++ 2008 C run time DLL (msvcr90.dll). This library ships with more
recent versions of Windows, but users of older versions can obtain it from the
Visual C++ 2008 Redistributable Package, which is available as a free download
from Microsoft's web site.
NOTE: Features of libjpeg which require passing a C run time structure, such
as a file handle, from an application to libjpeg will probably not work with
the distributed version of jpeg62.dll unless the application is also built to
use the Visual C++ 2008 C run time DLL. In particular, this affects
jpeg_stdio_dest() and jpeg_stdio_src().
Mac applications typically embed their own copies of libjpeg.62.dylib inside
the (hidden) application bundle, so it is not possible to globally replace
libjpeg on OS X systems. If an application uses a shared library version of
libjpeg, then it may be possible to replace the application's version of it.
This would generally involve copying libjpeg.62.dylib into the appropriate
place in the application bundle and using install_name_tool to repoint the
dylib to the new directory. This requires an advanced knowledge of OS X and
would not survive an upgrade or a re-install of the application. Thus, it is
not recommended for most users.
=======================
Replacing TurboJPEG/IPP
=======================
libjpeg-turbo is a drop-in replacement for the TurboJPEG/IPP SDK used by
VirtualGL 2.1.x (and prior) and TurboVNC. libjpeg-turbo contains a wrapper
library (TurboJPEG/OSS) that emulates the TurboJPEG API using libjpeg-turbo
instead of the closed source Intel Performance Primitives. You can replace the
TurboJPEG/IPP package on Linux systems with the libjpeg-turbo package in order
to make existing releases of VirtualGL 2.1.x and TurboVNC use the new codec at
run time. Note that the 64-bit libjpeg-turbo packages contain only 64-bit
binaries, whereas the TurboJPEG/IPP 64-bit packages contain both 64-bit and
32-bit binaries. Thus, to replace a TurboJPEG/IPP 64-bit package, install
both the 64-bit and 32-bit versions of libjpeg-turbo.
You can also build the VirtualGL 2.1.x and TurboVNC source code with
the libjpeg-turbo SDK instead of TurboJPEG/IPP. It should work identically.
libjpeg-turbo also includes static library versions of TurboJPEG/OSS, which
are used to build VirtualGL 2.2 and later.
========================================
Using libjpeg-turbo in Your Own Programs
========================================
For the most part, libjpeg-turbo should work identically to libjpeg, so in
most cases, an application can be built against libjpeg and then run against
libjpeg-turbo. On Unix systems, you can build against libjpeg-turbo instead
of libjpeg by setting
CPATH=/opt/libjpeg-turbo/include
and
LIBRARY_PATH=/opt/libjpeg-turbo/{lib}
({lib} = lib, lib32, lib64, or lib/amd64, as appropriate.)
If using Cygwin, then set
CPATH=/cygdrive/c/libjpeg-turbo-gcc[64]/include
and
LIBRARY_PATH=/cygdrive/c/libjpeg-turbo-gcc[64]/lib
If using MinGW, then set
CPATH=/c/libjpeg-turbo-gcc[64]/include
and
LIBRARY_PATH=/c/libjpeg-turbo-gcc[64]/lib
Building against libjpeg-turbo is useful, for instance, if you want to build an
application that leverages the libjpeg-turbo colorspace extensions (see below.)
On Linux and Solaris systems, you would still need to manipulate the
LD_LIBRARY_PATH or sym links appropriately to use libjpeg-turbo at run time.
On such systems, you can pass -R /opt/libjpeg-turbo/{lib} to the linker to
force the use of libjpeg-turbo at run time rather than libjpeg (also useful if
you want to leverage the colorspace extensions), or you can link against the
libjpeg-turbo static library.
To force a Linux, Solaris, or MinGW application to link against the static
version of libjpeg-turbo, you can use the following linker options:
-Wl,-Bstatic -ljpeg -Wl,-Bdynamic
On OS X, simply add /opt/libjpeg-turbo/{lib}/libjpeg.a to the linker command
line (this also works on Linux and Solaris.)
To build Visual C++ applications using libjpeg-turbo, add
c:\libjpeg-turbo[64]\include to your system or user INCLUDE environment
variable and c:\libjpeg-turbo[64]\lib to your system or user LIB environment
variable, and then link against either jpeg.lib (to use jpeg62.dll) or
jpeg-static.lib (to use the static version of libjpeg-turbo.)
=====================
Colorspace Extensions
=====================
libjpeg-turbo includes extensions which allow JPEG images to be compressed
directly from (and decompressed directly to) buffers which use BGR, BGRA,
RGBA, ABGR, and ARGB pixel ordering. This is implemented with six new
colorspace constants:
JCS_EXT_RGB /* red/green/blue */
JCS_EXT_RGBX /* red/green/blue/x */
JCS_EXT_BGR /* blue/green/red */
JCS_EXT_BGRX /* blue/green/red/x */
JCS_EXT_XBGR /* x/blue/green/red */
JCS_EXT_XRGB /* x/red/green/blue */
Setting cinfo.in_color_space (compression) or cinfo.out_color_space
(decompression) to one of these values will cause libjpeg-turbo to read the
red, green, and blue values from (or write them to) the appropriate position in
the pixel when YUV conversion is performed.
Your application can check for the existence of these extensions at compile
time with:
#ifdef JCS_EXTENSIONS
At run time, attempting to use these extensions with a version of libjpeg
that doesn't support them will result in a "Bogus input colorspace" error.

550
SETUP
View File

@@ -1,550 +0,0 @@
SETUP instructions for the Independent JPEG Group's JPEG software
=================================================================
This file explains how to configure and compile the JPEG software. We have
tried to make this software extremely portable and flexible, so that it can be
adapted to almost any environment. The downside of this decision is that the
installation process is not very automatic; you will need at least a little
familiarity with C programming and program build procedures for your system.
This file contains general instructions, then sections of specific hints for
certain systems. You may save yourself considerable time if you scan the
whole file before starting to do anything.
Before installing the software you must unpack the distributed source code.
Since you are reading this file, you have probably already succeeded in this
task. However, there is one potential trap if you are on a non-Unix system:
you may need to convert these files to the local standard text file format
(for example, if you are on MS-DOS you probably have to convert LF end-of-line
to CR/LF). If so, apply the conversion to all the files EXCEPT those whose
names begin with "test". The test files contain binary data; if you change
them in any way then the self-test will give bad results.
STEP 1: PREPARE A MAKEFILE
==========================
First, select a makefile and copy it to "Makefile" (or whatever your version
of make uses as the default makefile name; for example, "makefile.mak" for
old versions of Borland C). We include several standard makefiles in the
distribution:
makefile.ansi: for Unix systems with ANSI-compatible C compilers.
makefile.unix: for Unix systems with non-ANSI C compilers.
makefile.mc5: for Microsoft C 5.x under MS-DOS.
makefile.mc6: for Microsoft C 6.x and up under MS-DOS.
makefile.bcc: for Borland C (Turbo C) under MS-DOS.
makefile.icc: for Intel's Code Builder C under MS-DOS.
makefile.manx: for Manx Aztec C on Amigas.
makefile.sas: for SAS C on Amigas.
makcjpeg.st: project file for Atari ST/STE/TT Pure C or Turbo C.
makdjpeg.st: project file for Atari ST/STE/TT Pure C or Turbo C.
makljpeg.st: project file for Atari ST/STE/TT Pure C or Turbo C.
makefile.mms: for VAX/VMS systems with MMS.
makefile.vms: for VAX/VMS systems without MMS.
If you don't see a makefile for your system, we recommend starting from either
makefile.ansi or makefile.unix, depending on whether your compiler accepts
ANSI C or not. Actually you should start with makefile.ansi whenever your
compiler supports ANSI-style function definitions; you don't need full ANSI
compatibility. The difference between the two makefiles is that makefile.unix
preprocesses the source code to convert function definitions to old-style C.
(Our thanks to Peter Deutsch of Aladdin Enterprises for the ansi2knr program.)
If you don't know whether your compiler supports ANSI-style function
definitions, then take a look at ckconfig.c. It is a test program that will
help you figure out this fact, as well as some other facts you'll need in
later steps. You must compile and execute ckconfig.c by hand; the makefiles
don't provide any support for this. ckconfig.c may not compile the first try
(in fact, the whole idea is for it to fail if anything is going to). If you
get compile errors, fix them by editing ckconfig.c according to the directions
given in ckconfig.c. Once you get it to run, select a makefile according to
the advice it prints out, and make any other changes it recommends.
Look over the selected Makefile and adjust options as needed. In particular
you may want to change the CC and CFLAGS definitions. For instance, if you
are using GCC, set CC=gcc. If you had to use any compiler switches to get
ckconfig.c to work, make sure the same switches are in CFLAGS.
If you are on a system that doesn't use makefiles, you'll need to set up
project files (or whatever you do use) to compile all the source files and
link them into executable files cjpeg and djpeg. See the file lists in any of
the makefiles to find out which files go into each program. As a last resort,
you can make a batch script that just compiles everything and links it all
together; makefile.vms is an example of this (it's for VMS systems that have
no make-like utility).
STEP 2: EDIT JCONFIG.H
======================
Look over jconfig.h and adjust #defines to reflect the properties of your
system and C compiler. If you prefer, you can usually leave jconfig.h
unmodified and add -Dsymbol switches to the Makefile's CFLAGS definition.
(This is already done if you used a compiler-specific makefile in step 1.)
However, putting the switches in the Makefile is a bad idea if you are going
to incorporate the JPEG software into other programs --- you'd need to include
the same -D switches in the other programs' Makefiles. Better to change
jconfig.h.
If you have an ANSI-compliant C compiler, no changes should be necessary
except perhaps for RIGHT_SHIFT_IS_UNSIGNED and TWO_FILE_COMMANDLINE. For
older compilers other changes may be needed, depending on what ANSI features
are supported.
If you don't know enough about C programming to understand the questions in
jconfig.h, then use ckconfig.c to figure out what to change. (See description
of ckconfig.c in step 1.)
A note about TWO_FILE_COMMANDLINE: defining this selects the command line
syntax in which the input and output files are both named on the command line.
If it's not defined, the output image goes to standard output, and the input
can optionally come from standard input. You MUST use two-file style on any
system that doesn't cope well with binary data fed through stdin/stdout; this
is true for most MS-DOS compilers, for example. If you're not on a Unix
system, it's probably safest to assume you need two-file style. (But if your
compiler provides either the Posix-standard fdopen() library routine or a
Microsoft-compatible setmode() routine, you can use the Unix command line
style, by defining USE_FDOPEN or USE_SETMODE respectively.)
STEP 3: SELECT SYSTEM-DEPENDENT FILES
=====================================
A few places in the JPEG software are so system-dependent that we have to
provide several different implementations and let you select the one you need.
The only system-dependent file in the current version is jmemsys.c. This file
controls use of temporary files for big images that won't fit in main memory.
You'll notice there is no file named jmemsys.c in the distribution; you must
select one of the provided versions and copy, rename, or link it to jmemsys.c.
Here are the provided versions:
jmemansi.c This is a reasonably portable version that should
work on most ANSI and near-ANSI C compilers. It uses
the ANSI-standard library routine tmpfile(), which not
all non-ANSI systems have. On some systems tmpfile()
may put the temporary file in a non-optimal location;
if you don't like what it does, use jmemname.c.
jmemname.c This version constructs the temp file name by itself.
For anything except a Unix machine, you'll need to
configure the select_file_name() routine appropriately;
see the comments near the head of jmemname.c.
If you use this version, define NEED_SIGNAL_CATCHER
in jconfig.h or in the Makefile to make sure the temp
files are removed if the program is aborted.
jmemnobs.c (That stands for No Backing Store :-). This will
compile on almost any system, but it assumes you
have enough main memory or virtual memory to hold
the biggest images you need to work with.
jmemdos.c This should be used in most MS-DOS installations; see
the system-specific notes about MS-DOS for more info.
IMPORTANT: if you use this, also copy jmemdos.h to
jmemsys.h, replacing the standard version. ALSO,
include the assembly file jmemdosa.asm in the programs.
(This last is already done if you used one of the
supplied MS-DOS-specific makefiles.)
If you have plenty of (real or virtual) main memory, just use jmemnobs.c.
"Plenty" means at least ten bytes for every pixel in the largest images
you plan to process, so a lot of systems don't meet this criterion.
If yours doesn't, try jmemansi.c first. If that doesn't compile, you'll have
to use jmemname.c; be sure to adjust select_file_name() for local conditions.
You may also need to change unlink() to remove() in close_backing_store().
Except with jmemnobs.c, you need to adjust the #define DEFAULT_MAX_MEM to a
reasonable value for your system (either by editing jmemsys.c, or by adding
a -D switch to the Makefile). This value limits the amount of data space the
program will attempt to allocate. Code and static data space isn't counted,
so the actual memory needs for cjpeg or djpeg are typically 100 to 150Kb more
than the max-memory setting. Larger max-memory settings reduce the amount of
I/O needed to process a large image, but too large a value can result in
"insufficient memory" failures. On most Unix machines (and other systems with
virtual memory), just set DEFAULT_MAX_MEM to several million and forget it.
At the other end of the spectrum, for MS-DOS machines you probably can't go
much above 300K to 400K. (On MS-DOS the value refers to conventional memory;
extended/expanded memory is handled separately by jmemdos.c.)
STEP 4: MAKE
============
Now you should be able to "make" the software.
If you have trouble with missing system include files or inclusion of the
wrong ones, look at jinclude.h (or use ckconfig.c, if you are not a C expert).
If your compiler complains about big_sarray_control and big_barray_control
being undefined structures, you should be able to shut it up by adding
-DINCOMPLETE_TYPES_BROKEN to CFLAGS (or add #define INCOMPLETE_TYPES_BROKEN
to jconfig.h). If you don't have a getenv() library routine, define NO_GETENV.
There are a fair number of routines that do not use all of their parameters;
some compilers will issue warnings about this, which you can ignore. Any
other warning deserves investigation.
STEP 5: TEST
============
As a quick test of functionality we've included a small sample image in
several forms:
testorig.jpg A reduced section of the well-known Lenna picture.
testimg.ppm The output of djpeg testorig.jpg
testimg.gif The output of djpeg -gif testorig.jpg
testimg.jpg The output of cjpeg testimg.ppm
(The two .jpg files aren't identical since JPEG is lossy.) If you can
generate duplicates of the testimg.* files then you probably have working
programs.
With most of the makefiles, "make test" will perform the necessary
comparisons. If you started with makefile.ansi or makefile.unix, and you
defined TWO_FILE_COMMANDLINE, then change the makefile's test script to use
two-file syntax (i.e., delete the ">" character from the invocations of cjpeg
and djpeg). The other makefiles will work with either command-line syntax.
If you're using a makefile that doesn't provide the test option, run djpeg and
cjpeg by hand to generate testout.ppm, testout.gif, and testout.jpg, then
compare these to testimg.* with whatever binary file comparison tool you have.
The files should be bit-for-bit identical.
If the cjpeg test run fails with "Missing Huffman code table entry", it's a
good bet that you needed to define RIGHT_SHIFT_IS_UNSIGNED. Go back to step 2
and run ckconfig.c. (This is a good plan for any other test failure, too.)
If you are using Unix (one-file) command line style on a non-Unix system,
it's a good idea to check that binary I/O through stdin/stdout actually works.
You should get the same results from "djpeg <testorig.jpg >out.ppm" as from
"djpeg -outfile out.ppm testorig.jpg". Note that the non-Unix makefiles use
the latter style and therefore do not exercise stdin/stdout. If this test
fails, try recompiling jcmain.c & jdmain.c with USE_SETMODE and/or USE_FDOPEN.
If your choice of jmemsys.c was anything other than jmemnobs.c, you should
test that temporary-file usage works. Try "djpeg -gif -max 0 testorig.jpg"
and make sure its output matches testimg.gif. If you have any really large
images handy, try compressing them with -optimize and/or decompressing with
-gif to make sure your DEFAULT_MAX_MEM setting is not too large.
NOTE: this is far from an exhaustive test of the JPEG software; some modules,
such as 1-pass color quantization, are not exercised at all. It's just a quick
test to give you some confidence that you haven't missed something major.
STEP 6: INSTALLATION
====================
Once you're done with the above steps, you can install the software by copying
the executable files (cjpeg and djpeg) to wherever you normally install
programs. On Unix systems, you'll also want to put cjpeg.1 and djpeg.1 in the
corresponding manual directory. (The makefiles don't support this step since
there's such a wide variety of installation procedures on different systems.)
To learn to use the programs, read the file USAGE (or manual pages cjpeg(1)
and djpeg(1) on Unix). Note that the man pages cjpeg.1/djpeg.1 only describe
the Unix-style command line syntax; if you want to use these files with a
version that uses two-file command line syntax, you'll have to modify the text
accordingly. The USAGE file describes both styles.
OPTIMIZATION
============
Unless you own a Cray, you'll probably be interested in making the JPEG
software go as fast as possible. This section covers some machine-dependent
optimizations you may want to try. We suggest that before trying any of this,
you first get the basic installation to pass the self-test (step 5 above).
Repeat the self-test after any optimization to make sure that you haven't
broken anything.
The JPEG DCT routines perform a lot of multiplications. These multiplications
must yield 32-bit results, but none of their input values are more than 16
bits wide. On many machines, notably the 680x0 and 80x86 CPUs, a 16x16=>32
bit multiply instruction is faster than a full 32x32=>32 bit multiply.
Unfortunately there is no portable way to specify such a multiplication in C,
but some compilers can generate one when you use the right combination of
casts. See the MULTIPLY macro definitions in jfwddct.c and jrevdct.c.
If your compiler makes "int" be 32 bits and "short" be 16 bits, defining
SHORTxSHORT_32 is fairly likely to work. When experimenting with alternate
definitions, be sure to test not only whether the code still works (use the
self-test step), but also whether it is actually faster --- on some compilers,
alternate definitions may compute the right answer, yet be slower than the
default. Timing cjpeg on a large PPM input file is the best way to check
this, as the DCT will be the largest fraction of the runtime in that mode.
(Note: some of the distributed compiler-specific makefiles already contain
-D switches to select an appropriate MULTIPLY definition.)
If access to "short" arrays is slow on your machine, it may be a win to define
type DCTELEM as int rather than as JCOEF (which is normally defined as short).
This will cause the DCT routines to operate on int arrays instead of short
arrays. If shorts are slow and you have lots of memory to burn, you might
even make JCOEF itself be int.
If your compiler can compile function calls in-line, make sure the INLINE
macro in jconfig.h is defined as the keyword that marks a function
inline-able. Some compilers have a switch that tells the compiler to inline
any function it thinks is profitable (e.g., -finline-functions for gcc).
Enabling such a switch is likely to make the compiled code bigger but faster.
In general, it's worth trying the maximum optimization level of your compiler,
and experimenting with any optional optimizations such as loop unrolling.
(Unfortunately, far too many compilers have optimizer bugs ... be prepared to
back off if the code fails self-test.) If you do any experimentation along
these lines, please report the optimal settings to jpeg-info@uunet.uu.net so
we can mention them in future releases. Be sure to specify your machine and
compiler version.
OPTIONAL STUFF
==============
Progress monitor:
If you like, you can #define PROGRESS_REPORT (in jconfig.h or in the Makefile)
to enable display of percent-done progress reports. The routines provided in
jcmain.c/jdmain.c merely print percentages to stderr, but you can customize
them to do something fancier.
Utah RLE file format support:
We distribute the software with support for RLE image files (Utah Raster
Toolkit format) disabled, because the RLE support won't compile without the
Utah library. If you have URT version 3.0, you can enable RLE support as
follows:
1. #define RLE_SUPPORTED in jconfig.h or in the Makefile.
2. Add a -I option to CFLAGS in the Makefile for the directory
containing the URT .h files (typically the "include"
subdirectory of the URT distribution).
3. Add -L... -lrle to LDLIBS in the Makefile, where ... specifies
the directory containing the URT "librle.a" file (typically the
"lib" subdirectory of the URT distribution).
JPEG library:
If you want to incorporate the JPEG code as subroutines in a larger program,
we recommend that you make libjpeg.a, then link that into your surrounding
program. See file README for more info.
CAUTION: When you use the JPEG code as subroutines, we recommend that you make
any required configuration changes by modifying jconfig.h, not by adding -D
switches to the Makefile. Otherwise you must be sure to provide the same -D
switches when compiling any program that includes the JPEG .h files, to ensure
that the parameter structures are interpreted the same way. (This is only
critical for the first few symbols mentioned in jconfig.h, down through
NEED_FAR_POINTERS.)
Removing code:
If you need to make a smaller version of the JPEG software, some optional
functions can be removed at compile time. See the xxx_SUPPORTED #defines in
jconfig.h. If at all possible, we recommend that you leave in decoder support
for all valid JPEG files, to ensure that you can read anyone's output.
Restricting your encoder, or removing optional functions like block smoothing,
won't hurt compatibility. Taking out support for image file formats that you
don't use is the most painless way to make the programs smaller.
NOTES FOR SPECIFIC SYSTEMS
==========================
We welcome reports on changes needed for systems not mentioned here.
Submit 'em to jpeg-info@uunet.uu.net. Also, if ckconfig.c is wrong about
how to configure the JPEG software for your system, please let us know.
Amiga:
Makefiles are provided for Manx Aztec C and SAS C. I have also heard from
people who have compiled with the free DICE compiler, using makefile.ansi as a
starting point (set "CC= dcc" and "CFLAGS= -c -DAMIGA -DTWO_FILE_COMMANDLINE
-DNEED_SIGNAL_CATCHER" in the makefile). For all compilers, we recommend you
use jmemname.c as the system-dependent memory manager. Assuming you have
-DAMIGA in the makefile, jmemname.c will put temporary files in JPEGTMP:.
Change jmemname.c if you don't like this.
Atari:
The project files provided should work as-is with Pure C. For Turbo C, change
library filenames "PC..." to "TC..." in the project files for cjpeg.ttp and
djpeg.ttp. Don't forget to select a jmemsys.c file, see Step 3 (we recommend
jmemansi.c). Also adjust the DEFAULT_MAX_MEM setting --- you probably want it
to be a couple hundred K less than your normal free memory. Note that you
must make jpeg.lib before making cjpeg.ttp or cjpeg.ttp. You'll have to
perform the self-test (Step 5) by hand.
There is a bug in some older versions of the Turbo C library which causes the
space used by temporary files created with "tmpfile()" not to be freed after
an abnormal program exit. If you check your disk afterwards, you will find
cluster chains that are allocated but not used by a file. This should not
happen in cjpeg or djpeg, since we enable a signal catcher to explicitly close
temp files before exiting. But if you use the JPEG library with your own
code, be sure to supply a signal catcher, or else use a different
system-dependent memory manager.
Cray:
Should you be so fortunate as to be running JPEG on a Cray YMP, there is a
compiler bug in Cray's Standard C versions prior to 3.1. You'll need to
insert a line reading "#pragma novector" just before the loop
for (i = 1; i <= (int) htbl->bits[l]; i++)
huffsize[p++] = (char) l;
in fix_huff_tbl (in V4A, line 42 of jchuff.c and line 39 of jdhuff.c). The
usual symptom of not adding this line is a core-dump. See Cray's SPR 48222.
HP/Apollo DOMAIN:
With system release 10.4 or later, makefile.ansi should work OK. If you have
version 10.3.anything, you need to figure out whether you have the ANSI C
compiler (version 6.7 or later) and whether you've installed the ANSI C
include files (if so, the first line of <stdio.h> will mention ANSI C).
If you have the ANSI C compiler but not the ANSI C include files, use
makefile.ansi and add -DNONANSI_INCLUDES to CFLAGS. If you have both,
then makefile.ansi should work as is. If neither, use makefile.unix.
HP-UX:
If you have HP-UX 7.05 or later with the "software development" C compiler,
then you can use makefile.ansi. Add "-Aa" to the CFLAGS line in the makefile
to make the compiler work in ANSI mode. If you have a pre-7.05 system, or if
you are using the non-ANSI C compiler delivered with a minimum HP-UX 8.0
system, then you must use makefile.unix (and do NOT add -Aa). Also, adding
"-lmalloc" to LDLIBS is recommended if you have libmalloc.a (it seems not to
be present in minimum 8.0).
On HP 9000 series 800 machines, the HP C compiler is buggy in revisions prior
to A.08.07. If you get complaints about "not a typedef name", you'll have to
convert the code to K&R style (i.e., use makefile.unix).
Macintosh MPW:
We don't directly support MPW in the current release, but Larry Rosenstein
reports that the JPEG code can be ported without very much trouble. There's
useful notes and conversion scripts in his kit for porting PBMPLUS to MPW.
You can obtain the kit by FTP to ftp.apple.com, file /pub/lsr/pbmplus-port*.
Macintosh Think C:
You'll have to prepare project files for cjpeg and djpeg; we don't include
those in the distribution since they are not text files. The COBJECTS and
DOBJECTS lists in makefile.unix show which files should be included in each
project. Also add the ANSI and Unix C libraries in a separate segment. You
may need to divide the JPEG files into more than one segment; you can do this
pretty much as you please.
If you have Think C version 5.0 you need not modify jconfig.h; instead you
should turn on both the ANSI Settings and Language Extensions option buttons
(so that both __STDC__ and THINK_C are predefined). With version 4.0 you must
edit jconfig.h. (You can #define HAVE_STDC to do the right thing for all
options except const; you must also #define const.)
jcmain and jdmain are set up to provide the usual command-line interface
by means of Think's ccommand() library routine. A more Mac-like interface
is in the works.
MS-DOS, generic comments:
The JPEG code is designed to be compiled with 80x86 "small" or "medium" memory
models (i.e., data pointers are 16 bits unless explicitly declared "far"; code
pointers can be either size). You should be able to use small model to
compile cjpeg or djpeg by itself, but you will probably have to go to medium
model if you include the JPEG code in a larger application. This shouldn't
hurt performance much. You *will* take a noticeable performance hit if you
compile in a large-data memory model, and you should avoid "huge" model if at
all possible. Be sure that NEED_FAR_POINTERS is defined by jconfig.h or by
the Makefile if you use a small-data model; be sure it is NOT defined if you
use a large-data memory model. (As distributed, jconfig.h defines
NEED_FAR_POINTERS if MSDOS is defined.)
The DOS-specific memory manager, jmemdos.c, should be used if possible.
(Be sure to install jmemdos.h and jmemdosa.asm along with it.) If you
can't use jmemdos.c for some reason --- for example, because you don't have
a Microsoft-compatible assembler to assemble jmemdosa.asm --- you'll have
to fall back to jmemansi.c or jmemname.c. IMPORTANT: if you use either of
the latter two files, you will have to compile in a large-data memory model
in order to get the right stdio library. Too bad.
None of the above advice applies if you are using a 386 flat-memory-space
environment, such as DJGPP or Watcom C. (And you should use one if you have
it, as performance will be much better than 8086-compatible code!) For
flat-memory-space compilers, do NOT define NEED_FAR_POINTERS, and do NOT use
jmemdos.c. Use jmemnobs.c if the environment supplies adequate virtual
memory, otherwise use jmemansi.c or jmemname.c.
Most MS-DOS compilers treat stdin/stdout as text files, so you must use
two-file command line style. But if your compiler has either fdopen() or
setmode(), you can use one-file style if you like. To do this, define
USE_FDOPEN or USE_SETMODE so that stdin/stdout will be set to binary mode.
(USE_SETMODE seems to work with more DOS compilers than USE_FDOPEN.) You
should test that I/O through stdin/stdout produces the same results as I/O
to explicitly named files... the "make test" procedures in the DOS-specific
makefiles do NOT use stdin/stdout.
If you add more switches to CFLAGS in the DOS-specific makefiles, you are
likely to run up against DOS' 128-byte command line length limit. In that
case, remove some "-Dsymbol" switches from CFLAGS and instead put
corresponding "#define symbol" lines at the head of jinclude.h.
MS-DOS, Borland C:
Be sure to convert all the source files to DOS text format (CR/LF newlines).
Although Borland C will often work OK with unmodified Unix (LF newlines)
source files, sometimes it will give bogus compile errors.
"Illegal character '#'" is the most common such error.
Some versions of Borland's MAKE erroneously display the warning message about
creating jmemsys.c, even after you have done so. If this happens to you,
delete the four lines beginning with "jmemsys.c:" from the Makefile.
If you want one-file command line style, define USE_SETMODE. fdopen() does
not work correctly.
MS-DOS, DJGPP:
Use makefile.ansi and jmemnobs.c, and put "-UMSDOS" in CFLAGS to undo the
compiler's automatic definition of MSDOS. Also put either "-DUSE_SETMODE" or
"-DTWO_FILE_COMMANDLINE" in CFLAGS, depending on whether you prefer one-file
or two-file command line style. You'll also need to put the object-file lists
into response files in order to circumvent DOS's 128-byte command line length
limit at the final linking step.
MS-DOS, Microsoft C:
Old versions of MS C fail with an "out of macro expansion space" error
because they can't cope with the macro TRACEMS8 (defined in jpegdata.h).
If this happens to you, the easiest solution is to change TRACEMS8 to
expand to nothing. You'll lose the ability to dump out JPEG coefficient
tables with djpeg -debug -debug, but at least you can compile.
Original MS C 6.0 is buggy; it compiles incorrect code unless you turn off
optimization (remove -O from CFLAGS). That problem seems to have been fixed
in 6.00A and later versions. 6.00A still generates a bogus "conditional
expression is constant" warning in jrdppm.c, but the emitted code seems OK.
If you want one-file command line style, define USE_SETMODE. fdopen() does
not work correctly, at least not in 6.00A.
SGI:
Use makefile.ansi, but set "AR2= ar -ts" rather than "AR2= ranlib". Also
make any changes recommended by ckconfig.c.
Sun:
Don't forget to add -DBSD to CFLAGS. If you are using GCC on SunOS 4.0.1 or
earlier, you will need to add -DNONANSI_INCLUDES to CFLAGS (your compiler may
be ANSI, but your system include files aren't). I've gotten conflicting
reports on whether this is still necessary on SunOS 4.1 or later.

308
USAGE
View File

@@ -1,308 +0,0 @@
USAGE instructions for the Independent JPEG Group's JPEG software
=================================================================
INTRODUCTION
This distribution contains software to implement JPEG image compression and
decompression. JPEG (pronounced "jay-peg") is a standardized compression
method for full-color and gray-scale images. JPEG is designed to handle
"real-world" scenes, for example scanned photographs. Cartoons, line
drawings, and other non-realistic images are not JPEG's strong suit; on this
sort of material you may get poor image quality and/or little compression.
JPEG is lossy, meaning that the output image is not necessarily identical to
the input image. Hence you should not use JPEG if you have to have identical
output bits. However, on typical real-world images, very good compression
levels can be obtained with no visible change, and amazingly high compression
is possible if you can tolerate a low-quality image. You can trade off image
quality against file size by adjusting the compressor's "quality" setting.
This file describes usage of the standard programs "cjpeg" and "djpeg" that
can be built directly from the distributed C code. See the README file for
hints on incorporating the JPEG software into other programs.
If you are on a Unix machine you may prefer to read the Unix-style manual
pages in files cjpeg.1 and djpeg.1. But also see the HINTS section below,
which is not present in either manual page.
NOTE: the switch syntax has been redesigned since the v3 release of
cjpeg/djpeg. Switch names are now words instead of single letters.
GENERAL USAGE
We provide two programs, cjpeg to compress an image file into JPEG format,
and djpeg to decompress a JPEG file back into a conventional image format.
On Unix-like systems, you say:
cjpeg [switches] [imagefile] >jpegfile
or
djpeg [switches] [jpegfile] >imagefile
The programs read the specified input file, or standard input if none is
named. They always write to standard output (with trace/error messages to
standard error). These conventions are handy for piping images between
programs.
On most non-Unix systems, you say:
cjpeg [switches] imagefile jpegfile
or
djpeg [switches] jpegfile imagefile
i.e., both the input and output files are named on the command line. This
style is a little more foolproof, and it loses no functionality if you don't
have pipes. (You can get this style on Unix too, if you prefer, by defining
TWO_FILE_COMMANDLINE when you compile the programs; see SETUP.)
You can also say:
cjpeg [switches] -outfile jpegfile imagefile
or
djpeg [switches] -outfile imagefile jpegfile
This syntax works on all systems, so it is useful for scripts.
The currently supported image file formats are: PPM (PBMPLUS color format),
PGM (PBMPLUS gray-scale format), GIF, Targa, and RLE (Utah Raster Toolkit
format). (RLE is supported only if the URT library is available.)
cjpeg recognizes the input image format automatically, with the exception
of some Targa-format files. You have to tell djpeg which format to generate.
The only JPEG file format currently supported is the JFIF format. Support for
the TIFF 6.0 JPEG format will probably be added at some future date.
All switch names may be abbreviated; for example, -grayscale may be written
-gray or -gr. Most of the "basic" switches can be abbreviated to as little as
one letter. Upper and lower case are equivalent (-GIF is the same as -gif).
British spellings are also accepted (e.g., -greyscale), though for brevity
these are not mentioned below.
CJPEG DETAILS
The basic command line switches for cjpeg are:
-quality N Scale quantization tables to adjust image quality.
Quality is 0 (worst) to 100 (best); default is 75.
(See below for more info.)
-grayscale Create monochrome JPEG file from color input.
Be sure to use this switch when compressing a grayscale
GIF file, because cjpeg isn't bright enough to notice
whether a GIF file uses only shades of gray. By
saying -grayscale, you'll get a smaller JPEG file that
takes less time to process.
-optimize Perform optimization of entropy encoding parameters.
Without this, default encoding parameters are used.
-optimize usually makes the JPEG file a little smaller,
but cjpeg runs somewhat slower and needs much more
memory. Image quality and speed of decompression are
unaffected by -optimize.
-targa Input file is Targa format. Targa files that contain
an "identification" field will not be automatically
recognized by cjpeg; for such files you must specify
-targa to make cjpeg treat the input as Targa format.
The -quality switch lets you trade off compressed file size against quality of
the reconstructed image: the higher the quality setting, the larger the JPEG
file, and the closer the output image will be to the original input. Normally
you want to use the lowest quality setting (smallest file) that decompresses
into something visually indistinguishable from the original image. For this
purpose the quality setting should be between 50 and 95; the default of 75 is
often about right. If you see defects at -quality 75, then go up 5 or 10
counts at a time until you are happy with the output image. (The optimal
setting will vary from one image to another.)
-quality 100 will generate a quantization table of all 1's, eliminating loss
in the quantization step (but there is still information loss in subsampling,
as well as roundoff error). This setting is mainly of interest for
experimental purposes. Quality values above about 95 are NOT recommended for
normal use; the compressed file size goes up dramatically for hardly any gain
in output image quality.
In the other direction, quality values below 50 will produce very small files
of low image quality. Settings around 5 to 10 might be useful in preparing an
index of a large image library, for example. Try -quality 2 (or so) for some
amusing Cubist effects. (Note: quality values below about 25 generate 2-byte
quantization tables, which are considered optional in the JPEG standard.
cjpeg emits a warning message when you give such a quality value, because
some commercial JPEG programs may be unable to decode the resulting file.)
Switches for advanced users:
-maxmemory N Set limit for amount of memory to use in processing
large images. Value is in thousands of bytes, or
millions of bytes if "M" is attached to the number.
For example, -max 4m selects 4000000 bytes. If more
space is needed, temporary files will be used.
-restart N Emit a JPEG restart marker every N MCU rows, or every
N MCU blocks if "B" is attached to the number.
-restart 0 (the default) means no restart markers.
-smooth N Smooth the input image to eliminate dithering noise.
N, ranging from 1 to 100, indicates the strength of
smoothing. 0 (the default) means no smoothing.
-verbose Enable debug printout. More -v's give more printout.
or -debug Also, version information is printed at startup.
The -restart option inserts extra markers that allow a JPEG decoder to
resynchronize after a transmission error. Without restart markers, any damage
to a compressed file will usually ruin the image from the point of the error
to the end of the image; with restart markers, the damage is usually confined
to the portion of the image up to the next restart marker. Of course, the
restart markers occupy extra space. We recommend -restart 1 for images that
will be transmitted across unreliable networks such as Usenet.
The -smooth option filters the input to eliminate fine-scale noise. This is
often useful when converting GIF files to JPEG: a moderate smoothing factor of
10 to 50 gets rid of dithering patterns in the input file, resulting in a
smaller JPEG file and a better-looking image. Too large a smoothing factor
will visibly blur the image, however.
Switches for wizards:
-arithmetic Use arithmetic coding rather than Huffman coding.
(Not currently supported for legal reasons.)
-nointerleave Generate noninterleaved JPEG file (not yet supported).
-qtables file Use the quantization tables given in the specified
file. The file should contain one to four tables
(64 values each) as plain text. Comments preceded by
'#' may be included in the file. The tables are
implicitly numbered 0,1,etc. If -quality N is also
specified, the values in the file are scaled according
to cjpeg's quality scaling curve.
-sample HxV[,...] Set JPEG sampling factors. If you specify
fewer H/V pairs than there are components, the
remaining components are set to 1x1 sampling. The
default setting is equivalent to "-sample 2x2".
The "wizard" switches are intended for experimentation with JPEG. If you
don't know what you are doing, DON'T USE THEM. You can easily produce files
with worse image quality and/or poorer compression than you'll get from the
default settings. Furthermore, these switches should not be used when making
files intended for general use, because not all JPEG implementations will
support unusual JPEG parameter settings.
DJPEG DETAILS
The basic command line switches for djpeg are:
-colors N Reduce image to at most N colors. This reduces the
or -quantize N number of colors used in the output image, so that it
can be displayed on a colormapped display or stored in
a colormapped file format. For example, if you have
an 8-bit display, you'd need to reduce to 256 or fewer
colors. (-colors is the recommended name, -quantize
is provided only for backwards compatibility.)
-gif Select GIF output format. Since GIF does not support
more than 256 colors, -colors 256 is assumed (unless
you specify a smaller number of colors).
-pnm Select PBMPLUS (PPM/PGM) output format (this is the
default format). PGM is emitted if the JPEG file is
gray-scale or if -grayscale is specified; otherwise
PPM is emitted.
-rle Select RLE output format. (Requires URT library.)
-targa Select Targa output format. Gray-scale format is
emitted if the JPEG file is gray-scale or if
-grayscale is specified; otherwise, colormapped format
is emitted if -colors is specified; otherwise, 24-bit
full-color format is emitted.
Switches for advanced users:
-blocksmooth Perform cross-block smoothing. This is slow, quite
memory-intensive, and only seems to improve the image
at very low quality settings (-quality 10 to 20 or so).
At normal quality settings it may make things worse.
-grayscale Force gray-scale output even if JPEG file is color.
Useful for viewing on monochrome displays.
-maxmemory N Set limit for amount of memory to use in processing
large images. Value is in thousands of bytes, or
millions of bytes if "M" is attached to the number.
For example, -max 4m selects 4000000 bytes. If more
space is needed, temporary files will be used.
-nodither Do not use dithering in color quantization.
By default, Floyd-Steinberg dithering is applied when
quantizing colors, but on some images dithering may
result in objectionable "graininess". If that
happens, you can turn off dithering with -nodither.
-nodither is ignored unless you also say -colors N.
-onepass Use one-pass instead of two-pass color quantization.
The one-pass method is faster and needs less memory,
but it produces a lower-quality image. -onepass is
ignored unless you also say -colors N. Also,
the one-pass method is always used for gray-scale
output (the two-pass method is no improvement then).
-verbose Enable debug printout. More -v's give more printout.
or -debug Also, version information is printed at startup.
HINTS
Color GIF files are not the ideal input for JPEG; JPEG is really intended for
compressing full-color (24-bit) images. In particular, don't try to convert
cartoons, line drawings, and other images that have only a few distinct
colors. GIF works great on these, JPEG does not. If you want to convert a
GIF to JPEG, you should experiment with cjpeg's -quality and -smooth options
to get a satisfactory conversion. -smooth 10 or so is often helpful.
Avoid running an image through a series of JPEG compression/decompression
cycles. Image quality loss will accumulate; after ten or so cycles the image
may be noticeably worse than it was after one cycle. It's best to use a
lossless format while manipulating an image, then convert to JPEG format when
you are ready to file the image away.
The -optimize option to cjpeg is worth using when you are making a "final"
version for posting or archiving. It's also a win when you are using low
quality settings to make very small JPEG files; the percentage improvement
is often a lot more than it is on larger files.
When making images to be posted on Usenet, we recommend using cjpeg's option
-restart 1. This option limits the damage done to a compressed image by
netnews transmission errors.
The default memory usage limit (-maxmemory) is set when the software is
compiled. If you get an "insufficient memory" error, try specifying a smaller
-maxmemory value, even -maxmemory 0 to use the absolute minimum space. You
may want to recompile with a smaller default value if this happens often.
On machines that have "environment" variables, you can define the environment
variable JPEGMEM to set the default memory limit. The value is specified as
described for the -maxmemory switch. JPEGMEM overrides the default value
specified when the program was compiled, and itself is overridden by an
explicit -maxmemory switch.
On MS-DOS machines, -maxmemory is the amount of main (conventional) memory to
use. (Extended or expanded memory is also used if available.) Most
DOS-specific versions of this software do their own memory space estimation
and do not need -maxmemory.
djpeg with two-pass color quantization requires a good deal of memory; on
MS-DOS machines it may run out of memory even with -maxmemory 0. In that case
you can still decompress, with some loss of image quality, by specifying
-onepass for one-pass quantization.
If more space is needed than will fit in the available main memory (as
determined by -maxmemory), temporary files will be used. (MS-DOS versions
will try to get extended or expanded memory first.) The temporary files are
often rather large: in typical cases they occupy three bytes per pixel, for
example 3*800*600 = 1.44Mb for an 800x600 image. If you don't have enough
free disk space, leave out -optimize (for cjpeg) or specify -onepass (for
djpeg). On MS-DOS, the temporary files are created in the directory named by
the TMP or TEMP environment variable, or in the current directory if neither
of those exist. Amiga implementations put the temp files in the directory
named by JPEGTMP:, so be sure to assign JPEGTMP: to a disk partition with
adequate free space.

136
acinclude.m4 Normal file
View File

@@ -0,0 +1,136 @@
# AC_PROG_NASM
# --------------------------
# Check that NASM exists and determine flags
AC_DEFUN([AC_PROG_NASM],[
AC_CHECK_PROGS(NASM, [nasm nasmw])
test -z "$NASM" && AC_MSG_ERROR([no nasm (Netwide Assembler) found])
AC_MSG_CHECKING([for object file format of host system])
case "$host_os" in
cygwin* | mingw* | pw32* | interix*)
case "$host_cpu" in
x86_64)
objfmt='Win64-COFF'
;;
*)
objfmt='Win32-COFF'
;;
esac
;;
msdosdjgpp* | go32*)
objfmt='COFF'
;;
os2-emx*) # not tested
objfmt='MSOMF' # obj
;;
linux*coff* | linux*oldld*)
objfmt='COFF' # ???
;;
linux*aout*)
objfmt='a.out'
;;
linux*)
case "$host_cpu" in
x86_64)
objfmt='ELF64'
;;
*)
objfmt='ELF'
;;
esac
;;
freebsd* | netbsd* | openbsd*)
if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
objfmt='BSD-a.out'
else
case "$host_cpu" in
x86_64)
objfmt='ELF64'
;;
*)
objfmt='ELF'
;;
esac
fi
;;
solaris* | sunos* | sysv* | sco*)
case "$host_cpu" in
x86_64)
objfmt='ELF64'
;;
*)
objfmt='ELF'
;;
esac
;;
darwin* | rhapsody* | nextstep* | openstep* | macos*)
case "$host_cpu" in
x86_64)
objfmt='Mach-O64'
;;
*)
objfmt='Mach-O'
;;
esac
;;
*)
objfmt='ELF ?'
;;
esac
AC_MSG_RESULT([$objfmt])
if test "$objfmt" = 'ELF ?'; then
objfmt='ELF'
AC_MSG_WARN([unexpected host system. assumed that the format is $objfmt.])
fi
AC_MSG_CHECKING([for object file format specifier (NAFLAGS) ])
case "$objfmt" in
MSOMF) NAFLAGS='-fobj -DOBJ32';;
Win32-COFF) NAFLAGS='-fwin32 -DWIN32';;
Win64-COFF) NAFLAGS='-fwin64 -DWIN64 -D__x86_64__';;
COFF) NAFLAGS='-fcoff -DCOFF';;
a.out) NAFLAGS='-faout -DAOUT';;
BSD-a.out) NAFLAGS='-faoutb -DAOUT';;
ELF) NAFLAGS='-felf -DELF';;
ELF64) NAFLAGS='-felf64 -DELF -D__x86_64__';;
RDF) NAFLAGS='-frdf -DRDF';;
Mach-O) NAFLAGS='-fmacho -DMACHO';;
Mach-O64) NAFLAGS='-fmacho64 -DMACHO -D__x86_64__';;
esac
AC_MSG_RESULT([$NAFLAGS])
AC_SUBST([NAFLAGS])
AC_MSG_CHECKING([whether the assembler ($NASM $NAFLAGS) works])
cat > conftest.asm <<EOF
[%line __oline__ "configure"
section .text
global _main,main
_main:
main: xor eax,eax
ret
]EOF
try_nasm='$NASM $NAFLAGS -o conftest.o conftest.asm'
if AC_TRY_EVAL(try_nasm) && test -s conftest.o; then
AC_MSG_RESULT(yes)
else
echo "configure: failed program was:" >&AC_FD_CC
cat conftest.asm >&AC_FD_CC
rm -rf conftest*
AC_MSG_RESULT(no)
AC_MSG_ERROR([installation or configuration problem: assembler cannot create object files.])
fi
AC_MSG_CHECKING([whether the linker accepts assembler output])
try_nasm='${CC-cc} -o conftest${ac_exeext} $LDFLAGS conftest.o $LIBS 1>&AC_FD_CC'
if AC_TRY_EVAL(try_nasm) && test -s conftest${ac_exeext}; then
rm -rf conftest*
AC_MSG_RESULT(yes)
else
rm -rf conftest*
AC_MSG_RESULT(no)
AC_MSG_ERROR([configuration problem: maybe object file format mismatch.])
fi
])

View File

@@ -1,477 +0,0 @@
/* Copyright (C) 1989, 1991 Aladdin Enterprises. All rights reserved.
Distributed by Free Software Foundation, Inc.
This file is part of Ghostscript.
Ghostscript is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
to anyone for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing. Refer
to the Ghostscript General Public License for full details.
Everyone is granted permission to copy, modify and redistribute
Ghostscript, but only under the conditions described in the Ghostscript
General Public License. A copy of this license is supposed to have been
given to you along with Ghostscript so you can know your rights and
responsibilities. It should be in a file named COPYING. Among other
things, the copyright notice and this notice must be preserved on all
copies. */
/*
---------- Here is the GhostScript file COPYING, referred to above ----------
----- These terms do NOT apply to the JPEG software itself; see README ------
GHOSTSCRIPT GENERAL PUBLIC LICENSE
(Clarified 11 Feb 1988)
Copyright (C) 1988 Richard M. Stallman
Everyone is permitted to copy and distribute verbatim copies of this
license, but changing it is not allowed. You can also use this wording
to make the terms for other programs.
The license agreements of most software companies keep you at the
mercy of those companies. By contrast, our general public license is
intended to give everyone the right to share Ghostscript. To make sure
that you get the rights we want you to have, we need to make
restrictions that forbid anyone to deny you these rights or to ask you
to surrender the rights. Hence this license agreement.
Specifically, we want to make sure that you have the right to give
away copies of Ghostscript, that you receive source code or else can get
it if you want it, that you can change Ghostscript or use pieces of it
in new free programs, and that you know you can do these things.
To make sure that everyone has such rights, we have to forbid you to
deprive anyone else of these rights. For example, if you distribute
copies of Ghostscript, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must tell them their rights.
Also, for our own protection, we must make certain that everyone finds
out that there is no warranty for Ghostscript. If Ghostscript is
modified by someone else and passed on, we want its recipients to know
that what they have is not what we distributed, so that any problems
introduced by others will not reflect on our reputation.
Therefore we (Richard M. Stallman and the Free Software Foundation,
Inc.) make the following terms which say what you must do to be allowed
to distribute or change Ghostscript.
COPYING POLICIES
1. You may copy and distribute verbatim copies of Ghostscript source
code as you receive it, in any medium, provided that you conspicuously
and appropriately publish on each copy a valid copyright and license
notice "Copyright (C) 1989 Aladdin Enterprises. All rights reserved.
Distributed by Free Software Foundation, Inc." (or with whatever year is
appropriate); keep intact the notices on all files that refer to this
License Agreement and to the absence of any warranty; and give any other
recipients of the Ghostscript program a copy of this License Agreement
along with the program. You may charge a distribution fee for the
physical act of transferring a copy.
2. You may modify your copy or copies of Ghostscript or any portion of
it, and copy and distribute such modifications under the terms of
Paragraph 1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating
that you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish,
that in whole or in part contains or is a derivative of Ghostscript
or any part thereof, to be licensed at no charge to all third
parties on terms identical to those contained in this License
Agreement (except that you may choose to grant more extensive
warranty protection to some or all third parties, at your option).
c) You may charge a distribution fee for the physical act of
transferring a copy, and you may at your option offer warranty
protection in exchange for a fee.
Mere aggregation of another unrelated program with this program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other program under the scope of these terms.
3. You may copy and distribute Ghostscript (or a portion or derivative
of it, under Paragraph 2) in object code or executable form under the
terms of Paragraphs 1 and 2 above provided that you also do one of the
following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal
shipping charge) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
For an executable file, complete source code means all the source code for
all modules it contains; but, as a special exception, it need not include
source code for modules which are standard libraries that accompany the
operating system on which the executable file runs.
4. You may not copy, sublicense, distribute or transfer Ghostscript
except as expressly provided under this License Agreement. Any attempt
otherwise to copy, sublicense, distribute or transfer Ghostscript is
void and your rights to use the program under this License agreement
shall be automatically terminated. However, parties who have received
computer software programs from you with this License Agreement will not
have their licenses terminated so long as such parties remain in full
compliance.
5. If you wish to incorporate parts of Ghostscript into other free
programs whose distribution conditions are different, write to the Free
Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not
yet worked out a simple rule that can be stated here, but we will often
permit this. We will be guided by the two goals of preserving the free
status of all derivatives of our free software and of promoting the
sharing and reuse of software.
Your comments and suggestions about our licensing policies and our
software are welcome! Please contact the Free Software Foundation,
Inc., 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296.
NO WARRANTY
BECAUSE GHOSTSCRIPT IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD
M. STALLMAN, ALADDIN ENTERPRISES, L. PETER DEUTSCH, AND/OR OTHER PARTIES
PROVIDE GHOSTSCRIPT "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF GHOSTSCRIPT IS WITH
YOU. SHOULD GHOSTSCRIPT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
NECESSARY SERVICING, REPAIR OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., L. PETER DEUTSCH, ALADDIN
ENTERPRISES, AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE
GHOSTSCRIPT AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING
ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GHOSTSCRIPT, EVEN IF YOU
HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM
BY ANY OTHER PARTY.
-------------------- End of file COPYING ------------------------------
*/
/* ansi2knr.c */
/* Convert ANSI function declarations to K&R syntax */
#include <stdio.h>
#include <ctype.h>
#ifdef BSD
#include <strings.h>
#define strchr index
#else
#ifdef VMS
extern char *strcat(), *strchr(), *strcpy(), *strupr();
extern int strcmp(), strlen(), strncmp();
#else
#include <string.h>
#endif
#endif
#ifdef MSDOS
#include <malloc.h>
#else
#ifdef VMS
extern char *malloc();
extern void free();
#else
extern char *malloc();
extern int free();
#endif
#endif
/* Usage:
ansi2knr input_file output_file
* If no output_file is supplied, output goes to stdout.
* There are no error messages.
*
* ansi2knr recognizes functions by seeing a non-keyword identifier
* at the left margin, followed by a left parenthesis,
* with a right parenthesis as the last character on the line.
* It will recognize a multi-line header if the last character
* on each line but the last is a left parenthesis or comma.
* These algorithms ignore whitespace and comments, except that
* the function name must be the first thing on the line.
* The following constructs will confuse it:
- Any other construct that starts at the left margin and
follows the above syntax (such as a macro or function call).
- Macros that tinker with the syntax of the function header.
*/
/* Scanning macros */
#define isidchar(ch) (isalnum(ch) || (ch) == '_')
#define isidfirstchar(ch) (isalpha(ch) || (ch) == '_')
main(argc, argv)
int argc;
char *argv[];
{ FILE *in, *out;
#define bufsize 5000 /* arbitrary size */
char *buf;
char *line;
switch ( argc )
{
default:
printf("Usage: ansi2knr input_file [output_file]\n");
exit(0);
case 2:
out = stdout; break;
case 3:
out = fopen(argv[2], "w");
if ( out == NULL )
{ fprintf(stderr, "Cannot open %s\n", argv[2]);
exit(1);
}
}
in = fopen(argv[1], "r");
if ( in == NULL )
{ fprintf(stderr, "Cannot open %s\n", argv[1]);
exit(1);
}
fprintf(out, "#line 1 \"%s\"\n", argv[1]);
buf = malloc(bufsize);
line = buf;
while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
{ switch ( test1(buf) )
{
case 1: /* a function */
convert1(buf, out);
break;
case -1: /* maybe the start of a function */
line = buf + strlen(buf);
if ( line != buf + (bufsize - 1) ) /* overflow check */
continue;
/* falls through */
default: /* not a function */
fputs(buf, out);
break;
}
line = buf;
}
if ( line != buf ) fputs(buf, out);
free(buf);
fclose(out);
fclose(in);
return 0;
}
/* Skip over space and comments, in either direction. */
char *
skipspace(p, dir)
register char *p;
register int dir; /* 1 for forward, -1 for backward */
{ for ( ; ; )
{ while ( isspace(*p) ) p += dir;
if ( !(*p == '/' && p[dir] == '*') ) break;
p += dir; p += dir;
while ( !(*p == '*' && p[dir] == '/') )
{ if ( *p == 0 ) return p; /* multi-line comment?? */
p += dir;
}
p += dir; p += dir;
}
return p;
}
/*
* Write blanks over part of a string.
*/
int
writeblanks(start, end)
char *start;
char *end;
{ char *p;
for ( p = start; p < end; p++ ) *p = ' ';
return 0;
}
/*
* Test whether the string in buf is a function definition.
* The string may contain and/or end with a newline.
* Return as follows:
* 0 - definitely not a function definition;
* 1 - definitely a function definition;
* -1 - may be the beginning of a function definition,
* append another line and look again.
*/
int
test1(buf)
char *buf;
{ register char *p = buf;
char *bend;
char *endfn;
int contin;
if ( !isidfirstchar(*p) )
return 0; /* no name at left margin */
bend = skipspace(buf + strlen(buf) - 1, -1);
switch ( *bend )
{
case ')': contin = 1; break;
case '(':
case ',': contin = -1; break;
default: return 0; /* not a function */
}
while ( isidchar(*p) ) p++;
endfn = p;
p = skipspace(p, 1);
if ( *p++ != '(' )
return 0; /* not a function */
p = skipspace(p, 1);
if ( *p == ')' )
return 0; /* no parameters */
/* Check that the apparent function name isn't a keyword. */
/* We only need to check for keywords that could be followed */
/* by a left parenthesis (which, unfortunately, is most of them). */
{ static char *words[] =
{ "asm", "auto", "case", "char", "const", "double",
"extern", "float", "for", "if", "int", "long",
"register", "return", "short", "signed", "sizeof",
"static", "switch", "typedef", "unsigned",
"void", "volatile", "while", 0
};
char **key = words;
char *kp;
int len = endfn - buf;
while ( (kp = *key) != 0 )
{ if ( strlen(kp) == len && !strncmp(kp, buf, len) )
return 0; /* name is a keyword */
key++;
}
}
return contin;
}
int
convert1(buf, out)
char *buf;
FILE *out;
{ char *endfn = strchr(buf, '(') + 1;
register char *p;
char **breaks;
unsigned num_breaks = 2; /* for testing */
char **btop;
char **bp;
char **ap;
top: p = endfn;
breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
if ( breaks == 0 )
{ /* Couldn't allocate break table, give up */
fprintf(stderr, "Unable to allocate break table!\n");
fputs(buf, out);
return -1;
}
btop = breaks + num_breaks * 2 - 2;
bp = breaks;
/* Parse the argument list */
do
{ int level = 0;
char *end = NULL;
if ( bp >= btop )
{ /* Filled up break table. */
/* Allocate a bigger one and start over. */
free((char *)breaks);
num_breaks <<= 1;
goto top;
}
*bp++ = p;
/* Find the end of the argument */
for ( ; end == NULL; p++ )
{ switch(*p)
{
case ',': if ( !level ) end = p; break;
case '(': level++; break;
case ')': if ( --level < 0 ) end = p; break;
case '/': p = skipspace(p, 1) - 1; break;
default: ;
}
}
p--; /* back up over terminator */
/* Find the name being declared. */
/* This is complicated because of procedure and */
/* array modifiers. */
for ( ; ; )
{ p = skipspace(p - 1, -1);
switch ( *p )
{
case ']': /* skip array dimension(s) */
case ')': /* skip procedure args OR name */
{ int level = 1;
while ( level )
switch ( *--p )
{
case ']': case ')': level++; break;
case '[': case '(': level--; break;
case '/': p = skipspace(p, -1) + 1; break;
default: ;
}
}
if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
{ /* We found the name being declared */
while ( !isidfirstchar(*p) )
p = skipspace(p, 1) + 1;
goto found;
}
break;
default: goto found;
}
}
found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
{ p++;
if ( bp == breaks + 1 ) /* sole argument */
writeblanks(breaks[0], p);
else
writeblanks(bp[-1] - 1, p);
bp--;
}
else
{ while ( isidchar(*p) ) p--;
*bp++ = p+1;
}
p = end;
}
while ( *p++ == ',' );
*bp = p;
/* Make a special check for 'void' arglist */
if ( bp == breaks+2 )
{ p = skipspace(breaks[0], 1);
if ( !strncmp(p, "void", 4) )
{ p = skipspace(p+4, 1);
if ( p == breaks[2] - 1 )
{ bp = breaks; /* yup, pretend arglist is empty */
writeblanks(breaks[0], p + 1);
}
}
}
/* Put out the function name */
p = buf;
while ( p != endfn ) putc(*p, out), p++;
/* Put out the declaration */
for ( ap = breaks+1; ap < bp; ap += 2 )
{ p = *ap;
while ( isidchar(*p) ) putc(*p, out), p++;
if ( ap < bp - 1 ) fputs(", ", out);
}
fputs(") ", out);
/* Put out the argument declarations */
for ( ap = breaks+2; ap <= bp; ap += 2 ) (*ap)[-1] = ';';
fputs(breaks[0], out);
free((char *)breaks);
return 0;
}

File diff suppressed because it is too large Load Diff

370
bmp.c Normal file
View File

@@ -0,0 +1,370 @@
/* Copyright (C)2004 Landmark Graphics Corporation
* Copyright (C)2005 Sun Microsystems, Inc.
*
* This library is free software and may be redistributed and/or modified under
* the terms of the wxWindows Library License, Version 3.1 or (at your option)
* any later version. The full license is in the LICENSE.txt file included
* with this distribution.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* wxWindows Library License for more details.
*/
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#include "./rrutil.h"
#include "./bmp.h"
#ifndef BI_BITFIELDS
#define BI_BITFIELDS 3L
#endif
#ifndef BI_RGB
#define BI_RGB 0L
#endif
#define BMPHDRSIZE 54
typedef struct _bmphdr
{
unsigned short bfType;
unsigned int bfSize;
unsigned short bfReserved1, bfReserved2;
unsigned int bfOffBits;
unsigned int biSize;
int biWidth, biHeight;
unsigned short biPlanes, biBitCount;
unsigned int biCompression, biSizeImage;
int biXPelsPerMeter, biYPelsPerMeter;
unsigned int biClrUsed, biClrImportant;
} bmphdr;
static const char *__bmperr="No error";
static const int ps[BMPPIXELFORMATS]={3, 4, 3, 4, 4, 4};
static const int roffset[BMPPIXELFORMATS]={0, 0, 2, 2, 3, 1};
static const int goffset[BMPPIXELFORMATS]={1, 1, 1, 1, 2, 2};
static const int boffset[BMPPIXELFORMATS]={2, 2, 0, 0, 1, 3};
#define _throw(m) {__bmperr=m; retcode=-1; goto finally;}
#define _unix(f) {if((f)==-1) _throw(strerror(errno));}
#define _catch(f) {if((f)==-1) {retcode=-1; goto finally;}}
#define readme(fd, addr, size) \
if((bytesread=read(fd, addr, (size)))==-1) _throw(strerror(errno)); \
if(bytesread!=(size)) _throw("Read error");
void pixelconvert(unsigned char *srcbuf, enum BMPPIXELFORMAT srcformat,
int srcpitch, unsigned char *dstbuf, enum BMPPIXELFORMAT dstformat, int dstpitch,
int w, int h, int flip)
{
unsigned char *srcptr, *srcptr0, *dstptr, *dstptr0;
int i, j;
srcptr=flip? &srcbuf[srcpitch*(h-1)]:srcbuf;
for(j=0, dstptr=dstbuf; j<h; j++,
srcptr+=flip? -srcpitch:srcpitch, dstptr+=dstpitch)
{
for(i=0, srcptr0=srcptr, dstptr0=dstptr; i<w; i++,
srcptr0+=ps[srcformat], dstptr0+=ps[dstformat])
{
dstptr0[roffset[dstformat]]=srcptr0[roffset[srcformat]];
dstptr0[goffset[dstformat]]=srcptr0[goffset[srcformat]];
dstptr0[boffset[dstformat]]=srcptr0[boffset[srcformat]];
}
}
}
int loadppm(int *fd, unsigned char **buf, int *w, int *h,
enum BMPPIXELFORMAT f, int align, int dstbottomup, int ascii)
{
FILE *fs=NULL; int retcode=0, scalefactor, dstpitch;
unsigned char *tempbuf=NULL; char temps[255], temps2[255];
int numread=0, totalread=0, pixel[3], i, j;
if((fs=fdopen(*fd, "r"))==NULL) _throw(strerror(errno));
do
{
if(!fgets(temps, 255, fs)) _throw("Read error");
if(strlen(temps)==0 || temps[0]=='\n') continue;
if(sscanf(temps, "%s", temps2)==1 && temps2[1]=='#') continue;
switch(totalread)
{
case 0:
if((numread=sscanf(temps, "%d %d %d", w, h, &scalefactor))==EOF)
_throw("Read error");
break;
case 1:
if((numread=sscanf(temps, "%d %d", h, &scalefactor))==EOF)
_throw("Read error");
break;
case 2:
if((numread=sscanf(temps, "%d", &scalefactor))==EOF)
_throw("Read error");
break;
}
totalread+=numread;
} while(totalread<3);
if((*w)<1 || (*h)<1 || scalefactor<1) _throw("Corrupt PPM header");
dstpitch=(((*w)*ps[f])+(align-1))&(~(align-1));
if((*buf=(unsigned char *)malloc(dstpitch*(*h)))==NULL)
_throw("Memory allocation error");
if(ascii)
{
for(j=0; j<*h; j++)
{
for(i=0; i<*w; i++)
{
if(fscanf(fs, "%d%d%d", &pixel[0], &pixel[1], &pixel[2])!=3)
_throw("Read error");
(*buf)[j*dstpitch+i*ps[f]+roffset[f]]=(unsigned char)(pixel[0]*255/scalefactor);
(*buf)[j*dstpitch+i*ps[f]+goffset[f]]=(unsigned char)(pixel[1]*255/scalefactor);
(*buf)[j*dstpitch+i*ps[f]+boffset[f]]=(unsigned char)(pixel[2]*255/scalefactor);
}
}
}
else
{
if(scalefactor!=255)
_throw("Binary PPMs must have 8-bit components");
if((tempbuf=(unsigned char *)malloc((*w)*(*h)*3))==NULL)
_throw("Memory allocation error");
if(fread(tempbuf, (*w)*(*h)*3, 1, fs)!=1) _throw("Read error");
pixelconvert(tempbuf, BMP_RGB, (*w)*3, *buf, f, dstpitch, *w, *h, dstbottomup);
}
finally:
if(fs) {fclose(fs); *fd=-1;}
if(tempbuf) free(tempbuf);
return retcode;
}
int loadbmp(char *filename, unsigned char **buf, int *w, int *h,
enum BMPPIXELFORMAT f, int align, int dstbottomup)
{
int fd=-1, bytesread, srcpitch, srcbottomup=1, srcps, dstpitch,
retcode=0;
unsigned char *tempbuf=NULL;
bmphdr bh; int flags=O_RDONLY;
dstbottomup=dstbottomup? 1:0;
#ifdef _WIN32
flags|=O_BINARY;
#endif
if(!filename || !buf || !w || !h || f<0 || f>BMPPIXELFORMATS-1 || align<1)
_throw("invalid argument to loadbmp()");
if((align&(align-1))!=0)
_throw("Alignment must be a power of 2");
_unix(fd=open(filename, flags));
readme(fd, &bh.bfType, sizeof(unsigned short));
if(!littleendian()) bh.bfType=byteswap16(bh.bfType);
if(bh.bfType==0x3650)
{
_catch(loadppm(&fd, buf, w, h, f, align, dstbottomup, 0));
goto finally;
}
if(bh.bfType==0x3350)
{
_catch(loadppm(&fd, buf, w, h, f, align, dstbottomup, 1));
goto finally;
}
readme(fd, &bh.bfSize, sizeof(unsigned int));
readme(fd, &bh.bfReserved1, sizeof(unsigned short));
readme(fd, &bh.bfReserved2, sizeof(unsigned short));
readme(fd, &bh.bfOffBits, sizeof(unsigned int));
readme(fd, &bh.biSize, sizeof(unsigned int));
readme(fd, &bh.biWidth, sizeof(int));
readme(fd, &bh.biHeight, sizeof(int));
readme(fd, &bh.biPlanes, sizeof(unsigned short));
readme(fd, &bh.biBitCount, sizeof(unsigned short));
readme(fd, &bh.biCompression, sizeof(unsigned int));
readme(fd, &bh.biSizeImage, sizeof(unsigned int));
readme(fd, &bh.biXPelsPerMeter, sizeof(int));
readme(fd, &bh.biYPelsPerMeter, sizeof(int));
readme(fd, &bh.biClrUsed, sizeof(unsigned int));
readme(fd, &bh.biClrImportant, sizeof(unsigned int));
if(!littleendian())
{
bh.bfSize=byteswap(bh.bfSize);
bh.bfOffBits=byteswap(bh.bfOffBits);
bh.biSize=byteswap(bh.biSize);
bh.biWidth=byteswap(bh.biWidth);
bh.biHeight=byteswap(bh.biHeight);
bh.biPlanes=byteswap16(bh.biPlanes);
bh.biBitCount=byteswap16(bh.biBitCount);
bh.biCompression=byteswap(bh.biCompression);
bh.biSizeImage=byteswap(bh.biSizeImage);
bh.biXPelsPerMeter=byteswap(bh.biXPelsPerMeter);
bh.biYPelsPerMeter=byteswap(bh.biYPelsPerMeter);
bh.biClrUsed=byteswap(bh.biClrUsed);
bh.biClrImportant=byteswap(bh.biClrImportant);
}
if(bh.bfType!=0x4d42 || bh.bfOffBits<BMPHDRSIZE
|| bh.biWidth<1 || bh.biHeight==0)
_throw("Corrupt bitmap header");
if((bh.biBitCount!=24 && bh.biBitCount!=32) || bh.biCompression!=BI_RGB)
_throw("Only uncompessed RGB bitmaps are supported");
*w=bh.biWidth; *h=bh.biHeight; srcps=bh.biBitCount/8;
if(*h<0) {*h=-(*h); srcbottomup=0;}
srcpitch=(((*w)*srcps)+3)&(~3);
dstpitch=(((*w)*ps[f])+(align-1))&(~(align-1));
if(srcpitch*(*h)+bh.bfOffBits!=bh.bfSize) _throw("Corrupt bitmap header");
if((tempbuf=(unsigned char *)malloc(srcpitch*(*h)))==NULL
|| (*buf=(unsigned char *)malloc(dstpitch*(*h)))==NULL)
_throw("Memory allocation error");
if(lseek(fd, (long)bh.bfOffBits, SEEK_SET)!=(long)bh.bfOffBits)
_throw(strerror(errno));
_unix(bytesread=read(fd, tempbuf, srcpitch*(*h)));
if(bytesread!=srcpitch*(*h)) _throw("Read error");
pixelconvert(tempbuf, BMP_BGR, srcpitch, *buf, f, dstpitch, *w, *h,
srcbottomup!=dstbottomup);
finally:
if(tempbuf) free(tempbuf);
if(fd!=-1) close(fd);
return retcode;
}
#define writeme(fd, addr, size) \
if((byteswritten=write(fd, addr, (size)))==-1) _throw(strerror(errno)); \
if(byteswritten!=(size)) _throw("Write error");
int saveppm(char *filename, unsigned char *buf, int w, int h,
enum BMPPIXELFORMAT f, int srcpitch, int srcbottomup)
{
FILE *fs=NULL; int retcode=0;
unsigned char *tempbuf=NULL;
if((fs=fopen(filename, "wb"))==NULL) _throw(strerror(errno));
if(fprintf(fs, "P6\n")<1) _throw("Write error");
if(fprintf(fs, "%d %d\n", w, h)<1) _throw("Write error");
if(fprintf(fs, "255\n")<1) _throw("Write error");
if((tempbuf=(unsigned char *)malloc(w*h*3))==NULL)
_throw("Memory allocation error");
pixelconvert(buf, f, srcpitch, tempbuf, BMP_RGB, w*3, w, h,
srcbottomup);
if((fwrite(tempbuf, w*h*3, 1, fs))!=1) _throw("Write error");
finally:
if(tempbuf) free(tempbuf);
if(fs) fclose(fs);
return retcode;
}
int savebmp(char *filename, unsigned char *buf, int w, int h,
enum BMPPIXELFORMAT f, int srcpitch, int srcbottomup)
{
int fd=-1, byteswritten, dstpitch, retcode=0;
int flags=O_RDWR|O_CREAT|O_TRUNC;
unsigned char *tempbuf=NULL; char *temp;
bmphdr bh; int mode;
#ifdef _WIN32
flags|=O_BINARY; mode=_S_IREAD|_S_IWRITE;
#else
mode=S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
#endif
if(!filename || !buf || w<1 || h<1 || f<0 || f>BMPPIXELFORMATS-1 || srcpitch<0)
_throw("bad argument to savebmp()");
if(srcpitch==0) srcpitch=w*ps[f];
if((temp=strrchr(filename, '.'))!=NULL)
{
if(!stricmp(temp, ".ppm"))
return saveppm(filename, buf, w, h, f, srcpitch, srcbottomup);
}
_unix(fd=open(filename, flags, mode));
dstpitch=((w*3)+3)&(~3);
bh.bfType=0x4d42;
bh.bfSize=BMPHDRSIZE+dstpitch*h;
bh.bfReserved1=0; bh.bfReserved2=0;
bh.bfOffBits=BMPHDRSIZE;
bh.biSize=40;
bh.biWidth=w; bh.biHeight=h;
bh.biPlanes=0; bh.biBitCount=24;
bh.biCompression=BI_RGB; bh.biSizeImage=0;
bh.biXPelsPerMeter=0; bh.biYPelsPerMeter=0;
bh.biClrUsed=0; bh.biClrImportant=0;
if(!littleendian())
{
bh.bfType=byteswap16(bh.bfType);
bh.bfSize=byteswap(bh.bfSize);
bh.bfOffBits=byteswap(bh.bfOffBits);
bh.biSize=byteswap(bh.biSize);
bh.biWidth=byteswap(bh.biWidth);
bh.biHeight=byteswap(bh.biHeight);
bh.biPlanes=byteswap16(bh.biPlanes);
bh.biBitCount=byteswap16(bh.biBitCount);
bh.biCompression=byteswap(bh.biCompression);
bh.biSizeImage=byteswap(bh.biSizeImage);
bh.biXPelsPerMeter=byteswap(bh.biXPelsPerMeter);
bh.biYPelsPerMeter=byteswap(bh.biYPelsPerMeter);
bh.biClrUsed=byteswap(bh.biClrUsed);
bh.biClrImportant=byteswap(bh.biClrImportant);
}
writeme(fd, &bh.bfType, sizeof(unsigned short));
writeme(fd, &bh.bfSize, sizeof(unsigned int));
writeme(fd, &bh.bfReserved1, sizeof(unsigned short));
writeme(fd, &bh.bfReserved2, sizeof(unsigned short));
writeme(fd, &bh.bfOffBits, sizeof(unsigned int));
writeme(fd, &bh.biSize, sizeof(unsigned int));
writeme(fd, &bh.biWidth, sizeof(int));
writeme(fd, &bh.biHeight, sizeof(int));
writeme(fd, &bh.biPlanes, sizeof(unsigned short));
writeme(fd, &bh.biBitCount, sizeof(unsigned short));
writeme(fd, &bh.biCompression, sizeof(unsigned int));
writeme(fd, &bh.biSizeImage, sizeof(unsigned int));
writeme(fd, &bh.biXPelsPerMeter, sizeof(int));
writeme(fd, &bh.biYPelsPerMeter, sizeof(int));
writeme(fd, &bh.biClrUsed, sizeof(unsigned int));
writeme(fd, &bh.biClrImportant, sizeof(unsigned int));
if((tempbuf=(unsigned char *)malloc(dstpitch*h))==NULL)
_throw("Memory allocation error");
pixelconvert(buf, f, srcpitch, tempbuf, BMP_BGR, dstpitch, w, h,
!srcbottomup);
if((byteswritten=write(fd, tempbuf, dstpitch*h))!=dstpitch*h)
_throw(strerror(errno));
finally:
if(tempbuf) free(tempbuf);
if(fd!=-1) close(fd);
return retcode;
}
const char *bmpgeterr(void)
{
return __bmperr;
}

48
bmp.h Normal file
View File

@@ -0,0 +1,48 @@
/* Copyright (C)2004 Landmark Graphics Corporation
* Copyright (C)2005 Sun Microsystems, Inc.
*
* This library is free software and may be redistributed and/or modified under
* the terms of the wxWindows Library License, Version 3.1 or (at your option)
* any later version. The full license is in the LICENSE.txt file included
* with this distribution.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* wxWindows Library License for more details.
*/
// This provides rudimentary facilities for loading and saving true color
// BMP and PPM files
#ifndef __BMP_H__
#define __BMP_H__
#define BMPPIXELFORMATS 6
enum BMPPIXELFORMAT {BMP_RGB=0, BMP_RGBA, BMP_BGR, BMP_BGRA, BMP_ABGR, BMP_ARGB};
#ifdef __cplusplus
extern "C" {
#endif
// This will load a Windows bitmap from a file and return a buffer with the
// specified pixel format, scanline alignment, and orientation. The width and
// height are returned in w and h.
int loadbmp(char *filename, unsigned char **buf, int *w, int *h,
enum BMPPIXELFORMAT f, int align, int dstbottomup);
// This will save a buffer with the specified pixel format, pitch, orientation,
// width, and height as a 24-bit Windows bitmap or PPM (the filename determines
// which format to use)
int savebmp(char *filename, unsigned char *buf, int w, int h,
enum BMPPIXELFORMAT f, int srcpitch, int srcbottomup);
const char *bmpgeterr(void);
#ifdef __cplusplus
}
#endif
#endif

132
cderror.h Normal file
View File

@@ -0,0 +1,132 @@
/*
* cderror.h
*
* Copyright (C) 1994-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file defines the error and message codes for the cjpeg/djpeg
* applications. These strings are not needed as part of the JPEG library
* proper.
* Edit this file to add new codes, or to translate the message strings to
* some other language.
*/
/*
* To define the enum list of message codes, include this file without
* defining macro JMESSAGE. To create a message string table, include it
* again with a suitable JMESSAGE definition (see jerror.c for an example).
*/
#ifndef JMESSAGE
#ifndef CDERROR_H
#define CDERROR_H
/* First time through, define the enum list */
#define JMAKE_ENUM_LIST
#else
/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
#define JMESSAGE(code,string)
#endif /* CDERROR_H */
#endif /* JMESSAGE */
#ifdef JMAKE_ENUM_LIST
typedef enum {
#define JMESSAGE(code,string) code ,
#endif /* JMAKE_ENUM_LIST */
JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */
#ifdef BMP_SUPPORTED
JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format")
JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported")
JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length")
JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1")
JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB")
JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported")
JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM")
JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image")
JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image")
JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image")
JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image")
#endif /* BMP_SUPPORTED */
#ifdef GIF_SUPPORTED
JMESSAGE(JERR_GIF_BUG, "GIF output got confused")
JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d")
JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB")
JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file")
JMESSAGE(JERR_GIF_NOT, "Not a GIF file")
JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image")
JMESSAGE(JTRC_GIF_BADVERSION,
"Warning: unexpected GIF version number '%c%c%c'")
JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x")
JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input")
JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file")
JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring")
JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image")
JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits")
#endif /* GIF_SUPPORTED */
#ifdef PPM_SUPPORTED
JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB")
JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file")
JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file")
JMESSAGE(JTRC_PGM, "%ux%u PGM image")
JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image")
JMESSAGE(JTRC_PPM, "%ux%u PPM image")
JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image")
#endif /* PPM_SUPPORTED */
#ifdef RLE_SUPPORTED
JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library")
JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB")
JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE")
JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file")
JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header")
JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header")
JMESSAGE(JERR_RLE_NOT, "Not an RLE file")
JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE")
JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup")
JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file")
JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d")
JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file")
JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d")
JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d")
#endif /* RLE_SUPPORTED */
#ifdef TARGA_SUPPORTED
JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format")
JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file")
JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB")
JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image")
JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image")
JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image")
#else
JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled")
#endif /* TARGA_SUPPORTED */
JMESSAGE(JERR_BAD_CMAP_FILE,
"Color map file is invalid or of unsupported format")
JMESSAGE(JERR_TOO_MANY_COLORS,
"Output file format cannot handle %d colormap entries")
JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed")
#ifdef TARGA_SUPPORTED
JMESSAGE(JERR_UNKNOWN_FORMAT,
"Unrecognized input file format --- perhaps you need -targa")
#else
JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format")
#endif
JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format")
#ifdef JMAKE_ENUM_LIST
JMSG_LASTADDONCODE
} ADDON_MESSAGE_CODE;
#undef JMAKE_ENUM_LIST
#endif /* JMAKE_ENUM_LIST */
/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
#undef JMESSAGE

181
cdjpeg.c Normal file
View File

@@ -0,0 +1,181 @@
/*
* cdjpeg.c
*
* Copyright (C) 1991-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains common support routines used by the IJG application
* programs (cjpeg, djpeg, jpegtran).
*/
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#include <ctype.h> /* to declare isupper(), tolower() */
#ifdef NEED_SIGNAL_CATCHER
#include <signal.h> /* to declare signal() */
#endif
#ifdef USE_SETMODE
#include <fcntl.h> /* to declare setmode()'s parameter macros */
/* If you have setmode() but not <io.h>, just delete this line: */
#include <io.h> /* to declare setmode() */
#endif
/*
* Signal catcher to ensure that temporary files are removed before aborting.
* NB: for Amiga Manx C this is actually a global routine named _abort();
* we put "#define signal_catcher _abort" in jconfig.h. Talk about bogus...
*/
#ifdef NEED_SIGNAL_CATCHER
static j_common_ptr sig_cinfo;
void /* must be global for Manx C */
signal_catcher (int signum)
{
if (sig_cinfo != NULL) {
if (sig_cinfo->err != NULL) /* turn off trace output */
sig_cinfo->err->trace_level = 0;
jpeg_destroy(sig_cinfo); /* clean up memory allocation & temp files */
}
exit(EXIT_FAILURE);
}
GLOBAL(void)
enable_signal_catcher (j_common_ptr cinfo)
{
sig_cinfo = cinfo;
#ifdef SIGINT /* not all systems have SIGINT */
signal(SIGINT, signal_catcher);
#endif
#ifdef SIGTERM /* not all systems have SIGTERM */
signal(SIGTERM, signal_catcher);
#endif
}
#endif
/*
* Optional progress monitor: display a percent-done figure on stderr.
*/
#ifdef PROGRESS_REPORT
METHODDEF(void)
progress_monitor (j_common_ptr cinfo)
{
cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress;
int total_passes = prog->pub.total_passes + prog->total_extra_passes;
int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit);
if (percent_done != prog->percent_done) {
prog->percent_done = percent_done;
if (total_passes > 1) {
fprintf(stderr, "\rPass %d/%d: %3d%% ",
prog->pub.completed_passes + prog->completed_extra_passes + 1,
total_passes, percent_done);
} else {
fprintf(stderr, "\r %3d%% ", percent_done);
}
fflush(stderr);
}
}
GLOBAL(void)
start_progress_monitor (j_common_ptr cinfo, cd_progress_ptr progress)
{
/* Enable progress display, unless trace output is on */
if (cinfo->err->trace_level == 0) {
progress->pub.progress_monitor = progress_monitor;
progress->completed_extra_passes = 0;
progress->total_extra_passes = 0;
progress->percent_done = -1;
cinfo->progress = &progress->pub;
}
}
GLOBAL(void)
end_progress_monitor (j_common_ptr cinfo)
{
/* Clear away progress display */
if (cinfo->err->trace_level == 0) {
fprintf(stderr, "\r \r");
fflush(stderr);
}
}
#endif
/*
* Case-insensitive matching of possibly-abbreviated keyword switches.
* keyword is the constant keyword (must be lower case already),
* minchars is length of minimum legal abbreviation.
*/
GLOBAL(boolean)
keymatch (char * arg, const char * keyword, int minchars)
{
register int ca, ck;
register int nmatched = 0;
while ((ca = *arg++) != '\0') {
if ((ck = *keyword++) == '\0')
return FALSE; /* arg longer than keyword, no good */
if (isupper(ca)) /* force arg to lcase (assume ck is already) */
ca = tolower(ca);
if (ca != ck)
return FALSE; /* no good */
nmatched++; /* count matched characters */
}
/* reached end of argument; fail if it's too short for unique abbrev */
if (nmatched < minchars)
return FALSE;
return TRUE; /* A-OK */
}
/*
* Routines to establish binary I/O mode for stdin and stdout.
* Non-Unix systems often require some hacking to get out of text mode.
*/
GLOBAL(FILE *)
read_stdin (void)
{
FILE * input_file = stdin;
#ifdef USE_SETMODE /* need to hack file mode? */
setmode(fileno(stdin), O_BINARY);
#endif
#ifdef USE_FDOPEN /* need to re-open in binary mode? */
if ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
fprintf(stderr, "Cannot reopen stdin\n");
exit(EXIT_FAILURE);
}
#endif
return input_file;
}
GLOBAL(FILE *)
write_stdout (void)
{
FILE * output_file = stdout;
#ifdef USE_SETMODE /* need to hack file mode? */
setmode(fileno(stdout), O_BINARY);
#endif
#ifdef USE_FDOPEN /* need to re-open in binary mode? */
if ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
fprintf(stderr, "Cannot reopen stdout\n");
exit(EXIT_FAILURE);
}
#endif
return output_file;
}

184
cdjpeg.h Normal file
View File

@@ -0,0 +1,184 @@
/*
* cdjpeg.h
*
* Copyright (C) 1994-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains common declarations for the sample applications
* cjpeg and djpeg. It is NOT used by the core JPEG library.
*/
#define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */
#define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */
#include "jinclude.h"
#include "jpeglib.h"
#include "jerror.h" /* get library error codes too */
#include "cderror.h" /* get application-specific error codes */
/*
* Object interface for cjpeg's source file decoding modules
*/
typedef struct cjpeg_source_struct * cjpeg_source_ptr;
struct cjpeg_source_struct {
JMETHOD(void, start_input, (j_compress_ptr cinfo,
cjpeg_source_ptr sinfo));
JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,
cjpeg_source_ptr sinfo));
JMETHOD(void, finish_input, (j_compress_ptr cinfo,
cjpeg_source_ptr sinfo));
FILE *input_file;
JSAMPARRAY buffer;
JDIMENSION buffer_height;
};
/*
* Object interface for djpeg's output file encoding modules
*/
typedef struct djpeg_dest_struct * djpeg_dest_ptr;
struct djpeg_dest_struct {
/* start_output is called after jpeg_start_decompress finishes.
* The color map will be ready at this time, if one is needed.
*/
JMETHOD(void, start_output, (j_decompress_ptr cinfo,
djpeg_dest_ptr dinfo));
/* Emit the specified number of pixel rows from the buffer. */
JMETHOD(void, put_pixel_rows, (j_decompress_ptr cinfo,
djpeg_dest_ptr dinfo,
JDIMENSION rows_supplied));
/* Finish up at the end of the image. */
JMETHOD(void, finish_output, (j_decompress_ptr cinfo,
djpeg_dest_ptr dinfo));
/* Target file spec; filled in by djpeg.c after object is created. */
FILE * output_file;
/* Output pixel-row buffer. Created by module init or start_output.
* Width is cinfo->output_width * cinfo->output_components;
* height is buffer_height.
*/
JSAMPARRAY buffer;
JDIMENSION buffer_height;
};
/*
* cjpeg/djpeg may need to perform extra passes to convert to or from
* the source/destination file format. The JPEG library does not know
* about these passes, but we'd like them to be counted by the progress
* monitor. We use an expanded progress monitor object to hold the
* additional pass count.
*/
struct cdjpeg_progress_mgr {
struct jpeg_progress_mgr pub; /* fields known to JPEG library */
int completed_extra_passes; /* extra passes completed */
int total_extra_passes; /* total extra */
/* last printed percentage stored here to avoid multiple printouts */
int percent_done;
};
typedef struct cdjpeg_progress_mgr * cd_progress_ptr;
/* Short forms of external names for systems with brain-damaged linkers. */
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define jinit_read_bmp jIRdBMP
#define jinit_write_bmp jIWrBMP
#define jinit_read_gif jIRdGIF
#define jinit_write_gif jIWrGIF
#define jinit_read_ppm jIRdPPM
#define jinit_write_ppm jIWrPPM
#define jinit_read_rle jIRdRLE
#define jinit_write_rle jIWrRLE
#define jinit_read_targa jIRdTarga
#define jinit_write_targa jIWrTarga
#define read_quant_tables RdQTables
#define read_scan_script RdScnScript
#define set_quant_slots SetQSlots
#define set_sample_factors SetSFacts
#define read_color_map RdCMap
#define enable_signal_catcher EnSigCatcher
#define start_progress_monitor StProgMon
#define end_progress_monitor EnProgMon
#define read_stdin RdStdin
#define write_stdout WrStdout
#endif /* NEED_SHORT_EXTERNAL_NAMES */
/* Module selection routines for I/O modules. */
EXTERN(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo));
EXTERN(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo,
boolean is_os2));
EXTERN(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo));
EXTERN(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo));
EXTERN(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo));
EXTERN(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo));
EXTERN(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo));
EXTERN(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo));
EXTERN(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo));
EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo));
/* cjpeg support routines (in rdswitch.c) */
EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename,
int scale_factor, boolean force_baseline));
EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename));
EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg));
EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg));
/* djpeg support routines (in rdcolmap.c) */
EXTERN(void) read_color_map JPP((j_decompress_ptr cinfo, FILE * infile));
/* common support routines (in cdjpeg.c) */
EXTERN(void) enable_signal_catcher JPP((j_common_ptr cinfo));
EXTERN(void) start_progress_monitor JPP((j_common_ptr cinfo,
cd_progress_ptr progress));
EXTERN(void) end_progress_monitor JPP((j_common_ptr cinfo));
EXTERN(boolean) keymatch JPP((char * arg, const char * keyword, int minchars));
EXTERN(FILE *) read_stdin JPP((void));
EXTERN(FILE *) write_stdout JPP((void));
/* miscellaneous useful macros */
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
#define READ_BINARY "r"
#define WRITE_BINARY "w"
#else
#ifdef VMS /* VMS is very nonstandard */
#define READ_BINARY "rb", "ctx=stm"
#define WRITE_BINARY "wb", "ctx=stm"
#else /* standard ANSI-compliant case */
#define READ_BINARY "rb"
#define WRITE_BINARY "wb"
#endif
#endif
#ifndef EXIT_FAILURE /* define exit() codes if not provided */
#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
#ifdef VMS
#define EXIT_SUCCESS 1 /* VMS is very nonstandard */
#else
#define EXIT_SUCCESS 0
#endif
#endif
#ifndef EXIT_WARNING
#ifdef VMS
#define EXIT_WARNING 1 /* VMS is very nonstandard */
#else
#define EXIT_WARNING 2
#endif
#endif

217
change.log Normal file
View File

@@ -0,0 +1,217 @@
CHANGE LOG for Independent JPEG Group's JPEG software
Version 6b 27-Mar-1998
-----------------------
jpegtran has new features for lossless image transformations (rotation
and flipping) as well as "lossless" reduction to grayscale.
jpegtran now copies comments by default; it has a -copy switch to enable
copying all APPn blocks as well, or to suppress comments. (Formerly it
always suppressed comments and APPn blocks.) jpegtran now also preserves
JFIF version and resolution information.
New decompressor library feature: COM and APPn markers found in the input
file can be saved in memory for later use by the application. (Before,
you had to code this up yourself with a custom marker processor.)
There is an unused field "void * client_data" now in compress and decompress
parameter structs; this may be useful in some applications.
JFIF version number information is now saved by the decoder and accepted by
the encoder. jpegtran uses this to copy the source file's version number,
to ensure "jpegtran -copy all" won't create bogus files that contain JFXX
extensions but claim to be version 1.01. Applications that generate their
own JFXX extension markers also (finally) have a supported way to cause the
encoder to emit JFIF version number 1.02.
djpeg's trace mode reports JFIF 1.02 thumbnail images as such, rather
than as unknown APP0 markers.
In -verbose mode, djpeg and rdjpgcom will try to print the contents of
APP12 markers as text. Some digital cameras store useful text information
in APP12 markers.
Handling of truncated data streams is more robust: blocks beyond the one in
which the error occurs will be output as uniform gray, or left unchanged
if decoding a progressive JPEG. The appearance no longer depends on the
Huffman tables being used.
Huffman tables are checked for validity much more carefully than before.
To avoid the Unisys LZW patent, djpeg's GIF output capability has been
changed to produce "uncompressed GIFs", and cjpeg's GIF input capability
has been removed altogether. We're not happy about it either, but there
seems to be no good alternative.
The configure script now supports building libjpeg as a shared library
on many flavors of Unix (all the ones that GNU libtool knows how to
build shared libraries for). Use "./configure --enable-shared" to
try this out.
New jconfig file and makefiles for Microsoft Visual C++ and Developer Studio.
Also, a jconfig file and a build script for Metrowerks CodeWarrior
on Apple Macintosh. makefile.dj has been updated for DJGPP v2, and there
are miscellaneous other minor improvements in the makefiles.
jmemmac.c now knows how to create temporary files following Mac System 7
conventions.
djpeg's -map switch is now able to read raw-format PPM files reliably.
cjpeg -progressive -restart no longer generates any unnecessary DRI markers.
Multiple calls to jpeg_simple_progression for a single JPEG object
no longer leak memory.
Version 6a 7-Feb-96
--------------------
Library initialization sequence modified to detect version mismatches
and struct field packing mismatches between library and calling application.
This change requires applications to be recompiled, but does not require
any application source code change.
All routine declarations changed to the style "GLOBAL(type) name ...",
that is, GLOBAL, LOCAL, METHODDEF, EXTERN are now macros taking the
routine's return type as an argument. This makes it possible to add
Microsoft-style linkage keywords to all the routines by changing just
these macros. Note that any application code that was using these macros
will have to be changed.
DCT coefficient quantization tables are now stored in normal array order
rather than zigzag order. Application code that calls jpeg_add_quant_table,
or otherwise manipulates quantization tables directly, will need to be
changed. If you need to make such code work with either older or newer
versions of the library, a test like "#if JPEG_LIB_VERSION >= 61" is
recommended.
djpeg's trace capability now dumps DQT tables in natural order, not zigzag
order. This allows the trace output to be made into a "-qtables" file
more easily.
New system-dependent memory manager module for use on Apple Macintosh.
Fix bug in cjpeg's -smooth option: last one or two scanlines would be
duplicates of the prior line unless the image height mod 16 was 1 or 2.
Repair minor problems in VMS, BCC, MC6 makefiles.
New configure script based on latest GNU Autoconf.
Correct the list of include files needed by MetroWerks C for ccommand().
Numerous small documentation updates.
Version 6 2-Aug-95
-------------------
Progressive JPEG support: library can read and write full progressive JPEG
files. A "buffered image" mode supports incremental decoding for on-the-fly
display of progressive images. Simply recompiling an existing IJG-v5-based
decoder with v6 should allow it to read progressive files, though of course
without any special progressive display.
New "jpegtran" application performs lossless transcoding between different
JPEG formats; primarily, it can be used to convert baseline to progressive
JPEG and vice versa. In support of jpegtran, the library now allows lossless
reading and writing of JPEG files as DCT coefficient arrays. This ability
may be of use in other applications.
Notes for programmers:
* We changed jpeg_start_decompress() to be able to suspend; this makes all
decoding modes available to suspending-input applications. However,
existing applications that use suspending input will need to be changed
to check the return value from jpeg_start_decompress(). You don't need to
do anything if you don't use a suspending data source.
* We changed the interface to the virtual array routines: access_virt_array
routines now take a count of the number of rows to access this time. The
last parameter to request_virt_array routines is now interpreted as the
maximum number of rows that may be accessed at once, but not necessarily
the height of every access.
Version 5b 15-Mar-95
---------------------
Correct bugs with grayscale images having v_samp_factor > 1.
jpeg_write_raw_data() now supports output suspension.
Correct bugs in "configure" script for case of compiling in
a directory other than the one containing the source files.
Repair bug in jquant1.c: sometimes didn't use as many colors as it could.
Borland C makefile and jconfig file work under either MS-DOS or OS/2.
Miscellaneous improvements to documentation.
Version 5a 7-Dec-94
--------------------
Changed color conversion roundoff behavior so that grayscale values are
represented exactly. (This causes test image files to change.)
Make ordered dither use 16x16 instead of 4x4 pattern for a small quality
improvement.
New configure script based on latest GNU Autoconf.
Fix configure script to handle CFLAGS correctly.
Rename *.auto files to *.cfg, so that configure script still works if
file names have been truncated for DOS.
Fix bug in rdbmp.c: didn't allow for extra data between header and image.
Modify rdppm.c/wrppm.c to handle 2-byte raw PPM/PGM formats for 12-bit data.
Fix several bugs in rdrle.c.
NEED_SHORT_EXTERNAL_NAMES option was broken.
Revise jerror.h/jerror.c for more flexibility in message table.
Repair oversight in jmemname.c NO_MKTEMP case: file could be there
but unreadable.
Version 5 24-Sep-94
--------------------
Version 5 represents a nearly complete redesign and rewrite of the IJG
software. Major user-visible changes include:
* Automatic configuration simplifies installation for most Unix systems.
* A range of speed vs. image quality tradeoffs are supported.
This includes resizing of an image during decompression: scaling down
by a factor of 1/2, 1/4, or 1/8 is handled very efficiently.
* New programs rdjpgcom and wrjpgcom allow insertion and extraction
of text comments in a JPEG file.
The application programmer's interface to the library has changed completely.
Notable improvements include:
* We have eliminated the use of callback routines for handling the
uncompressed image data. The application now sees the library as a
set of routines that it calls to read or write image data on a
scanline-by-scanline basis.
* The application image data is represented in a conventional interleaved-
pixel format, rather than as a separate array for each color channel.
This can save a copying step in many programs.
* The handling of compressed data has been cleaned up: the application can
supply routines to source or sink the compressed data. It is possible to
suspend processing on source/sink buffer overrun, although this is not
supported in all operating modes.
* All static state has been eliminated from the library, so that multiple
instances of compression or decompression can be active concurrently.
* JPEG abbreviated datastream formats are supported, ie, quantization and
Huffman tables can be stored separately from the image data.
* And not only that, but the documentation of the library has improved
considerably!
The last widely used release before the version 5 rewrite was version 4A of
18-Feb-93. Change logs before that point have been discarded, since they
are not of much interest after the rewrite.

196
cjpeg.1
View File

@@ -1,46 +1,10 @@
.TH CJPEG 1 "4 November 1992"
.TH CJPEG 1 "20 March 1998"
.SH NAME
cjpeg \- compress an image file to a JPEG file
.SH SYNOPSIS
.B cjpeg
[
.BI \-quality " N"
]
[
.B \-grayscale
]
[
.B \-optimize
]
[
.B \-targa
]
[
.BI \-maxmemory " N"
]
[
.BI \-restart " N"
]
[
.BI \-smooth " N"
]
[
.B \-verbose
]
[
.B \-debug
]
[
.B \-arithmetic
]
[
.B \-nointerleave
]
[
.BI \-qtables " file"
]
[
.BI \-sample " HxV[,...]"
.I options
]
[
.I filename
@@ -52,7 +16,7 @@ cjpeg \- compress an image file to a JPEG file
compresses the named image file, or the standard input if no file is
named, and produces a JPEG/JFIF file on the standard output.
The currently supported input file formats are: PPM (PBMPLUS color
format), PGM (PBMPLUS gray-scale format), GIF, Targa, and RLE (Utah Raster
format), PGM (PBMPLUS gray-scale format), BMP, Targa, and RLE (Utah Raster
Toolkit format). (RLE is supported only if the URT library is available.)
.SH OPTIONS
All switch names may be abbreviated; for example,
@@ -63,9 +27,9 @@ or
.BR \-gr .
Most of the "basic" switches can be abbreviated to as little as one letter.
Upper and lower case are equivalent (thus
.B \-GIF
.B \-BMP
is the same as
.BR \-gif ).
.BR \-bmp ).
British spellings are also accepted (e.g.,
.BR \-greyscale ),
though for brevity these are not mentioned below.
@@ -78,9 +42,9 @@ Scale quantization tables to adjust image quality. Quality is 0 (worst) to
.TP
.B \-grayscale
Create monochrome JPEG file from color input. Be sure to use this switch when
compressing a grayscale GIF file, because
compressing a grayscale BMP file, because
.B cjpeg
isn't bright enough to notice whether a GIF file uses only shades of gray.
isn't bright enough to notice whether a BMP file uses only shades of gray.
By saying
.BR \-grayscale ,
you'll get a smaller JPEG file that takes less time to process.
@@ -95,6 +59,9 @@ runs somewhat slower and needs much more memory. Image quality and speed of
decompression are unaffected by
.BR \-optimize .
.TP
.B \-progressive
Create progressive JPEG file (see below).
.TP
.B \-targa
Input file is Targa format. Targa files that contain an "identification"
field will not be automatically recognized by
@@ -104,6 +71,7 @@ for such files you must specify
to make
.B cjpeg
treat the input as Targa format.
For most Targa files, you won't need this switch.
.PP
The
.B \-quality
@@ -119,7 +87,7 @@ often about right. If you see defects at
image. (The optimal setting will vary from one image to another.)
.PP
.B \-quality
100 will generate a quantization table of all 1's, eliminating loss in the
100 will generate a quantization table of all 1's, minimizing loss in the
quantization step (but there is still information loss in subsampling, as well
as roundoff error). This setting is mainly of interest for experimental
purposes. Quality values above about 95 are
@@ -136,16 +104,38 @@ values below about 25 generate 2-byte quantization tables, which are
considered optional in the JPEG standard.
.B cjpeg
emits a warning message when you give such a quality value, because some
commercial JPEG programs may be unable to decode the resulting file.)
other JPEG programs may be unable to decode the resulting file. Use
.B \-baseline
if you need to ensure compatibility at low quality values.)
.PP
The
.B \-progressive
switch creates a "progressive JPEG" file. In this type of JPEG file, the data
is stored in multiple scans of increasing quality. If the file is being
transmitted over a slow communications link, the decoder can use the first
scan to display a low-quality image very quickly, and can then improve the
display with each subsequent scan. The final image is exactly equivalent to a
standard JPEG file of the same quality setting, and the total file size is
about the same --- often a little smaller.
.B Caution:
progressive JPEG is not yet widely implemented, so many decoders will be
unable to view a progressive JPEG file at all.
.PP
Switches for advanced users:
.TP
.BI \-maxmemory " N"
Set limit for amount of memory to use in processing large images. Value is
in thousands of bytes, or millions of bytes if "M" is attached to the
number. For example,
.B \-max 4m
selects 4000000 bytes. If more space is needed, temporary files will be used.
.B \-dct int
Use integer DCT method (default).
.TP
.B \-dct fast
Use fast integer DCT (less accurate).
.TP
.B \-dct float
Use floating-point DCT method.
The float method is very slightly more accurate than the int method, but is
much slower unless your machine has very fast floating-point hardware. Also
note that results of the floating-point method may vary slightly across
machines, while the integer methods should give the same results everywhere.
The fast integer method is much less accurate than the other two.
.TP
.BI \-restart " N"
Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is
@@ -157,6 +147,16 @@ attached to the number.
Smooth the input image to eliminate dithering noise. N, ranging from 1 to
100, indicates the strength of smoothing. 0 (the default) means no smoothing.
.TP
.BI \-maxmemory " N"
Set limit for amount of memory to use in processing large images. Value is
in thousands of bytes, or millions of bytes if "M" is attached to the
number. For example,
.B \-max 4m
selects 4000000 bytes. If more space is needed, temporary files will be used.
.TP
.BI \-outfile " name"
Send output image to the named file, not to standard output.
.TP
.B \-verbose
Enable debug printout. More
.BR \-v 's
@@ -180,41 +180,38 @@ for images that will be transmitted across unreliable networks such as Usenet.
The
.B \-smooth
option filters the input to eliminate fine-scale noise. This is often useful
when converting GIF files to JPEG: a moderate smoothing factor of 10 to 50
gets rid of dithering patterns in the input file, resulting in a smaller JPEG
file and a better-looking image. Too large a smoothing factor will visibly
blur the image, however.
when converting dithered images to JPEG: a moderate smoothing factor of 10 to
50 gets rid of dithering patterns in the input file, resulting in a smaller
JPEG file and a better-looking image. Too large a smoothing factor will
visibly blur the image, however.
.PP
Switches for wizards:
.TP
.B \-arithmetic
Use arithmetic coding rather than Huffman coding. (Not currently
supported for legal reasons.)
.TP
.B \-nointerleave
Generate noninterleaved JPEG file (not yet supported).
.B \-baseline
Force baseline-compatible quantization tables to be generated. This clamps
quantization values to 8 bits even at low quality settings. (This switch is
poorly named, since it does not ensure that the output is actually baseline
JPEG. For example, you can use
.B \-baseline
and
.B \-progressive
together.)
.TP
.BI \-qtables " file"
Use the quantization tables given in the specified file. The file should
contain one to four tables (64 values each) as plain text. Comments preceded
by '#' may be included in the file. The tables are implicitly numbered
0,1,etc. If
.B \-quality
N is also specified, the values in the file are scaled according to
.BR cjpeg 's
quality scaling curve.
Use the quantization tables given in the specified text file.
.TP
.BI \-qslots " N[,...]"
Select which quantization table to use for each color component.
.TP
.BI \-sample " HxV[,...]"
Set JPEG sampling factors. If you specify fewer H/V pairs than there are
components, the remaining components are set to 1x1 sampling. The default
setting is equivalent to \fB\-sample 2x2\fR.
Set JPEG sampling factors for each color component.
.TP
.BI \-scans " file"
Use the scan script given in the specified text file.
.PP
The "wizard" switches are intended for experimentation with JPEG. If you
don't know what you are doing, \fBdon't use them\fR. You can easily produce
files with worse image quality and/or poorer compression than you'll get from
the default settings. Furthermore, these switches should not be used when
making files intended for general use, because not all JPEG implementations
will support unusual JPEG parameter settings.
don't know what you are doing, \fBdon't use them\fR. These switches are
documented further in the file wizard.doc.
.SH EXAMPLES
.LP
This example compresses the PPM file foo.ppm with a quality factor of
@@ -224,6 +221,36 @@ This example compresses the PPM file foo.ppm with a quality factor of
.I 60 foo.ppm
.B >
.I foo.jpg
.SH HINTS
Color GIF files are not the ideal input for JPEG; JPEG is really intended for
compressing full-color (24-bit) images. In particular, don't try to convert
cartoons, line drawings, and other images that have only a few distinct
colors. GIF works great on these, JPEG does not. If you want to convert a
GIF to JPEG, you should experiment with
.BR cjpeg 's
.B \-quality
and
.B \-smooth
options to get a satisfactory conversion.
.B \-smooth 10
or so is often helpful.
.PP
Avoid running an image through a series of JPEG compression/decompression
cycles. Image quality loss will accumulate; after ten or so cycles the image
may be noticeably worse than it was after one cycle. It's best to use a
lossless format while manipulating an image, then convert to JPEG format when
you are ready to file the image away.
.PP
The
.B \-optimize
option to
.B cjpeg
is worth using when you are making a "final" version for posting or archiving.
It's also a win when you are using low quality settings to make very small
JPEG files; the percentage improvement is often a lot more than it is on
larger files. (At present,
.B \-optimize
mode is always selected when generating progressive JPEG files.)
.SH ENVIRONMENT
.TP
.B JPEGMEM
@@ -236,7 +263,10 @@ overrides the default value specified when the program was compiled, and
itself is overridden by an explicit
.BR \-maxmemory .
.SH SEE ALSO
.BR djpeg (1)
.BR djpeg (1),
.BR jpegtran (1),
.BR rdjpgcom (1),
.BR wrjpgcom (1)
.br
.BR ppm (5),
.BR pgm (5)
@@ -246,12 +276,16 @@ Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44.
.SH AUTHOR
Independent JPEG Group
.SH BUGS
Arithmetic coding and interleaved output not yet supported.
Arithmetic coding is not supported for legal reasons.
.PP
Not all variants of Targa file format are supported.
GIF input files are no longer supported, to avoid the Unisys LZW patent.
Use a Unisys-licensed program if you need to read a GIF file. (Conversion
of GIF files to JPEG is usually a bad idea anyway.)
.PP
Not all variants of BMP and Targa file formats are supported.
.PP
The
.B -targa
.B \-targa
switch is not a bug, it's a feature. (It would be a bug if the Targa format
designers had not been clueless.)
.PP

606
cjpeg.c Normal file
View File

@@ -0,0 +1,606 @@
/*
* cjpeg.c
*
* Copyright (C) 1991-1998, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains a command-line user interface for the JPEG compressor.
* It should work on any system with Unix- or MS-DOS-style command lines.
*
* Two different command line styles are permitted, depending on the
* compile-time switch TWO_FILE_COMMANDLINE:
* cjpeg [options] inputfile outputfile
* cjpeg [options] [inputfile]
* In the second style, output is always to standard output, which you'd
* normally redirect to a file or pipe to some other program. Input is
* either from a named file or from standard input (typically redirected).
* The second style is convenient on Unix but is unhelpful on systems that
* don't support pipes. Also, you MUST use the first style if your system
* doesn't do binary I/O to stdin/stdout.
* To simplify script writing, the "-outfile" switch is provided. The syntax
* cjpeg [options] -outfile outputfile inputfile
* works regardless of which command line style is used.
*/
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#include "jversion.h" /* for version message */
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
#ifdef __MWERKS__
#include <SIOUX.h> /* Metrowerks needs this */
#include <console.h> /* ... and this */
#endif
#ifdef THINK_C
#include <console.h> /* Think declares it here */
#endif
#endif
/* Create the add-on message string table. */
#define JMESSAGE(code,string) string ,
static const char * const cdjpeg_message_table[] = {
#include "cderror.h"
NULL
};
/*
* This routine determines what format the input file is,
* and selects the appropriate input-reading module.
*
* To determine which family of input formats the file belongs to,
* we may look only at the first byte of the file, since C does not
* guarantee that more than one character can be pushed back with ungetc.
* Looking at additional bytes would require one of these approaches:
* 1) assume we can fseek() the input file (fails for piped input);
* 2) assume we can push back more than one character (works in
* some C implementations, but unportable);
* 3) provide our own buffering (breaks input readers that want to use
* stdio directly, such as the RLE library);
* or 4) don't put back the data, and modify the input_init methods to assume
* they start reading after the start of file (also breaks RLE library).
* #1 is attractive for MS-DOS but is untenable on Unix.
*
* The most portable solution for file types that can't be identified by their
* first byte is to make the user tell us what they are. This is also the
* only approach for "raw" file types that contain only arbitrary values.
* We presently apply this method for Targa files. Most of the time Targa
* files start with 0x00, so we recognize that case. Potentially, however,
* a Targa file could start with any byte value (byte 0 is the length of the
* seldom-used ID field), so we provide a switch to force Targa input mode.
*/
static boolean is_targa; /* records user -targa switch */
LOCAL(cjpeg_source_ptr)
select_file_type (j_compress_ptr cinfo, FILE * infile)
{
int c;
if (is_targa) {
#ifdef TARGA_SUPPORTED
return jinit_read_targa(cinfo);
#else
ERREXIT(cinfo, JERR_TGA_NOTCOMP);
#endif
}
if ((c = getc(infile)) == EOF)
ERREXIT(cinfo, JERR_INPUT_EMPTY);
if (ungetc(c, infile) == EOF)
ERREXIT(cinfo, JERR_UNGETC_FAILED);
switch (c) {
#ifdef BMP_SUPPORTED
case 'B':
return jinit_read_bmp(cinfo);
#endif
#ifdef GIF_SUPPORTED
case 'G':
return jinit_read_gif(cinfo);
#endif
#ifdef PPM_SUPPORTED
case 'P':
return jinit_read_ppm(cinfo);
#endif
#ifdef RLE_SUPPORTED
case 'R':
return jinit_read_rle(cinfo);
#endif
#ifdef TARGA_SUPPORTED
case 0x00:
return jinit_read_targa(cinfo);
#endif
default:
ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
break;
}
return NULL; /* suppress compiler warnings */
}
/*
* Argument-parsing code.
* The switch parser is designed to be useful with DOS-style command line
* syntax, ie, intermixed switches and file names, where only the switches
* to the left of a given file name affect processing of that file.
* The main program in this file doesn't actually use this capability...
*/
static const char * progname; /* program name for error messages */
static char * outfilename; /* for -outfile switch */
LOCAL(void)
usage (void)
/* complain about bad command line */
{
fprintf(stderr, "usage: %s [switches] ", progname);
#ifdef TWO_FILE_COMMANDLINE
fprintf(stderr, "inputfile outputfile\n");
#else
fprintf(stderr, "[inputfile]\n");
#endif
fprintf(stderr, "Switches (names may be abbreviated):\n");
fprintf(stderr, " -quality N Compression quality (0..100; 5-95 is useful range)\n");
fprintf(stderr, " -grayscale Create monochrome JPEG file\n");
#ifdef ENTROPY_OPT_SUPPORTED
fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
#endif
#ifdef C_PROGRESSIVE_SUPPORTED
fprintf(stderr, " -progressive Create progressive JPEG file\n");
#endif
#ifdef TARGA_SUPPORTED
fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n");
#endif
fprintf(stderr, "Switches for advanced users:\n");
#ifdef DCT_ISLOW_SUPPORTED
fprintf(stderr, " -dct int Use integer DCT method%s\n",
(JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
#endif
#ifdef DCT_IFAST_SUPPORTED
fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
(JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
#endif
#ifdef DCT_FLOAT_SUPPORTED
fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
(JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
#endif
fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
#ifdef INPUT_SMOOTHING_SUPPORTED
fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n");
#endif
fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
fprintf(stderr, " -outfile name Specify name for output file\n");
fprintf(stderr, " -verbose or -debug Emit debug output\n");
fprintf(stderr, "Switches for wizards:\n");
#ifdef C_ARITH_CODING_SUPPORTED
fprintf(stderr, " -arithmetic Use arithmetic coding\n");
#endif
fprintf(stderr, " -baseline Force baseline quantization tables\n");
fprintf(stderr, " -qtables file Use quantization tables given in file\n");
fprintf(stderr, " -qslots N[,...] Set component quantization tables\n");
fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n");
#ifdef C_MULTISCAN_FILES_SUPPORTED
fprintf(stderr, " -scans file Create multi-scan JPEG per script file\n");
#endif
exit(EXIT_FAILURE);
}
LOCAL(int)
parse_switches (j_compress_ptr cinfo, int argc, char **argv,
int last_file_arg_seen, boolean for_real)
/* Parse optional switches.
* Returns argv[] index of first file-name argument (== argc if none).
* Any file names with indexes <= last_file_arg_seen are ignored;
* they have presumably been processed in a previous iteration.
* (Pass 0 for last_file_arg_seen on the first or only iteration.)
* for_real is FALSE on the first (dummy) pass; we may skip any expensive
* processing.
*/
{
int argn;
char * arg;
int quality; /* -quality parameter */
int q_scale_factor; /* scaling percentage for -qtables */
boolean force_baseline;
boolean simple_progressive;
char * qtablefile = NULL; /* saves -qtables filename if any */
char * qslotsarg = NULL; /* saves -qslots parm if any */
char * samplearg = NULL; /* saves -sample parm if any */
char * scansarg = NULL; /* saves -scans parm if any */
/* Set up default JPEG parameters. */
/* Note that default -quality level need not, and does not,
* match the default scaling for an explicit -qtables argument.
*/
quality = 75; /* default -quality value */
q_scale_factor = 100; /* default to no scaling for -qtables */
force_baseline = FALSE; /* by default, allow 16-bit quantizers */
simple_progressive = FALSE;
is_targa = FALSE;
outfilename = NULL;
cinfo->err->trace_level = 0;
/* Scan command line options, adjust parameters */
for (argn = 1; argn < argc; argn++) {
arg = argv[argn];
if (*arg != '-') {
/* Not a switch, must be a file name argument */
if (argn <= last_file_arg_seen) {
outfilename = NULL; /* -outfile applies to just one input file */
continue; /* ignore this name if previously processed */
}
break; /* else done parsing switches */
}
arg++; /* advance past switch marker character */
if (keymatch(arg, "arithmetic", 1)) {
/* Use arithmetic coding. */
#ifdef C_ARITH_CODING_SUPPORTED
cinfo->arith_code = TRUE;
#else
fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
progname);
exit(EXIT_FAILURE);
#endif
} else if (keymatch(arg, "baseline", 1)) {
/* Force baseline-compatible output (8-bit quantizer values). */
force_baseline = TRUE;
} else if (keymatch(arg, "dct", 2)) {
/* Select DCT algorithm. */
if (++argn >= argc) /* advance to next argument */
usage();
if (keymatch(argv[argn], "int", 1)) {
cinfo->dct_method = JDCT_ISLOW;
} else if (keymatch(argv[argn], "fast", 2)) {
cinfo->dct_method = JDCT_IFAST;
} else if (keymatch(argv[argn], "float", 2)) {
cinfo->dct_method = JDCT_FLOAT;
} else
usage();
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
/* Enable debug printouts. */
/* On first -d, print version identification */
static boolean printed_version = FALSE;
if (! printed_version) {
fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
JVERSION, JCOPYRIGHT);
printed_version = TRUE;
}
cinfo->err->trace_level++;
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
/* Force a monochrome JPEG file to be generated. */
jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
} else if (keymatch(arg, "maxmemory", 3)) {
/* Maximum memory in Kb (or Mb with 'm'). */
long lval;
char ch = 'x';
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
usage();
if (ch == 'm' || ch == 'M')
lval *= 1000L;
cinfo->mem->max_memory_to_use = lval * 1000L;
} else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
/* Enable entropy parm optimization. */
#ifdef ENTROPY_OPT_SUPPORTED
cinfo->optimize_coding = TRUE;
#else
fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
progname);
exit(EXIT_FAILURE);
#endif
} else if (keymatch(arg, "outfile", 4)) {
/* Set output file name. */
if (++argn >= argc) /* advance to next argument */
usage();
outfilename = argv[argn]; /* save it away for later use */
} else if (keymatch(arg, "progressive", 1)) {
/* Select simple progressive mode. */
#ifdef C_PROGRESSIVE_SUPPORTED
simple_progressive = TRUE;
/* We must postpone execution until num_components is known. */
#else
fprintf(stderr, "%s: sorry, progressive output was not compiled\n",
progname);
exit(EXIT_FAILURE);
#endif
} else if (keymatch(arg, "quality", 1)) {
/* Quality factor (quantization table scaling factor). */
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%d", &quality) != 1)
usage();
/* Change scale factor in case -qtables is present. */
q_scale_factor = jpeg_quality_scaling(quality);
} else if (keymatch(arg, "qslots", 2)) {
/* Quantization table slot numbers. */
if (++argn >= argc) /* advance to next argument */
usage();
qslotsarg = argv[argn];
/* Must delay setting qslots until after we have processed any
* colorspace-determining switches, since jpeg_set_colorspace sets
* default quant table numbers.
*/
} else if (keymatch(arg, "qtables", 2)) {
/* Quantization tables fetched from file. */
if (++argn >= argc) /* advance to next argument */
usage();
qtablefile = argv[argn];
/* We postpone actually reading the file in case -quality comes later. */
} else if (keymatch(arg, "restart", 1)) {
/* Restart interval in MCU rows (or in MCUs with 'b'). */
long lval;
char ch = 'x';
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
usage();
if (lval < 0 || lval > 65535L)
usage();
if (ch == 'b' || ch == 'B') {
cinfo->restart_interval = (unsigned int) lval;
cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
} else {
cinfo->restart_in_rows = (int) lval;
/* restart_interval will be computed during startup */
}
} else if (keymatch(arg, "sample", 2)) {
/* Set sampling factors. */
if (++argn >= argc) /* advance to next argument */
usage();
samplearg = argv[argn];
/* Must delay setting sample factors until after we have processed any
* colorspace-determining switches, since jpeg_set_colorspace sets
* default sampling factors.
*/
} else if (keymatch(arg, "scans", 2)) {
/* Set scan script. */
#ifdef C_MULTISCAN_FILES_SUPPORTED
if (++argn >= argc) /* advance to next argument */
usage();
scansarg = argv[argn];
/* We must postpone reading the file in case -progressive appears. */
#else
fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n",
progname);
exit(EXIT_FAILURE);
#endif
} else if (keymatch(arg, "smooth", 2)) {
/* Set input smoothing factor. */
int val;
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%d", &val) != 1)
usage();
if (val < 0 || val > 100)
usage();
cinfo->smoothing_factor = val;
} else if (keymatch(arg, "targa", 1)) {
/* Input file is Targa format. */
is_targa = TRUE;
} else {
usage(); /* bogus switch */
}
}
/* Post-switch-scanning cleanup */
if (for_real) {
/* Set quantization tables for selected quality. */
/* Some or all may be overridden if -qtables is present. */
jpeg_set_quality(cinfo, quality, force_baseline);
if (qtablefile != NULL) /* process -qtables if it was present */
if (! read_quant_tables(cinfo, qtablefile,
q_scale_factor, force_baseline))
usage();
if (qslotsarg != NULL) /* process -qslots if it was present */
if (! set_quant_slots(cinfo, qslotsarg))
usage();
if (samplearg != NULL) /* process -sample if it was present */
if (! set_sample_factors(cinfo, samplearg))
usage();
#ifdef C_PROGRESSIVE_SUPPORTED
if (simple_progressive) /* process -progressive; -scans can override */
jpeg_simple_progression(cinfo);
#endif
#ifdef C_MULTISCAN_FILES_SUPPORTED
if (scansarg != NULL) /* process -scans if it was present */
if (! read_scan_script(cinfo, scansarg))
usage();
#endif
}
return argn; /* return index of next arg (file name) */
}
/*
* The main program.
*/
int
main (int argc, char **argv)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
#ifdef PROGRESS_REPORT
struct cdjpeg_progress_mgr progress;
#endif
int file_index;
cjpeg_source_ptr src_mgr;
FILE * input_file;
FILE * output_file;
JDIMENSION num_scanlines;
/* On Mac, fetch a command line. */
#ifdef USE_CCOMMAND
argc = ccommand(&argv);
#endif
progname = argv[0];
if (progname == NULL || progname[0] == 0)
progname = "cjpeg"; /* in case C library doesn't provide it */
/* Initialize the JPEG compression object with default error handling. */
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
/* Add some application-specific error messages (from cderror.h) */
jerr.addon_message_table = cdjpeg_message_table;
jerr.first_addon_message = JMSG_FIRSTADDONCODE;
jerr.last_addon_message = JMSG_LASTADDONCODE;
/* Now safe to enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
enable_signal_catcher((j_common_ptr) &cinfo);
#endif
/* Initialize JPEG parameters.
* Much of this may be overridden later.
* In particular, we don't yet know the input file's color space,
* but we need to provide some value for jpeg_set_defaults() to work.
*/
cinfo.in_color_space = JCS_RGB; /* arbitrary guess */
jpeg_set_defaults(&cinfo);
/* Scan command line to find file names.
* It is convenient to use just one switch-parsing routine, but the switch
* values read here are ignored; we will rescan the switches after opening
* the input file.
*/
file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
#ifdef TWO_FILE_COMMANDLINE
/* Must have either -outfile switch or explicit output file name */
if (outfilename == NULL) {
if (file_index != argc-2) {
fprintf(stderr, "%s: must name one input and one output file\n",
progname);
usage();
}
outfilename = argv[file_index+1];
} else {
if (file_index != argc-1) {
fprintf(stderr, "%s: must name one input and one output file\n",
progname);
usage();
}
}
#else
/* Unix style: expect zero or one file name */
if (file_index < argc-1) {
fprintf(stderr, "%s: only one input file\n", progname);
usage();
}
#endif /* TWO_FILE_COMMANDLINE */
/* Open the input file. */
if (file_index < argc) {
if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
exit(EXIT_FAILURE);
}
} else {
/* default input file is stdin */
input_file = read_stdin();
}
/* Open the output file. */
if (outfilename != NULL) {
if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
exit(EXIT_FAILURE);
}
} else {
/* default output file is stdout */
output_file = write_stdout();
}
#ifdef PROGRESS_REPORT
start_progress_monitor((j_common_ptr) &cinfo, &progress);
#endif
/* Figure out the input file format, and set up to read it. */
src_mgr = select_file_type(&cinfo, input_file);
src_mgr->input_file = input_file;
/* Read the input file header to obtain file size & colorspace. */
(*src_mgr->start_input) (&cinfo, src_mgr);
/* Now that we know input colorspace, fix colorspace-dependent defaults */
jpeg_default_colorspace(&cinfo);
/* Adjust default compression parameters by re-parsing the options */
file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
/* Specify data destination for compression */
jpeg_stdio_dest(&cinfo, output_file);
/* Start compressor */
jpeg_start_compress(&cinfo, TRUE);
/* Process data */
while (cinfo.next_scanline < cinfo.image_height) {
num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
(void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
}
/* Finish compression and release memory */
(*src_mgr->finish_input) (&cinfo, src_mgr);
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
/* Close files, if we opened them */
if (input_file != stdin)
fclose(input_file);
if (output_file != stdout)
fclose(output_file);
#ifdef PROGRESS_REPORT
end_progress_monitor((j_common_ptr) &cinfo);
#endif
/* All done. */
exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
return 0; /* suppress no-return-value warnings */
}

View File

@@ -1,404 +0,0 @@
/*
* ckconfig.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*/
/*
* This program is intended to help you determine how to configure the JPEG
* software for installation on a particular system. The idea is to try to
* compile and execute this program. If your compiler fails to compile the
* program, make changes as indicated in the comments below. Once you can
* compile the program, run it, and it will tell you how to set the various
* switches in jconfig.h and in your Makefile.
*
* This could all be done automatically if we could assume we were on a Unix
* system, but we don't want to assume that, so you'll have to edit and
* recompile this program until it works.
*
* As a general rule, each time you try to compile this program,
* pay attention only to the *first* error message you get from the compiler.
* Many C compilers will issue lots of spurious error messages once they
* have gotten confused. Go to the line indicated in the first error message,
* and read the comments preceding that line to see what to change.
*
* Almost all of the edits you may need to make to this program consist of
* changing a line that reads "#define SOME_SYMBOL" to "#undef SOME_SYMBOL",
* or vice versa. This is called defining or undefining that symbol.
*/
/* First we must see if your system has the include files we need.
* We start out with the assumption that your system follows the ANSI
* conventions for include files. If you get any error in the next dozen
* lines, undefine INCLUDES_ARE_ANSI.
*/
#define INCLUDES_ARE_ANSI /* replace 'define' by 'undef' if error here */
#ifdef INCLUDES_ARE_ANSI /* this will be skipped if you undef... */
#include <stdio.h> /* If you ain't got this, you ain't got C. */
#ifdef __SASC /* Amiga SAS C provides size_t in stddef.h. */
#include <stddef.h> /* (They are wrong...) */
#endif
#include <string.h> /* size_t might be here too. */
typedef size_t my_size_t; /* The payoff: do we have size_t now? */
#include <stdlib.h> /* Check other ANSI includes we use. */
#endif
/* If your system doesn't follow the ANSI conventions, we have to figure out
* what it does follow. If you didn't get an error before this line, you can
* ignore everything down to "#define HAVE_ANSI_DEFINITIONS".
*/
#ifndef INCLUDES_ARE_ANSI /* skip these tests if INCLUDES_ARE_ANSI */
#include <stdio.h> /* If you ain't got this, you ain't got C. */
/* jinclude.h will try to include <sys/types.h> if you don't set
* INCLUDES_ARE_ANSI. We need to test whether that include file is provided.
* If you get an error here, undefine HAVE_TYPES_H.
*/
#define HAVE_TYPES_H
#ifdef HAVE_TYPES_H
#include <sys/types.h>
#endif
/* We have to see if your string functions are defined by
* strings.h (BSD convention) or string.h (everybody else).
* We try the non-BSD convention first; define BSD if the compiler
* says it can't find string.h.
*/
#undef BSD
#ifdef BSD
#include <strings.h>
#else
#include <string.h>
#endif
/* Usually size_t is defined in stdio.h, sys/types.h, and/or string.h.
* If not, you'll get an error on the "typedef size_t my_size_t;" line below.
* In that case, you'll have to search through your system library to
* figure out which include file defines "size_t". Look for a line that
* says "typedef something-or-other size_t;" (stddef.h and stdlib.h are
* good places to look first). Then, change the line below that says
* "#include <someincludefile.h>" to instead include the file
* you found size_t in, and define NEED_SPECIAL_INCLUDE.
*/
#undef NEED_SPECIAL_INCLUDE /* assume we DON'T need it, for starters */
#ifdef NEED_SPECIAL_INCLUDE
#include <someincludefile.h>
#endif
typedef size_t my_size_t; /* The payoff: do we have size_t now? */
#endif /* INCLUDES_ARE_ANSI */
/* The next question is whether your compiler supports ANSI-style function
* definitions. You need to know this in order to choose between using
* makefile.ansi and using makefile.unix.
* The #define line below is set to assume you have ANSI function definitions.
* If you get an error in this group of lines, undefine HAVE_ANSI_DEFINITIONS.
*/
#define HAVE_ANSI_DEFINITIONS
#ifdef HAVE_ANSI_DEFINITIONS
int testfunction (int arg1, int * arg2); /* check prototypes */
struct methods_struct { /* check method-pointer declarations */
int (*error_exit) (char *msgtext);
int (*trace_message) (char *msgtext);
int (*another_method) (void);
};
int testfunction (int arg1, int * arg2) /* check definitions */
{
return arg2[arg1];
}
int testfunction1 (void) /* check void arg list */
{
return 0;
}
#endif
/* Now we want to find out if your compiler knows what "unsigned char" means.
* If you get an error on the "unsigned char un_char;" line,
* then undefine HAVE_UNSIGNED_CHAR.
*/
#define HAVE_UNSIGNED_CHAR
#ifdef HAVE_UNSIGNED_CHAR
unsigned char un_char;
#endif
/* Now we want to find out if your compiler knows what "unsigned short" means.
* If you get an error on the "unsigned short un_short;" line,
* then undefine HAVE_UNSIGNED_SHORT.
*/
#define HAVE_UNSIGNED_SHORT
#ifdef HAVE_UNSIGNED_SHORT
unsigned short un_short;
#endif
/* Now we want to find out if your compiler understands type "void".
* If you get an error anywhere in here, undefine HAVE_VOID.
*/
#define HAVE_VOID
#ifdef HAVE_VOID
typedef void * void_ptr; /* check void * */
typedef void (*void_func) (); /* check ptr to function returning void */
void testfunction2 (arg1, arg2) /* check void function result */
void_ptr arg1;
void_func arg2;
{
char * locptr = (char *) arg1; /* check casting to and from void * */
arg1 = (void *) locptr;
(*arg2) (1, 2); /* check call of fcn returning void */
}
#endif
/* Now we want to find out if your compiler knows what "const" means.
* If you get an error here, undefine HAVE_CONST.
*/
#define HAVE_CONST
#ifdef HAVE_CONST
static const int carray[3] = {1, 2, 3};
int testfunction3 (arg1)
const int arg1;
{
return carray[arg1];
}
#endif
/************************************************************************
* OK, that's it. You should not have to change anything beyond this
* point in order to compile and execute this program. (You might get
* some warnings, but you can ignore them.)
* When you run the program, it will make a couple more tests that it
* can do automatically, and then it will print out a summary of the changes
* that you need to make to the makefile and jconfig.h.
************************************************************************
*/
static int any_changes = 0;
int new_change ()
{
if (! any_changes) {
printf("\nMost of the changes recommended by this program can be made either\n");
printf("by editing jconfig.h, or by adding -Dsymbol switches to the CFLAGS\n");
printf("line in your Makefile. (Some PC compilers expect /Dsymbol instead.)\n");
printf("The CFLAGS method is simpler, but if your compiler doesn't support -D,\n");
printf("then you must change jconfig.h. Also, it's best to change jconfig.h\n");
printf("if you plan to use the JPEG software as a library for other programs.\n");
any_changes = 1;
}
printf("\n"); /* blank line before each problem report */
return 0;
}
int test_char_sign (arg)
int arg;
{
if (arg == 189) { /* expected result for unsigned char */
new_change();
printf("You should add -DCHAR_IS_UNSIGNED to CFLAGS,\n");
printf("or else remove the /* */ comment marks from the line\n");
printf("/* #define CHAR_IS_UNSIGNED */ in jconfig.h.\n");
printf("(Be sure to delete the space before the # character too.)\n");
}
else if (arg != -67) { /* expected result for signed char */
new_change();
printf("Hmm, it seems 'char' is less than eight bits wide on your machine.\n");
printf("I fear the JPEG software will not work at all.\n");
}
return 0;
}
int test_shifting (arg)
long arg;
/* See whether right-shift on a long is signed or not. */
{
long res = arg >> 4;
if (res == 0x80817F4L) { /* expected result for unsigned */
new_change();
printf("You must add -DRIGHT_SHIFT_IS_UNSIGNED to CFLAGS,\n");
printf("or else remove the /* */ comment marks from the line\n");
printf("/* #define RIGHT_SHIFT_IS_UNSIGNED */ in jconfig.h.\n");
}
else if (res != -0x7F7E80CL) { /* expected result for signed */
new_change();
printf("Right shift isn't acting as I expect it to.\n");
printf("I fear the JPEG software will not work at all.\n");
}
return 0;
}
int main (argc, argv)
int argc;
char ** argv;
{
char signed_char_check = (char) (-67);
printf("Results of configuration check for Independent JPEG Group's software:\n");
printf("\nIf there's not a specific makefile provided for your compiler,\n");
#ifdef HAVE_ANSI_DEFINITIONS
printf("you should use makefile.ansi as the starting point for your Makefile.\n");
#else
printf("you should use makefile.unix as the starting point for your Makefile.\n");
#endif
/* Check whether we have all the ANSI features, */
/* and whether this agrees with __STDC__ being predefined. */
#ifdef __STDC__
#define HAVE_STDC /* ANSI compilers won't allow redefining __STDC__ */
#endif
#ifdef HAVE_ANSI_DEFINITIONS
#ifdef HAVE_UNSIGNED_CHAR
#ifdef HAVE_UNSIGNED_SHORT
#ifdef HAVE_CONST
#define HAVE_ALL_ANSI_FEATURES
#endif
#endif
#endif
#endif
#ifdef HAVE_ALL_ANSI_FEATURES
#ifndef HAVE_STDC
new_change();
printf("Your compiler doesn't claim to be ANSI-compliant, but it is close enough\n");
printf("for me. Either add -DHAVE_STDC to CFLAGS, or add #define HAVE_STDC at the\n");
printf("beginning of jconfig.h.\n");
#define HAVE_STDC
#endif
#else /* !HAVE_ALL_ANSI_FEATURES */
#ifdef HAVE_STDC
new_change();
printf("Your compiler claims to be ANSI-compliant, but it is lying!\n");
printf("Delete the line #define HAVE_STDC near the beginning of jconfig.h.\n");
#undef HAVE_STDC
#endif
#endif /* HAVE_ALL_ANSI_FEATURES */
#ifndef HAVE_STDC
#ifdef HAVE_ANSI_DEFINITIONS
new_change();
printf("You should add -DPROTO to CFLAGS, or else take out the several\n");
printf("#ifdef/#else/#endif lines surrounding #define PROTO in jconfig.h.\n");
printf("(Leave only one #define PROTO line.)\n");
#endif
#ifdef HAVE_UNSIGNED_CHAR
#ifdef HAVE_UNSIGNED_SHORT
new_change();
printf("You should add -DHAVE_UNSIGNED_CHAR and -DHAVE_UNSIGNED_SHORT\n");
printf("to CFLAGS, or else take out the #ifdef HAVE_STDC/#endif lines\n");
printf("surrounding #define HAVE_UNSIGNED_CHAR and #define HAVE_UNSIGNED_SHORT\n");
printf("in jconfig.h.\n");
#else /* only unsigned char */
new_change();
printf("You should add -DHAVE_UNSIGNED_CHAR to CFLAGS,\n");
printf("or else move #define HAVE_UNSIGNED_CHAR outside the\n");
printf("#ifdef HAVE_STDC/#endif lines surrounding it in jconfig.h.\n");
#endif
#else /* !HAVE_UNSIGNED_CHAR */
#ifdef HAVE_UNSIGNED_SHORT
new_change();
printf("You should add -DHAVE_UNSIGNED_SHORT to CFLAGS,\n");
printf("or else move #define HAVE_UNSIGNED_SHORT outside the\n");
printf("#ifdef HAVE_STDC/#endif lines surrounding it in jconfig.h.\n");
#endif
#endif /* HAVE_UNSIGNED_CHAR */
#ifdef HAVE_CONST
new_change();
printf("You should delete the #define const line from jconfig.h.\n");
#endif
#endif /* HAVE_STDC */
test_char_sign((int) signed_char_check);
test_shifting(-0x7F7E80B1L);
#ifndef HAVE_VOID
new_change();
printf("You should add -Dvoid=char to CFLAGS,\n");
printf("or else remove the /* */ comment marks from the line\n");
printf("/* #define void char */ in jconfig.h.\n");
printf("(Be sure to delete the space before the # character too.)\n");
#endif
#ifdef INCLUDES_ARE_ANSI
#ifndef __STDC__
new_change();
printf("You should add -DINCLUDES_ARE_ANSI to CFLAGS, or else add\n");
printf("#define INCLUDES_ARE_ANSI at the beginning of jinclude.h (NOT jconfig.h).\n");
#endif
#else /* !INCLUDES_ARE_ANSI */
#ifdef __STDC__
new_change();
printf("You should add -DNONANSI_INCLUDES to CFLAGS, or else add\n");
printf("#define NONANSI_INCLUDES at the beginning of jinclude.h (NOT jconfig.h).\n");
#endif
#ifdef NEED_SPECIAL_INCLUDE
new_change();
printf("In jinclude.h, change the line reading #include <sys/types.h>\n");
printf("to instead include the file you found size_t in.\n");
#else /* !NEED_SPECIAL_INCLUDE */
#ifndef HAVE_TYPES_H
new_change();
printf("In jinclude.h, delete the line reading #include <sys/types.h>.\n");
#endif
#endif /* NEED_SPECIAL_INCLUDE */
#ifdef BSD
new_change();
printf("You should add -DBSD to CFLAGS, or else add\n");
printf("#define BSD at the beginning of jinclude.h (NOT jconfig.h).\n");
#endif
#endif /* INCLUDES_ARE_ANSI */
if (any_changes) {
printf("\nI think that's everything...\n");
} else {
printf("\nI think jconfig.h is OK as distributed.\n");
}
return any_changes;
}

118
coderules.doc Normal file
View File

@@ -0,0 +1,118 @@
IJG JPEG LIBRARY: CODING RULES
Copyright (C) 1991-1996, Thomas G. Lane.
This file is part of the Independent JPEG Group's software.
For conditions of distribution and use, see the accompanying README file.
Since numerous people will be contributing code and bug fixes, it's important
to establish a common coding style. The goal of using similar coding styles
is much more important than the details of just what that style is.
In general we follow the recommendations of "Recommended C Style and Coding
Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and
Brader). This document is available in the IJG FTP archive (see
jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl).
Block comments should be laid out thusly:
/*
* Block comments in this style.
*/
We indent statements in K&R style, e.g.,
if (test) {
then-part;
} else {
else-part;
}
with two spaces per indentation level. (This indentation convention is
handled automatically by GNU Emacs and many other text editors.)
Multi-word names should be written in lower case with underscores, e.g.,
multi_word_name (not multiWordName). Preprocessor symbols and enum constants
are similar but upper case (MULTI_WORD_NAME). Names should be unique within
the first fifteen characters. (On some older systems, global names must be
unique within six characters. We accommodate this without cluttering the
source code by using macros to substitute shorter names.)
We use function prototypes everywhere; we rely on automatic source code
transformation to feed prototype-less C compilers. Transformation is done
by the simple and portable tool 'ansi2knr.c' (courtesy of Ghostscript).
ansi2knr is not very bright, so it imposes a format requirement on function
declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions
should be written in the following style:
LOCAL(int *)
function_name (int a, char *b)
{
code...
}
Note that each function definition must begin with GLOBAL(type), LOCAL(type),
or METHODDEF(type). These macros expand to "static type" or just "type" as
appropriate. They provide a readable indication of the routine's usage and
can readily be changed for special needs. (For instance, special linkage
keywords can be inserted for use in Windows DLLs.)
ansi2knr does not transform method declarations (function pointers in
structs). We handle these with a macro JMETHOD, defined as
#ifdef HAVE_PROTOTYPES
#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
#else
#define JMETHOD(type,methodname,arglist) type (*methodname) ()
#endif
which is used like this:
struct function_pointers {
JMETHOD(void, init_entropy_encoder, (int somearg, jparms *jp));
JMETHOD(void, term_entropy_encoder, (void));
};
Note the set of parentheses surrounding the parameter list.
A similar solution is used for forward and external function declarations
(see the EXTERN and JPP macros).
If the code is to work on non-ANSI compilers, we cannot rely on a prototype
declaration to coerce actual parameters into the right types. Therefore, use
explicit casts on actual parameters whenever the actual parameter type is not
identical to the formal parameter. Beware of implicit conversions to "int".
It seems there are some non-ANSI compilers in which the sizeof() operator
is defined to return int, yet size_t is defined as long. Needless to say,
this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(),
so that the result is guaranteed to be of type size_t.
The JPEG library is intended to be used within larger programs. Furthermore,
we want it to be reentrant so that it can be used by applications that process
multiple images concurrently. The following rules support these requirements:
1. Avoid direct use of file I/O, "malloc", error report printouts, etc;
pass these through the common routines provided.
2. Minimize global namespace pollution. Functions should be declared static
wherever possible. (Note that our method-based calling conventions help this
a lot: in many modules only the initialization function will ever need to be
called directly, so only that function need be externally visible.) All
global function names should begin with "jpeg_", and should have an
abbreviated name (unique in the first six characters) substituted by macro
when NEED_SHORT_EXTERNAL_NAMES is set.
3. Don't use global variables; anything that must be used in another module
should be in the common data structures.
4. Don't use static variables except for read-only constant tables. Variables
that should be private to a module can be placed into private structures (see
the system architecture document, structure.doc).
5. Source file names should begin with "j" for files that are part of the
library proper; source files that are not part of the library, such as cjpeg.c
and djpeg.c, do not begin with "j". Keep source file names to eight
characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers. Keep
compression and decompression code in separate source files --- some
applications may want only one half of the library.
Note: these rules (particularly #4) are not followed religiously in the
modules that are used in cjpeg/djpeg but are not part of the JPEG library
proper. Those modules are not really intended to be used in other
applications.

View File

@@ -1,99 +0,0 @@
JPEG SYSTEM CODING RULES 27-SEP-91
Since numerous people will be contributing code and bug fixes, it's important
to establish a common coding style. The goal of using similar coding styles
is much more important than the details of just what that style is.
I suggest we follow the recommendations of "Recommended C Style and Coding
Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and
Brader). I have placed a copy of this document in the jpeg FTP archive (see
jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl).
Unless someone has a real strong objection, let's do block comments thusly:
/*
* Block comments in this style.
*/
and indent statements in K&R style, e.g.,
if (test) {
then-part;
} else {
else-part;
}
I suggest that multi-word names be written in the style multi_word_name
rather than multiWordName, but I am open to argument on this.
I would like to use function prototypes everywhere, and rely on automatic
source code transformation to feed non-ANSI C compilers. The best tool
I have so far found for this is 'ansi2knr.c', which is part of Ghostscript.
ansi2knr is not very bright, so it imposes a format requirement on function
declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions
should be written in the following style:
static int *
function_name (int a, char *b)
{
code...
}
ansi2knr won't help with method declarations (function pointers in structs).
I suggest we use a macro to declare method pointers, something like this:
#ifdef PROTO
#define METHOD(type,methodname,arglist) type (*methodname) arglist
#else
#define METHOD(type,methodname,arglist) type (*methodname) ()
#endif
which is used like this:
struct function_pointers {
METHOD(void, init_entropy_encoder, (functptrs fptrs, jparms *jp));
METHOD(void, term_entropy_encoder, (void));
};
Note the set of parentheses surrounding the parameter list.
A similar solution is used for external function declarations (see the PP
macro in jpegdata.h).
If the code is to work on non-ANSI compilers, you cannot rely on a prototype
declaration to coerce actual parameters into the right types. Therefore, use
explicit casts on actual parameters whenever the actual parameter type is not
identical to the formal parameter. Beware of implicit conversions to "int".
It seems there are some non-ANSI compilers in which the sizeof() operator
is defined to return int, while size_t is defined as long. Needless to say,
this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(),
so that the result is guaranteed to be of type size_t.
We can expect that the JPEG compressor and decompressor will be incorporated
into larger programs. Therefore, the following rules are important:
1. Avoid direct use of any file I/O, "malloc", error report printouts, etc;
pass these through the common routines provided.
2. Assume that the JPEG code may be invoked more than once per program run;
therefore, do not rely on static initialization of variables, and be careful
to release all allocated storage at the end of processing.
3. Minimize global namespace pollution. Functions should be declared static
wherever possible. (Note that our method-based calling conventions help this
a lot: in many modules only the method-selector function will ever need to be
called directly, so only that function need be externally visible.) All
global function names should begin with "j", and should be unique in the first
six characters for portability reasons.
Don't use global variables at all; anything that must be used in another
module should be put into parameters (there'll be some large structs passed
around for this purpose).
4. Source file names should also begin with "j"; remember to keep them to
eight characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers.
Do not put code for both compression and decompression into the same source
file.

184
configure.ac Normal file
View File

@@ -0,0 +1,184 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.56])
AC_INIT([libjpeg-turbo], [0.0.93])
BUILD=`date +%Y%m%d`
AM_INIT_AUTOMAKE([-Wall foreign dist-bzip2])
AC_PREFIX_DEFAULT(/opt/libjpeg-turbo)
# Always build with prototypes
AC_DEFINE([HAVE_PROTOTYPES], 1, [Define if your compiler supports prototypes])
# Don't use undefined types
AC_DEFINE([INCOMPLETE_TYPES_BROKEN], 1, [Define if you want use complete types])
# Checks for programs.
SAVED_CFLAGS=${CFLAGS}
SAVED_CXXFLAGS=${CXXFLAGS}
AC_PROG_CPP
AC_PROG_CC
AC_PROG_CXX
AC_PROG_INSTALL
AC_PROG_LIBTOOL
AC_PROG_LN_S
AC_MSG_CHECKING([whether the linker supports version scripts])
VERSION_SCRIPT=no
LDVER=`$LD --help </dev/null 2>&1 | grep "\-\-version-script"`
if test "$LDVER"; then
VERSION_SCRIPT=yes
VERSION_SCRIPT_FLAG=-Wl,--version-script,
AC_MSG_RESULT(yes)
else
LDVER=`$LD --help </dev/null 2>&1 | grep "\-M"`
if test "$LDVER"; then
VERSION_SCRIPT=yes
VERSION_SCRIPT_FLAG=-Wl,-M,
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
fi
AM_CONDITIONAL(VERSION_SCRIPT, test "x$VERSION_SCRIPT" = "xyes")
AC_SUBST(VERSION_SCRIPT_FLAG)
if test "x${GCC}" = "xyes"; then
if test "x${SAVED_CFLAGS}" = "x"; then
CFLAGS=-O3
fi
if test "x${SAVED_CXXFLAGS}" = "x"; then
CXXFLAGS=-O3
fi
fi
AC_CHECK_DECL([__SUNPRO_C], [SUNCC="yes"], [SUNCC="no"])
if test "x${SUNCC}" = "xyes"; then
if test "x${SAVED_CFLAGS}" = "x"; then
CFLAGS=-xO5
fi
if test "x${SAVED_CXXFLAGS}" = "x"; then
CXXFLAGS=-xO5
fi
fi
# Checks for libraries.
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([stddef.h stdlib.h string.h])
AC_CHECK_HEADER([sys/types.h], AC_DEFINE([NEED_SYS_TYPES_H], 1, [Define if you have sys/types.h]))
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_CHAR_UNSIGNED
AC_C_INLINE
AC_TYPE_SIZE_T
AC_CHECK_TYPES([unsigned char, unsigned short])
AC_MSG_CHECKING([if right shift is signed])
AC_TRY_RUN(
[#include <stdio.h>
int is_shifting_signed (long arg) {
long res = arg >> 4;
if (res == -0x7F7E80CL)
return 1; /* right shift is signed */
/* see if unsigned-shift hack will fix it. */
/* we can't just test exact value since it depends on width of long... */
res |= (~0L) << (32-4);
if (res == -0x7F7E80CL)
return 0; /* right shift is unsigned */
printf("Right shift isn't acting as I expect it to.\n");
printf("I fear the JPEG software will not work at all.\n\n");
return 0; /* try it with unsigned anyway */
}
int main (void) {
exit(is_shifting_signed(-0x7F7E80B1L));
}],
[AC_MSG_RESULT(no)
AC_DEFINE([RIGHT_SHIFT_IS_UNSIGNED], 1, [Define if shift is unsigned])],
[AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(Assuming that right shift is signed on target machine.)])
# test whether global names are unique to at least 15 chars
AC_MSG_CHECKING([for short external names])
AC_TRY_LINK(
[int possibly_duplicate_function () { return 0; }
int possibly_dupli_function () { return 1; }], [ ],
[AC_MSG_RESULT(ok)],
[AC_MSG_RESULT(short)
AC_DEFINE([NEED_SHORT_EXTERNAL_NAMES], 1, [Define if you need short function names])])
# Checks for library functions.
AC_CHECK_FUNCS([memset memcpy], [],
[AC_DEFINE([NEED_BSD_STRINGS], 1,
[Define if you have BSD-like bzero and bcopy])])
# Set flags to indicate platform
case "$host_os" in
cygwin* | mingw* | pw32* | interix*)
is_win32=1
;;
esac
AM_CONDITIONAL([IS_WIN32], [test "x$is_win32" = "x1"])
# SIMD is optional
AC_ARG_WITH([simd],
AC_HELP_STRING([--without-simd],[Omit accelerated SIMD routines.]))
if test "x${with_simd}" != "xno"; then
# Check if we're on a supported CPU
AC_MSG_CHECKING([if we have SIMD optimisations for cpu type])
case "$host_cpu" in
x86_64)
AC_MSG_RESULT([yes (x86_64)])
AC_PROG_NASM
simd_arch=x86_64
;;
i*86 | x86 | ia32)
AC_MSG_RESULT([yes (i386)])
AC_PROG_NASM
simd_arch=i386
;;
*)
AC_MSG_RESULT([no ("$host_cpu")])
AC_MSG_ERROR([CPU is not supported])
;;
esac
if test "x${with_simd}" != "xno"; then
AC_DEFINE([WITH_SIMD], [1], [Use accelerated SIMD routines.])
fi
fi
AM_CONDITIONAL([WITH_SIMD], [test "x$with_simd" != "xno"])
AM_CONDITIONAL([SIMD_I386], [test "x$simd_arch" = "xi386"])
AM_CONDITIONAL([SIMD_X86_64], [test "x$simd_arch" = "xx86_64"])
AM_CONDITIONAL([X86_64], [test "x$host_cpu" = "xx86_64"])
case "$host_cpu" in
x86_64)
RPMARCH=x86_64
DEBARCH=amd64
;;
i*86 | x86 | ia32)
RPMARCH=i386
DEBARCH=i386
;;
esac
AC_SUBST(RPMARCH)
AC_SUBST(DEBARCH)
AC_SUBST(BUILD)
# jconfig.h is the file we use, but we have another before that to
# fool autoheader. the reason is that we include this header in our
# API headers, which can screw things up for users of the lib.
# jconfig.h is a minimal version that allows this package to be built
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_HEADERS([jconfig.h])
AC_CONFIG_FILES([Makefile simd/Makefile])
AC_OUTPUT

200
djpeg.1
View File

@@ -1,43 +1,10 @@
.TH DJPEG 1 "17 February 1993"
.TH DJPEG 1 "22 August 1997"
.SH NAME
djpeg \- decompress a JPEG file to an image file
.SH SYNOPSIS
.B djpeg
[
.BI \-colors " N"
]
[
.B \-gif
]
[
.B \-pnm
]
[
.B \-rle
]
[
.B \-targa
]
[
.B \-blocksmooth
]
[
.B \-grayscale
]
[
.BI \-maxmemory " N"
]
[
.B \-nodither
]
[
.B \-onepass
]
[
.B \-verbose
]
[
.B \-debug
.I options
]
[
.I filename
@@ -47,9 +14,9 @@ djpeg \- decompress a JPEG file to an image file
.LP
.B djpeg
decompresses the named JPEG file, or the standard input if no file is named,
and produces an image file on the standard output. PBMPLUS (PPM/PGM), GIF,
Targa, or RLE (Utah Raster Toolkit) output format can be selected. (RLE is
supported only if the URT library is available.)
and produces an image file on the standard output. PBMPLUS (PPM/PGM), BMP,
GIF, Targa, or RLE (Utah Raster Toolkit) output format can be selected.
(RLE is supported only if the URT library is available.)
.SH OPTIONS
All switch names may be abbreviated; for example,
.B \-grayscale
@@ -59,9 +26,9 @@ or
.BR \-gr .
Most of the "basic" switches can be abbreviated to as little as one letter.
Upper and lower case are equivalent (thus
.B \-GIF
.B \-BMP
is the same as
.BR \-gif ).
.BR \-bmp ).
British spellings are also accepted (e.g.,
.BR \-greyscale ),
though for brevity these are not mentioned below.
@@ -82,11 +49,47 @@ is the recommended name,
.B \-quantize
is provided only for backwards compatibility.
.TP
.B \-fast
Select recommended processing options for fast, low quality output. (The
default options are chosen for highest quality output.) Currently, this is
equivalent to \fB\-dct fast \-nosmooth \-onepass \-dither ordered\fR.
.TP
.B \-grayscale
Force gray-scale output even if JPEG file is color. Useful for viewing on
monochrome displays; also,
.B djpeg
runs noticeably faster in this mode.
.TP
.BI \-scale " M/N"
Scale the output image by a factor M/N. Currently the scale factor must be
1/1, 1/2, 1/4, or 1/8. Scaling is handy if the image is larger than your
screen; also,
.B djpeg
runs much faster when scaling down the output.
.TP
.B \-bmp
Select BMP output format (Windows flavor). 8-bit colormapped format is
emitted if
.B \-colors
or
.B \-grayscale
is specified, or if the JPEG file is gray-scale; otherwise, 24-bit full-color
format is emitted.
.TP
.B \-gif
Select GIF output format. Since GIF does not support more than 256 colors,
.B \-colors 256
is assumed (unless you specify a smaller number of colors).
.TP
.B \-os2
Select BMP output format (OS/2 1.x flavor). 8-bit colormapped format is
emitted if
.B \-colors
or
.B \-grayscale
is specified, or if the JPEG file is gray-scale; otherwise, 24-bit full-color
format is emitted.
.TP
.B \-pnm
Select PBMPLUS (PPM/PGM) output format (this is the default format).
PGM is emitted if the JPEG file is gray-scale or if
@@ -106,32 +109,48 @@ is specified; otherwise, 24-bit full-color format is emitted.
.PP
Switches for advanced users:
.TP
.B \-blocksmooth
Perform cross-block smoothing. This is slow, quite memory-intensive, and only
seems to improve the image at very low quality settings (\fB\-quality\fR 10 to
20 or so). At normal quality settings it may make the image worse.
.B \-dct int
Use integer DCT method (default).
.TP
.B \-grayscale
Force gray-scale output even if JPEG file is color.
Useful for viewing on monochrome displays.
.B \-dct fast
Use fast integer DCT (less accurate).
.TP
.BI \-maxmemory " N"
Set limit for amount of memory to use in processing large images. Value is
in thousands of bytes, or millions of bytes if "M" is attached to the
number. For example,
.B \-max 4m
selects 4000000 bytes. If more space is needed, temporary files will be used.
.B \-dct float
Use floating-point DCT method.
The float method is very slightly more accurate than the int method, but is
much slower unless your machine has very fast floating-point hardware. Also
note that results of the floating-point method may vary slightly across
machines, while the integer methods should give the same results everywhere.
The fast integer method is much less accurate than the other two.
.TP
.B \-nodither
Do not use dithering in color quantization. By default, Floyd-Steinberg
dithering is applied when quantizing colors, but on some images dithering may
result in objectionable "graininess". If that happens, you can turn off
dithering with
.BR \-nodither .
.B \-nodither
is ignored unless you also say
.B \-dither fs
Use Floyd-Steinberg dithering in color quantization.
.TP
.B \-dither ordered
Use ordered dithering in color quantization.
.TP
.B \-dither none
Do not use dithering in color quantization.
By default, Floyd-Steinberg dithering is applied when quantizing colors; this
is slow but usually produces the best results. Ordered dither is a compromise
between speed and quality; no dithering is fast but usually looks awful. Note
that these switches have no effect unless color quantization is being done.
Ordered dither is only available in
.B \-onepass
mode.
.TP
.BI \-map " file"
Quantize to the colors used in the specified image file. This is useful for
producing multiple files with identical color maps, or for forcing a
predefined set of colors to be used. The
.I file
must be a GIF or PPM file. This option overrides
.B \-colors
.IR N .
and
.BR \-onepass .
.TP
.B \-nosmooth
Use a faster, lower-quality upsampling routine.
.TP
.B \-onepass
Use one-pass instead of two-pass color quantization. The one-pass method is
@@ -143,6 +162,16 @@ is ignored unless you also say
Also, the one-pass method is always used for gray-scale output (the two-pass
method is no improvement then).
.TP
.BI \-maxmemory " N"
Set limit for amount of memory to use in processing large images. Value is
in thousands of bytes, or millions of bytes if "M" is attached to the
number. For example,
.B \-max 4m
selects 4000000 bytes. If more space is needed, temporary files will be used.
.TP
.BI \-outfile " name"
Send output image to the named file, not to standard output.
.TP
.B \-verbose
Enable debug printout. More
.BR \-v 's
@@ -153,13 +182,42 @@ Same as
.BR \-verbose .
.SH EXAMPLES
.LP
This example decompresses the JPEG file foo.jpg, automatically quantizes to
256 colors, and saves the output in GIF format in foo.gif:
This example decompresses the JPEG file foo.jpg, quantizes it to
256 colors, and saves the output in 8-bit BMP format in foo.bmp:
.IP
.B djpeg \-gif
.B djpeg \-colors 256 \-bmp
.I foo.jpg
.B >
.I foo.gif
.I foo.bmp
.SH HINTS
To get a quick preview of an image, use the
.B \-grayscale
and/or
.B \-scale
switches.
.B \-grayscale \-scale 1/8
is the fastest case.
.PP
Several options are available that trade off image quality to gain speed.
.B \-fast
turns on the recommended settings.
.PP
.B \-dct fast
and/or
.B \-nosmooth
gain speed at a small sacrifice in quality.
When producing a color-quantized image,
.B \-onepass \-dither ordered
is fast but much lower quality than the default behavior.
.B \-dither none
may give acceptable results in two-pass mode, but is seldom tolerable in
one-pass mode.
.PP
If you are fortunate enough to have very fast floating point hardware,
\fB\-dct float\fR may be even faster than \fB\-dct fast\fR. But on most
machines \fB\-dct float\fR is slower than \fB\-dct int\fR; in this case it is
not worth using, because its theoretical accuracy advantage is too small to be
significant in practice.
.SH ENVIRONMENT
.TP
.B JPEGMEM
@@ -172,7 +230,10 @@ overrides the default value specified when the program was compiled, and
itself is overridden by an explicit
.BR \-maxmemory .
.SH SEE ALSO
.BR cjpeg (1)
.BR cjpeg (1),
.BR jpegtran (1),
.BR rdjpgcom (1),
.BR wrjpgcom (1)
.br
.BR ppm (5),
.BR pgm (5)
@@ -184,4 +245,9 @@ Independent JPEG Group
.SH BUGS
Arithmetic coding is not supported for legal reasons.
.PP
To avoid the Unisys LZW patent,
.B djpeg
produces uncompressed GIF files. These are larger than they should be, but
are readable by standard GIF decoders.
.PP
Still not as fast as we'd like.

616
djpeg.c Normal file
View File

@@ -0,0 +1,616 @@
/*
* djpeg.c
*
* Copyright (C) 1991-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains a command-line user interface for the JPEG decompressor.
* It should work on any system with Unix- or MS-DOS-style command lines.
*
* Two different command line styles are permitted, depending on the
* compile-time switch TWO_FILE_COMMANDLINE:
* djpeg [options] inputfile outputfile
* djpeg [options] [inputfile]
* In the second style, output is always to standard output, which you'd
* normally redirect to a file or pipe to some other program. Input is
* either from a named file or from standard input (typically redirected).
* The second style is convenient on Unix but is unhelpful on systems that
* don't support pipes. Also, you MUST use the first style if your system
* doesn't do binary I/O to stdin/stdout.
* To simplify script writing, the "-outfile" switch is provided. The syntax
* djpeg [options] -outfile outputfile inputfile
* works regardless of which command line style is used.
*/
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#include "jversion.h" /* for version message */
#include <ctype.h> /* to declare isprint() */
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
#ifdef __MWERKS__
#include <SIOUX.h> /* Metrowerks needs this */
#include <console.h> /* ... and this */
#endif
#ifdef THINK_C
#include <console.h> /* Think declares it here */
#endif
#endif
/* Create the add-on message string table. */
#define JMESSAGE(code,string) string ,
static const char * const cdjpeg_message_table[] = {
#include "cderror.h"
NULL
};
/*
* This list defines the known output image formats
* (not all of which need be supported by a given version).
* You can change the default output format by defining DEFAULT_FMT;
* indeed, you had better do so if you undefine PPM_SUPPORTED.
*/
typedef enum {
FMT_BMP, /* BMP format (Windows flavor) */
FMT_GIF, /* GIF format */
FMT_OS2, /* BMP format (OS/2 flavor) */
FMT_PPM, /* PPM/PGM (PBMPLUS formats) */
FMT_RLE, /* RLE format */
FMT_TARGA, /* Targa format */
FMT_TIFF /* TIFF format */
} IMAGE_FORMATS;
#ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */
#define DEFAULT_FMT FMT_PPM
#endif
static IMAGE_FORMATS requested_fmt;
/*
* Argument-parsing code.
* The switch parser is designed to be useful with DOS-style command line
* syntax, ie, intermixed switches and file names, where only the switches
* to the left of a given file name affect processing of that file.
* The main program in this file doesn't actually use this capability...
*/
static const char * progname; /* program name for error messages */
static char * outfilename; /* for -outfile switch */
LOCAL(void)
usage (void)
/* complain about bad command line */
{
fprintf(stderr, "usage: %s [switches] ", progname);
#ifdef TWO_FILE_COMMANDLINE
fprintf(stderr, "inputfile outputfile\n");
#else
fprintf(stderr, "[inputfile]\n");
#endif
fprintf(stderr, "Switches (names may be abbreviated):\n");
fprintf(stderr, " -colors N Reduce image to no more than N colors\n");
fprintf(stderr, " -fast Fast, low-quality processing\n");
fprintf(stderr, " -grayscale Force grayscale output\n");
#ifdef IDCT_SCALING_SUPPORTED
fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n");
#endif
#ifdef BMP_SUPPORTED
fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n",
(DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
#endif
#ifdef GIF_SUPPORTED
fprintf(stderr, " -gif Select GIF output format%s\n",
(DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
#endif
#ifdef BMP_SUPPORTED
fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n",
(DEFAULT_FMT == FMT_OS2 ? " (default)" : ""));
#endif
#ifdef PPM_SUPPORTED
fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n",
(DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
#endif
#ifdef RLE_SUPPORTED
fprintf(stderr, " -rle Select Utah RLE output format%s\n",
(DEFAULT_FMT == FMT_RLE ? " (default)" : ""));
#endif
#ifdef TARGA_SUPPORTED
fprintf(stderr, " -targa Select Targa output format%s\n",
(DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
#endif
fprintf(stderr, "Switches for advanced users:\n");
#ifdef DCT_ISLOW_SUPPORTED
fprintf(stderr, " -dct int Use integer DCT method%s\n",
(JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
#endif
#ifdef DCT_IFAST_SUPPORTED
fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
(JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
#endif
#ifdef DCT_FLOAT_SUPPORTED
fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
(JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
#endif
fprintf(stderr, " -dither fs Use F-S dithering (default)\n");
fprintf(stderr, " -dither none Don't use dithering in quantization\n");
fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)\n");
#ifdef QUANT_2PASS_SUPPORTED
fprintf(stderr, " -map FILE Map to colors used in named image file\n");
#endif
fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n");
#ifdef QUANT_1PASS_SUPPORTED
fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n");
#endif
fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
fprintf(stderr, " -outfile name Specify name for output file\n");
fprintf(stderr, " -verbose or -debug Emit debug output\n");
exit(EXIT_FAILURE);
}
LOCAL(int)
parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
int last_file_arg_seen, boolean for_real)
/* Parse optional switches.
* Returns argv[] index of first file-name argument (== argc if none).
* Any file names with indexes <= last_file_arg_seen are ignored;
* they have presumably been processed in a previous iteration.
* (Pass 0 for last_file_arg_seen on the first or only iteration.)
* for_real is FALSE on the first (dummy) pass; we may skip any expensive
* processing.
*/
{
int argn;
char * arg;
/* Set up default JPEG parameters. */
requested_fmt = DEFAULT_FMT; /* set default output file format */
outfilename = NULL;
cinfo->err->trace_level = 0;
/* Scan command line options, adjust parameters */
for (argn = 1; argn < argc; argn++) {
arg = argv[argn];
if (*arg != '-') {
/* Not a switch, must be a file name argument */
if (argn <= last_file_arg_seen) {
outfilename = NULL; /* -outfile applies to just one input file */
continue; /* ignore this name if previously processed */
}
break; /* else done parsing switches */
}
arg++; /* advance past switch marker character */
if (keymatch(arg, "bmp", 1)) {
/* BMP output format. */
requested_fmt = FMT_BMP;
} else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
/* Do color quantization. */
int val;
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%d", &val) != 1)
usage();
cinfo->desired_number_of_colors = val;
cinfo->quantize_colors = TRUE;
} else if (keymatch(arg, "dct", 2)) {
/* Select IDCT algorithm. */
if (++argn >= argc) /* advance to next argument */
usage();
if (keymatch(argv[argn], "int", 1)) {
cinfo->dct_method = JDCT_ISLOW;
} else if (keymatch(argv[argn], "fast", 2)) {
cinfo->dct_method = JDCT_IFAST;
} else if (keymatch(argv[argn], "float", 2)) {
cinfo->dct_method = JDCT_FLOAT;
} else
usage();
} else if (keymatch(arg, "dither", 2)) {
/* Select dithering algorithm. */
if (++argn >= argc) /* advance to next argument */
usage();
if (keymatch(argv[argn], "fs", 2)) {
cinfo->dither_mode = JDITHER_FS;
} else if (keymatch(argv[argn], "none", 2)) {
cinfo->dither_mode = JDITHER_NONE;
} else if (keymatch(argv[argn], "ordered", 2)) {
cinfo->dither_mode = JDITHER_ORDERED;
} else
usage();
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
/* Enable debug printouts. */
/* On first -d, print version identification */
static boolean printed_version = FALSE;
if (! printed_version) {
fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
JVERSION, JCOPYRIGHT);
printed_version = TRUE;
}
cinfo->err->trace_level++;
} else if (keymatch(arg, "fast", 1)) {
/* Select recommended processing options for quick-and-dirty output. */
cinfo->two_pass_quantize = FALSE;
cinfo->dither_mode = JDITHER_ORDERED;
if (! cinfo->quantize_colors) /* don't override an earlier -colors */
cinfo->desired_number_of_colors = 216;
cinfo->dct_method = JDCT_FASTEST;
cinfo->do_fancy_upsampling = FALSE;
} else if (keymatch(arg, "gif", 1)) {
/* GIF output format. */
requested_fmt = FMT_GIF;
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
/* Force monochrome output. */
cinfo->out_color_space = JCS_GRAYSCALE;
} else if (keymatch(arg, "map", 3)) {
/* Quantize to a color map taken from an input file. */
if (++argn >= argc) /* advance to next argument */
usage();
if (for_real) { /* too expensive to do twice! */
#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */
FILE * mapfile;
if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
exit(EXIT_FAILURE);
}
read_color_map(cinfo, mapfile);
fclose(mapfile);
cinfo->quantize_colors = TRUE;
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
}
} else if (keymatch(arg, "maxmemory", 3)) {
/* Maximum memory in Kb (or Mb with 'm'). */
long lval;
char ch = 'x';
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
usage();
if (ch == 'm' || ch == 'M')
lval *= 1000L;
cinfo->mem->max_memory_to_use = lval * 1000L;
} else if (keymatch(arg, "nosmooth", 3)) {
/* Suppress fancy upsampling */
cinfo->do_fancy_upsampling = FALSE;
} else if (keymatch(arg, "onepass", 3)) {
/* Use fast one-pass quantization. */
cinfo->two_pass_quantize = FALSE;
} else if (keymatch(arg, "os2", 3)) {
/* BMP output format (OS/2 flavor). */
requested_fmt = FMT_OS2;
} else if (keymatch(arg, "outfile", 4)) {
/* Set output file name. */
if (++argn >= argc) /* advance to next argument */
usage();
outfilename = argv[argn]; /* save it away for later use */
} else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) {
/* PPM/PGM output format. */
requested_fmt = FMT_PPM;
} else if (keymatch(arg, "rle", 1)) {
/* RLE output format. */
requested_fmt = FMT_RLE;
} else if (keymatch(arg, "scale", 1)) {
/* Scale the output image by a fraction M/N. */
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%d/%d",
&cinfo->scale_num, &cinfo->scale_denom) != 2)
usage();
} else if (keymatch(arg, "targa", 1)) {
/* Targa output format. */
requested_fmt = FMT_TARGA;
} else {
usage(); /* bogus switch */
}
}
return argn; /* return index of next arg (file name) */
}
/*
* Marker processor for COM and interesting APPn markers.
* This replaces the library's built-in processor, which just skips the marker.
* We want to print out the marker as text, to the extent possible.
* Note this code relies on a non-suspending data source.
*/
LOCAL(unsigned int)
jpeg_getc (j_decompress_ptr cinfo)
/* Read next byte */
{
struct jpeg_source_mgr * datasrc = cinfo->src;
if (datasrc->bytes_in_buffer == 0) {
if (! (*datasrc->fill_input_buffer) (cinfo))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
}
datasrc->bytes_in_buffer--;
return GETJOCTET(*datasrc->next_input_byte++);
}
METHODDEF(boolean)
print_text_marker (j_decompress_ptr cinfo)
{
boolean traceit = (cinfo->err->trace_level >= 1);
INT32 length;
unsigned int ch;
unsigned int lastch = 0;
length = jpeg_getc(cinfo) << 8;
length += jpeg_getc(cinfo);
length -= 2; /* discount the length word itself */
if (traceit) {
if (cinfo->unread_marker == JPEG_COM)
fprintf(stderr, "Comment, length %ld:\n", (long) length);
else /* assume it is an APPn otherwise */
fprintf(stderr, "APP%d, length %ld:\n",
cinfo->unread_marker - JPEG_APP0, (long) length);
}
while (--length >= 0) {
ch = jpeg_getc(cinfo);
if (traceit) {
/* Emit the character in a readable form.
* Nonprintables are converted to \nnn form,
* while \ is converted to \\.
* Newlines in CR, CR/LF, or LF form will be printed as one newline.
*/
if (ch == '\r') {
fprintf(stderr, "\n");
} else if (ch == '\n') {
if (lastch != '\r')
fprintf(stderr, "\n");
} else if (ch == '\\') {
fprintf(stderr, "\\\\");
} else if (isprint(ch)) {
putc(ch, stderr);
} else {
fprintf(stderr, "\\%03o", ch);
}
lastch = ch;
}
}
if (traceit)
fprintf(stderr, "\n");
return TRUE;
}
/*
* The main program.
*/
int
main (int argc, char **argv)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
#ifdef PROGRESS_REPORT
struct cdjpeg_progress_mgr progress;
#endif
int file_index;
djpeg_dest_ptr dest_mgr = NULL;
FILE * input_file;
FILE * output_file;
JDIMENSION num_scanlines;
/* On Mac, fetch a command line. */
#ifdef USE_CCOMMAND
argc = ccommand(&argv);
#endif
progname = argv[0];
if (progname == NULL || progname[0] == 0)
progname = "djpeg"; /* in case C library doesn't provide it */
/* Initialize the JPEG decompression object with default error handling. */
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
/* Add some application-specific error messages (from cderror.h) */
jerr.addon_message_table = cdjpeg_message_table;
jerr.first_addon_message = JMSG_FIRSTADDONCODE;
jerr.last_addon_message = JMSG_LASTADDONCODE;
/* Insert custom marker processor for COM and APP12.
* APP12 is used by some digital camera makers for textual info,
* so we provide the ability to display it as text.
* If you like, additional APPn marker types can be selected for display,
* but don't try to override APP0 or APP14 this way (see libjpeg.doc).
*/
jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker);
jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker);
/* Now safe to enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
enable_signal_catcher((j_common_ptr) &cinfo);
#endif
/* Scan command line to find file names. */
/* It is convenient to use just one switch-parsing routine, but the switch
* values read here are ignored; we will rescan the switches after opening
* the input file.
* (Exception: tracing level set here controls verbosity for COM markers
* found during jpeg_read_header...)
*/
file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
#ifdef TWO_FILE_COMMANDLINE
/* Must have either -outfile switch or explicit output file name */
if (outfilename == NULL) {
if (file_index != argc-2) {
fprintf(stderr, "%s: must name one input and one output file\n",
progname);
usage();
}
outfilename = argv[file_index+1];
} else {
if (file_index != argc-1) {
fprintf(stderr, "%s: must name one input and one output file\n",
progname);
usage();
}
}
#else
/* Unix style: expect zero or one file name */
if (file_index < argc-1) {
fprintf(stderr, "%s: only one input file\n", progname);
usage();
}
#endif /* TWO_FILE_COMMANDLINE */
/* Open the input file. */
if (file_index < argc) {
if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
exit(EXIT_FAILURE);
}
} else {
/* default input file is stdin */
input_file = read_stdin();
}
/* Open the output file. */
if (outfilename != NULL) {
if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
exit(EXIT_FAILURE);
}
} else {
/* default output file is stdout */
output_file = write_stdout();
}
#ifdef PROGRESS_REPORT
start_progress_monitor((j_common_ptr) &cinfo, &progress);
#endif
/* Specify data source for decompression */
jpeg_stdio_src(&cinfo, input_file);
/* Read file header, set default decompression parameters */
(void) jpeg_read_header(&cinfo, TRUE);
/* Adjust default decompression parameters by re-parsing the options */
file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
/* Initialize the output module now to let it override any crucial
* option settings (for instance, GIF wants to force color quantization).
*/
switch (requested_fmt) {
#ifdef BMP_SUPPORTED
case FMT_BMP:
dest_mgr = jinit_write_bmp(&cinfo, FALSE);
break;
case FMT_OS2:
dest_mgr = jinit_write_bmp(&cinfo, TRUE);
break;
#endif
#ifdef GIF_SUPPORTED
case FMT_GIF:
dest_mgr = jinit_write_gif(&cinfo);
break;
#endif
#ifdef PPM_SUPPORTED
case FMT_PPM:
dest_mgr = jinit_write_ppm(&cinfo);
break;
#endif
#ifdef RLE_SUPPORTED
case FMT_RLE:
dest_mgr = jinit_write_rle(&cinfo);
break;
#endif
#ifdef TARGA_SUPPORTED
case FMT_TARGA:
dest_mgr = jinit_write_targa(&cinfo);
break;
#endif
default:
ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
break;
}
dest_mgr->output_file = output_file;
/* Start decompressor */
(void) jpeg_start_decompress(&cinfo);
/* Write output file header */
(*dest_mgr->start_output) (&cinfo, dest_mgr);
/* Process data */
while (cinfo.output_scanline < cinfo.output_height) {
num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
dest_mgr->buffer_height);
(*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
}
#ifdef PROGRESS_REPORT
/* Hack: count final pass as done in case finish_output does an extra pass.
* The library won't have updated completed_passes.
*/
progress.pub.completed_passes = progress.pub.total_passes;
#endif
/* Finish decompression and release memory.
* I must do it in this order because output module has allocated memory
* of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
*/
(*dest_mgr->finish_output) (&cinfo, dest_mgr);
(void) jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
/* Close files, if we opened them */
if (input_file != stdin)
fclose(input_file);
if (output_file != stdout)
fclose(output_file);
#ifdef PROGRESS_REPORT
end_progress_monitor((j_common_ptr) &cinfo);
#endif
/* All done. */
exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
return 0; /* suppress no-return-value warnings */
}

846
example.c
View File

@@ -1,31 +1,29 @@
/*
* example.c
*
* This file is not actually part of the JPEG software. Rather, it provides
* a skeleton that may be useful for constructing applications that use the
* JPEG software as subroutines. This code will NOT do anything useful as is.
* This file illustrates how to use the IJG code as a subroutine library
* to read or write JPEG image files. You should look at this code in
* conjunction with the documentation file libjpeg.doc.
*
* This file illustrates how to use the JPEG code as a subroutine library
* to read or write JPEG image files. We assume here that you are not
* merely interested in converting the image to yet another image file format
* (if you are, you should be adding another I/O module to cjpeg/djpeg, not
* constructing a new application). Instead, we show how to pass the
* decompressed image data into or out of routines that you provide. For
* example, a viewer program might use the JPEG decompressor together with
* routines that write the decompressed image directly to a display.
* This code will not do anything useful as-is, but it may be helpful as a
* skeleton for constructing routines that call the JPEG library.
*
* We present these routines in the same coding style used in the JPEG code
* (ANSI function definitions, etc); but you are of course free to code your
* routines in a different style if you prefer.
*/
#include <stdio.h>
/*
* Include file for declaring JPEG data structures.
* This file also includes some system headers like <stdio.h>;
* if you prefer, you can include "jconfig.h" and "jpegdata.h" instead.
* Include file for users of JPEG library.
* You will need to have included system headers that define at least
* the typedefs FILE and size_t before you can include jpeglib.h.
* (stdio.h is sufficient on ANSI-conforming systems.)
* You may also wish to include "jerror.h".
*/
#include "jinclude.h"
#include "jpeglib.h"
/*
* <setjmp.h> is used for the optional error recovery mechanism shown in
@@ -45,587 +43,391 @@
/*
* To supply the image data for compression, you must define three routines
* input_init, get_input_row, and input_term. These routines will be called
* from the JPEG compressor via function pointer values that you store in the
* cinfo data structure; hence they need not be globally visible and the exact
* names don't matter. (In fact, the "METHODDEF" macro expands to "static" if
* you use the unmodified JPEG include files.)
* IMAGE DATA FORMATS:
*
* The input file reading modules (jrdppm.c, jrdgif.c, jrdtarga.c, etc) may be
* useful examples of what these routines should actually do, although each of
* them is encrusted with a lot of specialized code for its own file format.
* The standard input image format is a rectangular array of pixels, with
* each pixel having the same number of "component" values (color channels).
* Each pixel row is an array of JSAMPLEs (which typically are unsigned chars).
* If you are working with color data, then the color values for each pixel
* must be adjacent in the row; for example, R,G,B,R,G,B,R,G,B,... for 24-bit
* RGB color.
*
* For this example, we'll assume that this data structure matches the way
* our application has stored the image in memory, so we can just pass a
* pointer to our image buffer. In particular, let's say that the image is
* RGB color and is described by:
*/
METHODDEF void
input_init (compress_info_ptr cinfo)
/* Initialize for input; return image size and component data. */
{
/* This routine must return five pieces of information about the incoming
* image, and must do any setup needed for the get_input_row routine.
* The image information is returned in fields of the cinfo struct.
* (If you don't care about modularity, you could initialize these fields
* in the main JPEG calling routine, and make this routine be a no-op.)
* We show some example values here.
*/
cinfo->image_width = 640; /* width in pixels */
cinfo->image_height = 480; /* height in pixels */
/* JPEG views an image as being a rectangular array of pixels, with each
* pixel having the same number of "component" values (color channels).
* You must specify how many components there are and the colorspace
* interpretation of the components. Most applications will use RGB data or
* grayscale data. If you want to use something else, you'll need to study
* and perhaps modify jcdeflts.c, jccolor.c, and jdcolor.c.
*/
cinfo->input_components = 3; /* or 1 for grayscale */
cinfo->in_color_space = CS_RGB; /* or CS_GRAYSCALE for grayscale */
cinfo->data_precision = 8; /* bits per pixel component value */
/* In the current JPEG software, data_precision must be set equal to
* BITS_IN_JSAMPLE, which is 8 unless you twiddle jconfig.h. Future
* versions might allow you to say either 8 or 12 if compiled with
* 12-bit JSAMPLEs, or up to 16 in lossless mode. In any case,
* it is up to you to scale incoming pixel values to the range
* 0 .. (1<<data_precision)-1.
* If your image data format is fixed at a byte per component,
* then saying "8" is probably the best long-term solution.
*/
}
extern JSAMPLE * image_buffer; /* Points to large array of R,G,B-order data */
extern int image_height; /* Number of rows in image */
extern int image_width; /* Number of columns in image */
/*
* This function is called repeatedly and must supply the next row of pixels
* on each call. The rows MUST be returned in top-to-bottom order if you want
* your JPEG files to be compatible with everyone else's. (If you cannot
* readily read your data in that order, you'll need an intermediate array to
* hold the image. See jrdtarga.c or jrdrle.c for examples of handling
* bottom-to-top source data using the JPEG code's portable mechanisms.)
* The data is to be returned into a 2-D array of JSAMPLEs, indexed as
* JSAMPLE pixel_row[component][column]
* where component runs from 0 to cinfo->input_components-1, and column runs
* from 0 to cinfo->image_width-1 (column 0 is left edge of image). Note that
* this is actually an array of pointers to arrays rather than a true 2D array,
* since C does not support variable-size multidimensional arrays.
* JSAMPLE is typically typedef'd as "unsigned char".
* Sample routine for JPEG compression. We assume that the target file name
* and a compression quality factor are passed in.
*/
METHODDEF void
get_input_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* Read next row of pixels into pixel_row[][] */
GLOBAL(void)
write_JPEG_file (char * filename, int quality)
{
/* This example shows how you might read RGB data (3 components)
* from an input file in which the data is stored 3 bytes per pixel
* in left-to-right, top-to-bottom order.
/* This struct contains the JPEG compression parameters and pointers to
* working space (which is allocated as needed by the JPEG library).
* It is possible to have several such structures, representing multiple
* compression/decompression processes, in existence at once. We refer
* to any one struct (and its associated working data) as a "JPEG object".
*/
register FILE * infile = cinfo->input_file;
register JSAMPROW ptr0, ptr1, ptr2;
register long col;
ptr0 = pixel_row[0];
ptr1 = pixel_row[1];
ptr2 = pixel_row[2];
for (col = 0; col < cinfo->image_width; col++) {
*ptr0++ = (JSAMPLE) getc(infile); /* red */
*ptr1++ = (JSAMPLE) getc(infile); /* green */
*ptr2++ = (JSAMPLE) getc(infile); /* blue */
}
}
METHODDEF void
input_term (compress_info_ptr cinfo)
/* Finish up at the end of the input */
{
/* This termination routine will very often have no work to do, */
/* but you must provide it anyway. */
/* Note that the JPEG code will only call it during successful exit; */
/* if you want it called during error exit, you gotta do that yourself. */
}
/*
* That's it for the routines that deal with reading the input image data.
* Now we have overall control and parameter selection routines.
struct jpeg_compress_struct cinfo;
/* This struct represents a JPEG error handler. It is declared separately
* because applications often want to supply a specialized error handler
* (see the second half of this file for an example). But here we just
* take the easy way out and use the standard error handler, which will
* print a message on stderr and call exit() if compression fails.
* Note that this struct must live as long as the main JPEG parameter
* struct, to avoid dangling-pointer problems.
*/
struct jpeg_error_mgr jerr;
/* More stuff */
FILE * outfile; /* target file */
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
int row_stride; /* physical row width in image buffer */
/* Step 1: allocate and initialize JPEG compression object */
/*
* This routine must determine what output JPEG file format is to be written,
* and make any other compression parameter changes that are desirable.
* This routine gets control after the input file header has been read
* (i.e., right after input_init has been called). You could combine its
* functions into input_init, or even into the main control routine, but
* if you have several different input_init routines, it's a definite win
* to keep this separate. You MUST supply this routine even if it's a no-op.
/* We have to set up the error handler first, in case the initialization
* step fails. (Unlikely, but it could happen if you are out of memory.)
* This routine fills in the contents of struct jerr, and returns jerr's
* address which we place into the link field in cinfo.
*/
cinfo.err = jpeg_std_error(&jerr);
/* Now we can initialize the JPEG compression object. */
jpeg_create_compress(&cinfo);
METHODDEF void
c_ui_method_selection (compress_info_ptr cinfo)
{
/* If the input is gray scale, generate a monochrome JPEG file. */
if (cinfo->in_color_space == CS_GRAYSCALE)
j_monochrome_default(cinfo);
/* For now, always select JFIF output format. */
jselwjfif(cinfo);
}
/* Step 2: specify data destination (eg, a file) */
/* Note: steps 2 and 3 can be done in either order. */
/*
* OK, here is the main function that actually causes everything to happen.
* We assume here that the target filename is supplied by the caller of this
* routine, and that all JPEG compression parameters can be default values.
*/
GLOBAL void
write_JPEG_file (char * filename)
{
/* These three structs contain JPEG parameters and working data.
* They must survive for the duration of parameter setup and one
* call to jpeg_compress; typically, making them local data in the
* calling routine is the best strategy.
*/
struct Compress_info_struct cinfo;
struct Compress_methods_struct c_methods;
struct External_methods_struct e_methods;
/* Initialize the system-dependent method pointers. */
cinfo.methods = &c_methods; /* links to method structs */
cinfo.emethods = &e_methods;
/* Here we use the default JPEG error handler, which will just print
* an error message on stderr and call exit(). See the second half of
* this file for an example of more graceful error recovery.
*/
jselerror(&e_methods); /* select std error/trace message routines */
/* Here we use the standard memory manager provided with the JPEG code.
* In some cases you might want to replace the memory manager, or at
* least the system-dependent part of it, with your own code.
*/
jselmemmgr(&e_methods); /* select std memory allocation routines */
/* If the compressor requires full-image buffers (for entropy-coding
* optimization or a noninterleaved JPEG file), it will create temporary
* files for anything that doesn't fit within the maximum-memory setting.
* (Note that temp files are NOT needed if you use the default parameters.)
* You can change the default maximum-memory setting by changing
* e_methods.max_memory_to_use after jselmemmgr returns.
* On some systems you may also need to set up a signal handler to
* ensure that temporary files are deleted if the program is interrupted.
* (This is most important if you are on MS-DOS and use the jmemdos.c
* memory manager back end; it will try to grab extended memory for
* temp files, and that space will NOT be freed automatically.)
* See jcmain.c or jdmain.c for an example signal handler.
*/
/* Here, set up pointers to your own routines for input data handling
* and post-init parameter selection.
*/
c_methods.input_init = input_init;
c_methods.get_input_row = get_input_row;
c_methods.input_term = input_term;
c_methods.c_ui_method_selection = c_ui_method_selection;
/* Set up default JPEG parameters in the cinfo data structure. */
j_c_defaults(&cinfo, 75, FALSE);
/* Note: 75 is the recommended default quality level; you may instead pass
* a user-specified quality level. Be aware that values below 25 will cause
* non-baseline JPEG files to be created (and a warning message to that
* effect to be emitted on stderr). This won't bother our decoder, but some
* commercial JPEG implementations may choke on non-baseline JPEG files.
* If you want to force baseline compatibility, pass TRUE instead of FALSE.
* (If non-baseline files are fine, but you could do without that warning
* message, set e_methods.trace_level to -1.)
*/
/* At this point you can modify the default parameters set by j_c_defaults
* as needed. For a minimal implementation, you shouldn't need to change
* anything. See jcmain.c for some examples of what you might change.
*/
/* Select the input and output files.
* Note that cinfo.input_file is only used if your input reading routines
* use it; otherwise, you can just make it NULL.
/* Here we use the library-supplied code to send compressed data to a
* stdio stream. You can also write your own code to do something else.
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
* requires it in order to write binary files.
*/
cinfo.input_file = NULL; /* if no actual input file involved */
if ((cinfo.output_file = fopen(filename, "wb")) == NULL) {
if ((outfile = fopen(filename, "wb")) == NULL) {
fprintf(stderr, "can't open %s\n", filename);
exit(1);
}
jpeg_stdio_dest(&cinfo, outfile);
/* Here we go! */
jpeg_compress(&cinfo);
/* Step 3: set parameters for compression */
/* That's it, son. Nothin' else to do, except close files. */
/* Here we assume only the output file need be closed. */
fclose(cinfo.output_file);
/* Note: if you want to compress more than one image, we recommend you
* repeat this whole routine. You MUST repeat the j_c_defaults()/alter
* parameters/jpeg_compress() sequence, as some data structures allocated
* in j_c_defaults are freed upon exit from jpeg_compress.
/* First we supply a description of the input image.
* Four fields of the cinfo struct must be filled in:
*/
cinfo.image_width = image_width; /* image width and height, in pixels */
cinfo.image_height = image_height;
cinfo.input_components = 3; /* # of color components per pixel */
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
/* Now use the library's routine to set default compression parameters.
* (You must set at least cinfo.in_color_space before calling this,
* since the defaults depend on the source color space.)
*/
jpeg_set_defaults(&cinfo);
/* Now you can set any non-default parameters you wish to.
* Here we just illustrate the use of quality (quantization table) scaling:
*/
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
/* Step 4: Start compressor */
/* TRUE ensures that we will write a complete interchange-JPEG file.
* Pass TRUE unless you are very sure of what you're doing.
*/
jpeg_start_compress(&cinfo, TRUE);
/* Step 5: while (scan lines remain to be written) */
/* jpeg_write_scanlines(...); */
/* Here we use the library's state variable cinfo.next_scanline as the
* loop counter, so that we don't have to keep track ourselves.
* To keep things simple, we pass one scanline per call; you can pass
* more if you wish, though.
*/
row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
while (cinfo.next_scanline < cinfo.image_height) {
/* jpeg_write_scanlines expects an array of pointers to scanlines.
* Here the array is only one element long, but you could pass
* more than one scanline at a time if that's more convenient.
*/
row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
/* Step 6: Finish compression */
jpeg_finish_compress(&cinfo);
/* After finish_compress, we can close the output file. */
fclose(outfile);
/* Step 7: release JPEG compression object */
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_compress(&cinfo);
/* And we're done! */
}
/*
* SOME FINE POINTS:
*
* In the above loop, we ignored the return value of jpeg_write_scanlines,
* which is the number of scanlines actually written. We could get away
* with this because we were only relying on the value of cinfo.next_scanline,
* which will be incremented correctly. If you maintain additional loop
* variables then you should be careful to increment them properly.
* Actually, for output to a stdio stream you needn't worry, because
* then jpeg_write_scanlines will write all the lines passed (or else exit
* with a fatal error). Partial writes can only occur if you use a data
* destination module that can demand suspension of the compressor.
* (If you don't know what that's for, you don't need it.)
*
* If the compressor requires full-image buffers (for entropy-coding
* optimization or a multi-scan JPEG file), it will create temporary
* files for anything that doesn't fit within the maximum-memory setting.
* (Note that temp files are NOT needed if you use the default parameters.)
* On some systems you may need to set up a signal handler to ensure that
* temporary files are deleted if the program is interrupted. See libjpeg.doc.
*
* Scanlines MUST be supplied in top-to-bottom order if you want your JPEG
* files to be compatible with everyone else's. If you cannot readily read
* your data in that order, you'll need an intermediate array to hold the
* image. See rdtarga.c or rdbmp.c for examples of handling bottom-to-top
* source data using the JPEG code's internal virtual-array mechanisms.
*/
/******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/
/* This half of the example shows how to read data from the JPEG decompressor.
* It's a little more refined than the above in that we show how to do your
* own error recovery. If you don't care about that, you don't need these
* next two routines.
*/
/*
* These routines replace the default trace/error routines included with the
* JPEG code. The example trace_message routine shown here is actually the
* same as the standard one, but you could modify it if you don't want messages
* sent to stderr. The example error_exit routine is set up to return
* control to read_JPEG_file() rather than calling exit(). You can use the
* same routines for both compression and decompression error recovery.
*/
/* These static variables are needed by the error routines. */
static jmp_buf setjmp_buffer; /* for return to caller */
static external_methods_ptr emethods; /* needed for access to message_parm */
/* This routine is used for any and all trace, debug, or error printouts
* from the JPEG code. The parameter is a printf format string; up to 8
* integer data values for the format string have been stored in the
* message_parm[] field of the external_methods struct.
*/
METHODDEF void
trace_message (const char *msgtext)
{
fprintf(stderr, msgtext,
emethods->message_parm[0], emethods->message_parm[1],
emethods->message_parm[2], emethods->message_parm[3],
emethods->message_parm[4], emethods->message_parm[5],
emethods->message_parm[6], emethods->message_parm[7]);
fprintf(stderr, "\n"); /* there is no \n in the format string! */
}
/*
* The error_exit() routine should not return to its caller. The default
* routine calls exit(), but here we assume that we want to return to
* read_JPEG_file, which has set up a setjmp context for the purpose.
* You should make sure that the free_all method is called, either within
* error_exit or after the return to the outer-level routine.
*/
METHODDEF void
error_exit (const char *msgtext)
{
trace_message(msgtext); /* report the error message */
(*emethods->free_all) (); /* clean up memory allocation & temp files */
longjmp(setjmp_buffer, 1); /* return control to outer routine */
}
/*
* To accept the image data from decompression, you must define four routines
* output_init, put_color_map, put_pixel_rows, and output_term.
* It's a bit more refined than the above, in that we show:
* (a) how to modify the JPEG library's standard error-reporting behavior;
* (b) how to allocate workspace using the library's memory manager.
*
* You must understand the distinction between full color output mode
* (N independent color components) and colormapped output mode (a single
* output component representing an index into a color map). You should use
* colormapped mode to write to a colormapped display screen or output file.
* Colormapped mode is also useful for reducing grayscale output to a small
* number of gray levels: when using the 1-pass quantizer on grayscale data,
* the colormap entries will be evenly spaced from 0 to MAX_JSAMPLE, so you
* can regard the indexes as directly representing gray levels at reduced
* precision. In any other case, you should not depend on the colormap
* entries having any particular order.
* To get colormapped output, set cinfo->quantize_colors to TRUE and set
* cinfo->desired_number_of_colors to the maximum number of entries in the
* colormap. This can be done either in your main routine or in
* d_ui_method_selection. For grayscale quantization, also set
* cinfo->two_pass_quantize to FALSE to ensure the 1-pass quantizer is used
* (presently this is the default, but it may not be so in the future).
*
* The output file writing modules (jwrppm.c, jwrgif.c, jwrtarga.c, etc) may be
* useful examples of what these routines should actually do, although each of
* them is encrusted with a lot of specialized code for its own file format.
*/
METHODDEF void
output_init (decompress_info_ptr cinfo)
/* This routine should do any setup required */
{
/* This routine can initialize for output based on the data passed in cinfo.
* Useful fields include:
* image_width, image_height Pretty obvious, I hope.
* data_precision bits per pixel value; typically 8.
* out_color_space output colorspace previously requested
* color_out_comps number of color components in same
* final_out_comps number of components actually output
* final_out_comps is 1 if quantize_colors is true, else it is equal to
* color_out_comps.
*
* If you have requested color quantization, the colormap is NOT yet set.
* You may wish to defer output initialization until put_color_map is called.
*/
}
/*
* This routine is called if and only if you have set cinfo->quantize_colors
* to TRUE. It is given the selected colormap and can complete any required
* initialization. This call will occur after output_init and before any
* calls to put_pixel_rows. Note that the colormap pointer is also placed
* in a cinfo field, whence it can be used by put_pixel_rows or output_term.
* num_colors will be less than or equal to desired_number_of_colors.
*
* The colormap data is supplied as a 2-D array of JSAMPLEs, indexed as
* JSAMPLE colormap[component][indexvalue]
* where component runs from 0 to cinfo->color_out_comps-1, and indexvalue
* runs from 0 to num_colors-1. Note that this is actually an array of
* pointers to arrays rather than a true 2D array, since C does not support
* variable-size multidimensional arrays.
* JSAMPLE is typically typedef'd as "unsigned char". If you want your code
* to be as portable as the JPEG code proper, you should always access JSAMPLE
* values with the GETJSAMPLE() macro, which will do the right thing if the
* machine has only signed chars.
*/
METHODDEF void
put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
/* Write the color map */
{
/* You need not provide this routine if you always set cinfo->quantize_colors
* FALSE; but a safer practice is to provide it and have it just print an
* error message, like this:
*/
fprintf(stderr, "put_color_map called: there's a bug here somewhere!\n");
}
/*
* This function is called repeatedly, with a few more rows of pixels supplied
* on each call. With the current JPEG code, some multiple of 8 rows will be
* passed on each call except the last, but it is extremely bad form to depend
* on this. You CAN assume num_rows > 0.
* The data is supplied in top-to-bottom row order (the standard order within
* a JPEG file). If you cannot readily use the data in that order, you'll
* need an intermediate array to hold the image. See jwrrle.c for an example
* of outputting data in bottom-to-top order.
*
* The data is supplied as a 3-D array of JSAMPLEs, indexed as
* JSAMPLE pixel_data[component][row][column]
* where component runs from 0 to cinfo->final_out_comps-1, row runs from 0 to
* num_rows-1, and column runs from 0 to cinfo->image_width-1 (column 0 is
* left edge of image). Note that this is actually an array of pointers to
* pointers to arrays rather than a true 3D array, since C does not support
* variable-size multidimensional arrays.
* JSAMPLE is typically typedef'd as "unsigned char". If you want your code
* to be as portable as the JPEG code proper, you should always access JSAMPLE
* values with the GETJSAMPLE() macro, which will do the right thing if the
* machine has only signed chars.
*
* If quantize_colors is true, then there is only one component, and its values
* are indexes into the previously supplied colormap. Otherwise the values
* are actual data in your selected output colorspace.
*/
METHODDEF void
put_pixel_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data)
/* Write some rows of output data */
{
/* This example shows how you might write full-color RGB data (3 components)
* to an output file in which the data is stored 3 bytes per pixel.
*/
register FILE * outfile = cinfo->output_file;
register JSAMPROW ptr0, ptr1, ptr2;
register long col;
register int row;
for (row = 0; row < num_rows; row++) {
ptr0 = pixel_data[0][row];
ptr1 = pixel_data[1][row];
ptr2 = pixel_data[2][row];
for (col = 0; col < cinfo->image_width; col++) {
putc(GETJSAMPLE(*ptr0), outfile); /* red */
ptr0++;
putc(GETJSAMPLE(*ptr1), outfile); /* green */
ptr1++;
putc(GETJSAMPLE(*ptr2), outfile); /* blue */
ptr2++;
}
}
}
METHODDEF void
output_term (decompress_info_ptr cinfo)
/* Finish up at the end of the output */
{
/* This termination routine may not need to do anything. */
/* Note that the JPEG code will only call it during successful exit; */
/* if you want it called during error exit, you gotta do that yourself. */
}
/*
* That's it for the routines that deal with writing the output image.
* Now we have overall control and parameter selection routines.
* Just to make this example a little different from the first one, we'll
* assume that we do not intend to put the whole image into an in-memory
* buffer, but to send it line-by-line someplace else. We need a one-
* scanline-high JSAMPLE array as a work buffer, and we will let the JPEG
* memory manager allocate it for us. This approach is actually quite useful
* because we don't need to remember to deallocate the buffer separately: it
* will go away automatically when the JPEG object is cleaned up.
*/
/*
* This routine gets control after the JPEG file header has been read;
* at this point the image size and colorspace are known.
* The routine must determine what output routines are to be used, and make
* any decompression parameter changes that are desirable. For example,
* if it is found that the JPEG file is grayscale, you might want to do
* things differently than if it is color. You can also delay setting
* quantize_colors and associated options until this point.
* ERROR HANDLING:
*
* j_d_defaults initializes out_color_space to CS_RGB. If you want grayscale
* output you should set out_color_space to CS_GRAYSCALE. Note that you can
* force grayscale output from a color JPEG file (though not vice versa).
* The JPEG library's standard error handler (jerror.c) is divided into
* several "methods" which you can override individually. This lets you
* adjust the behavior without duplicating a lot of code, which you might
* have to update with each future release.
*
* Our example here shows how to override the "error_exit" method so that
* control is returned to the library's caller when a fatal error occurs,
* rather than calling exit() as the standard error_exit method does.
*
* We use C's setjmp/longjmp facility to return control. This means that the
* routine which calls the JPEG library must first execute a setjmp() call to
* establish the return point. We want the replacement error_exit to do a
* longjmp(). But we need to make the setjmp buffer accessible to the
* error_exit routine. To do this, we make a private extension of the
* standard JPEG error handler object. (If we were using C++, we'd say we
* were making a subclass of the regular error handler.)
*
* Here's the extended error handler struct:
*/
METHODDEF void
d_ui_method_selection (decompress_info_ptr cinfo)
{
/* if grayscale input, force grayscale output; */
/* else leave the output colorspace as set by main routine. */
if (cinfo->jpeg_color_space == CS_GRAYSCALE)
cinfo->out_color_space = CS_GRAYSCALE;
struct my_error_mgr {
struct jpeg_error_mgr pub; /* "public" fields */
/* select output routines */
cinfo->methods->output_init = output_init;
cinfo->methods->put_color_map = put_color_map;
cinfo->methods->put_pixel_rows = put_pixel_rows;
cinfo->methods->output_term = output_term;
jmp_buf setjmp_buffer; /* for return to caller */
};
typedef struct my_error_mgr * my_error_ptr;
/*
* Here's the routine that will replace the standard error_exit method:
*/
METHODDEF(void)
my_error_exit (j_common_ptr cinfo)
{
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
my_error_ptr myerr = (my_error_ptr) cinfo->err;
/* Always display the message. */
/* We could postpone this until after returning, if we chose. */
(*cinfo->err->output_message) (cinfo);
/* Return control to the setjmp point */
longjmp(myerr->setjmp_buffer, 1);
}
/*
* OK, here is the main function that actually causes everything to happen.
* We assume here that the JPEG filename is supplied by the caller of this
* routine, and that all decompression parameters can be default values.
* The routine returns 1 if successful, 0 if not.
* Sample routine for JPEG decompression. We assume that the source file name
* is passed in. We want to return 1 on success, 0 on error.
*/
GLOBAL int
GLOBAL(int)
read_JPEG_file (char * filename)
{
/* These three structs contain JPEG parameters and working data.
* They must survive for the duration of parameter setup and one
* call to jpeg_decompress; typically, making them local data in the
* calling routine is the best strategy.
/* This struct contains the JPEG decompression parameters and pointers to
* working space (which is allocated as needed by the JPEG library).
*/
struct Decompress_info_struct cinfo;
struct Decompress_methods_struct dc_methods;
struct External_methods_struct e_methods;
struct jpeg_decompress_struct cinfo;
/* We use our private extension JPEG error handler.
* Note that this struct must live as long as the main JPEG parameter
* struct, to avoid dangling-pointer problems.
*/
struct my_error_mgr jerr;
/* More stuff */
FILE * infile; /* source file */
JSAMPARRAY buffer; /* Output row buffer */
int row_stride; /* physical row width in output buffer */
/* Select the input and output files.
* In this example we want to open the input file before doing anything else,
/* In this example we want to open the input file before doing anything else,
* so that the setjmp() error recovery below can assume the file is open.
* Note that cinfo.output_file is only used if your output handling routines
* use it; otherwise, you can just make it NULL.
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
* requires it in order to read binary files.
*/
if ((cinfo.input_file = fopen(filename, "rb")) == NULL) {
if ((infile = fopen(filename, "rb")) == NULL) {
fprintf(stderr, "can't open %s\n", filename);
return 0;
}
cinfo.output_file = NULL; /* if no actual output file involved */
/* Step 1: allocate and initialize JPEG decompression object */
/* Initialize the system-dependent method pointers. */
cinfo.methods = &dc_methods; /* links to method structs */
cinfo.emethods = &e_methods;
/* Here we supply our own error handler; compare to use of standard error
* handler in the previous write_JPEG_file example.
*/
emethods = &e_methods; /* save struct addr for possible access */
e_methods.error_exit = error_exit; /* supply error-exit routine */
e_methods.trace_message = trace_message; /* supply trace-message routine */
e_methods.trace_level = 0; /* default = no tracing */
e_methods.num_warnings = 0; /* no warnings emitted yet */
e_methods.first_warning_level = 0; /* display first corrupt-data warning */
e_methods.more_warning_level = 3; /* but suppress additional ones */
/* prepare setjmp context for possible exit from error_exit */
if (setjmp(setjmp_buffer)) {
/* We set up the normal JPEG error routines, then override error_exit. */
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
/* Establish the setjmp return context for my_error_exit to use. */
if (setjmp(jerr.setjmp_buffer)) {
/* If we get here, the JPEG code has signaled an error.
* Memory allocation has already been cleaned up (see free_all call in
* error_exit), but we need to close the input file before returning.
* You might also need to close an output file, etc.
* We need to clean up the JPEG object, close the input file, and return.
*/
fclose(cinfo.input_file);
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return 0;
}
/* Now we can initialize the JPEG decompression object. */
jpeg_create_decompress(&cinfo);
/* Here we use the standard memory manager provided with the JPEG code.
* In some cases you might want to replace the memory manager, or at
* least the system-dependent part of it, with your own code.
*/
jselmemmgr(&e_methods); /* select std memory allocation routines */
/* If the decompressor requires full-image buffers (for two-pass color
* quantization or a noninterleaved JPEG file), it will create temporary
* files for anything that doesn't fit within the maximum-memory setting.
* You can change the default maximum-memory setting by changing
* e_methods.max_memory_to_use after jselmemmgr returns.
* On some systems you may also need to set up a signal handler to
* ensure that temporary files are deleted if the program is interrupted.
* (This is most important if you are on MS-DOS and use the jmemdos.c
* memory manager back end; it will try to grab extended memory for
* temp files, and that space will NOT be freed automatically.)
* See jcmain.c or jdmain.c for an example signal handler.
/* Step 2: specify data source (eg, a file) */
jpeg_stdio_src(&cinfo, infile);
/* Step 3: read file parameters with jpeg_read_header() */
(void) jpeg_read_header(&cinfo, TRUE);
/* We can ignore the return value from jpeg_read_header since
* (a) suspension is not possible with the stdio data source, and
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
* See libjpeg.doc for more info.
*/
/* Here, set up the pointer to your own routine for post-header-reading
* parameter selection. You could also initialize the pointers to the
* output data handling routines here, if they are not dependent on the
* image type.
*/
dc_methods.d_ui_method_selection = d_ui_method_selection;
/* Step 4: set parameters for decompression */
/* Set up default decompression parameters. */
j_d_defaults(&cinfo, TRUE);
/* TRUE indicates that an input buffer should be allocated.
* In unusual cases you may want to allocate the input buffer yourself;
* see jddeflts.c for commentary.
/* In this example, we don't need to change any of the defaults set by
* jpeg_read_header(), so we do nothing here.
*/
/* At this point you can modify the default parameters set by j_d_defaults
* as needed; for example, you can request color quantization or force
* grayscale output. See jdmain.c for examples of what you might change.
/* Step 5: Start decompressor */
(void) jpeg_start_decompress(&cinfo);
/* We can ignore the return value since suspension is not possible
* with the stdio data source.
*/
/* Set up to read a JFIF or baseline-JPEG file. */
/* This is the only JPEG file format currently supported. */
jselrjfif(&cinfo);
/* Here we go! */
jpeg_decompress(&cinfo);
/* That's it, son. Nothin' else to do, except close files. */
/* Here we assume only the input file need be closed. */
fclose(cinfo.input_file);
/* You might want to test e_methods.num_warnings to see if bad data was
* detected. In this example, we just blindly forge ahead.
/* We may need to do some setup of our own at this point before reading
* the data. After jpeg_start_decompress() we have the correct scaled
* output image dimensions available, as well as the output colormap
* if we asked for color quantization.
* In this example, we need to make an output work buffer of the right size.
*/
return 1; /* indicate success */
/* JSAMPLEs per row in output buffer */
row_stride = cinfo.output_width * cinfo.output_components;
/* Make a one-row-high sample array that will go away when done with image */
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
/* Note: if you want to decompress more than one image, we recommend you
* repeat this whole routine. You MUST repeat the j_d_defaults()/alter
* parameters/jpeg_decompress() sequence, as some data structures allocated
* in j_d_defaults are freed upon exit from jpeg_decompress.
/* Step 6: while (scan lines remain to be read) */
/* jpeg_read_scanlines(...); */
/* Here we use the library's state variable cinfo.output_scanline as the
* loop counter, so that we don't have to keep track ourselves.
*/
while (cinfo.output_scanline < cinfo.output_height) {
/* jpeg_read_scanlines expects an array of pointers to scanlines.
* Here the array is only one element long, but you could ask for
* more than one scanline at a time if that's more convenient.
*/
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
/* Assume put_scanline_someplace wants a pointer and sample count. */
put_scanline_someplace(buffer[0], row_stride);
}
/* Step 7: Finish decompression */
(void) jpeg_finish_decompress(&cinfo);
/* We can ignore the return value since suspension is not possible
* with the stdio data source.
*/
/* Step 8: Release JPEG decompression object */
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_decompress(&cinfo);
/* After finish_decompress, we can close the input file.
* Here we postpone it until after no more JPEG errors are possible,
* so as to simplify the setjmp error logic above. (Actually, I don't
* think that jpeg_destroy can do an error exit, but why assume anything...)
*/
fclose(infile);
/* At this point you may want to check to see whether any corrupt-data
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
*/
/* And we're done! */
return 1;
}
/*
* SOME FINE POINTS:
*
* In the above code, we ignored the return value of jpeg_read_scanlines,
* which is the number of scanlines actually read. We could get away with
* this because we asked for only one line at a time and we weren't using
* a suspending data source. See libjpeg.doc for more info.
*
* We cheated a bit by calling alloc_sarray() after jpeg_start_decompress();
* we should have done it beforehand to ensure that the space would be
* counted against the JPEG max_memory setting. In some systems the above
* code would risk an out-of-memory error. However, in general we don't
* know the output image dimensions before jpeg_start_decompress(), unless we
* call jpeg_calc_output_dimensions(). See libjpeg.doc for more about this.
*
* Scanlines are returned in the same order as they appear in the JPEG file,
* which is standardly top-to-bottom. If you must emit data bottom-to-top,
* you can use one of the virtual arrays provided by the JPEG memory manager
* to invert the data. See wrbmp.c for an example.
*
* As with compression, some operating modes may require temporary files.
* On some systems you may need to set up a signal handler to ensure that
* temporary files are deleted if the program is interrupted. See libjpeg.doc.
*/

210
filelist.doc Normal file
View File

@@ -0,0 +1,210 @@
IJG JPEG LIBRARY: FILE LIST
Copyright (C) 1994-1998, Thomas G. Lane.
This file is part of the Independent JPEG Group's software.
For conditions of distribution and use, see the accompanying README file.
Here is a road map to the files in the IJG JPEG distribution. The
distribution includes the JPEG library proper, plus two application
programs ("cjpeg" and "djpeg") which use the library to convert JPEG
files to and from some other popular image formats. A third application
"jpegtran" uses the library to do lossless conversion between different
variants of JPEG. There are also two stand-alone applications,
"rdjpgcom" and "wrjpgcom".
THE JPEG LIBRARY
================
Include files:
jpeglib.h JPEG library's exported data and function declarations.
jconfig.h Configuration declarations. Note: this file is not present
in the distribution; it is generated during installation.
jmorecfg.h Additional configuration declarations; need not be changed
for a standard installation.
jerror.h Declares JPEG library's error and trace message codes.
jinclude.h Central include file used by all IJG .c files to reference
system include files.
jpegint.h JPEG library's internal data structures.
jchuff.h Private declarations for Huffman encoder modules.
jdhuff.h Private declarations for Huffman decoder modules.
jdct.h Private declarations for forward & reverse DCT subsystems.
jmemsys.h Private declarations for memory management subsystem.
jversion.h Version information.
Applications using the library should include jpeglib.h (which in turn
includes jconfig.h and jmorecfg.h). Optionally, jerror.h may be included
if the application needs to reference individual JPEG error codes. The
other include files are intended for internal use and would not normally
be included by an application program. (cjpeg/djpeg/etc do use jinclude.h,
since its function is to improve portability of the whole IJG distribution.
Most other applications will directly include the system include files they
want, and hence won't need jinclude.h.)
C source code files:
These files contain most of the functions intended to be called directly by
an application program:
jcapimin.c Application program interface: core routines for compression.
jcapistd.c Application program interface: standard compression.
jdapimin.c Application program interface: core routines for decompression.
jdapistd.c Application program interface: standard decompression.
jcomapi.c Application program interface routines common to compression
and decompression.
jcparam.c Compression parameter setting helper routines.
jctrans.c API and library routines for transcoding compression.
jdtrans.c API and library routines for transcoding decompression.
Compression side of the library:
jcinit.c Initialization: determines which other modules to use.
jcmaster.c Master control: setup and inter-pass sequencing logic.
jcmainct.c Main buffer controller (preprocessor => JPEG compressor).
jcprepct.c Preprocessor buffer controller.
jccoefct.c Buffer controller for DCT coefficient buffer.
jccolor.c Color space conversion.
jcsample.c Downsampling.
jcdctmgr.c DCT manager (DCT implementation selection & control).
jfdctint.c Forward DCT using slow-but-accurate integer method.
jfdctfst.c Forward DCT using faster, less accurate integer method.
jfdctflt.c Forward DCT using floating-point arithmetic.
jchuff.c Huffman entropy coding for sequential JPEG.
jcphuff.c Huffman entropy coding for progressive JPEG.
jcmarker.c JPEG marker writing.
jdatadst.c Data destination manager for stdio output.
Decompression side of the library:
jdmaster.c Master control: determines which other modules to use.
jdinput.c Input controller: controls input processing modules.
jdmainct.c Main buffer controller (JPEG decompressor => postprocessor).
jdcoefct.c Buffer controller for DCT coefficient buffer.
jdpostct.c Postprocessor buffer controller.
jdmarker.c JPEG marker reading.
jdhuff.c Huffman entropy decoding for sequential JPEG.
jdphuff.c Huffman entropy decoding for progressive JPEG.
jddctmgr.c IDCT manager (IDCT implementation selection & control).
jidctint.c Inverse DCT using slow-but-accurate integer method.
jidctfst.c Inverse DCT using faster, less accurate integer method.
jidctflt.c Inverse DCT using floating-point arithmetic.
jidctred.c Inverse DCTs with reduced-size outputs.
jdsample.c Upsampling.
jdcolor.c Color space conversion.
jdmerge.c Merged upsampling/color conversion (faster, lower quality).
jquant1.c One-pass color quantization using a fixed-spacing colormap.
jquant2.c Two-pass color quantization using a custom-generated colormap.
Also handles one-pass quantization to an externally given map.
jdatasrc.c Data source manager for stdio input.
Support files for both compression and decompression:
jerror.c Standard error handling routines (application replaceable).
jmemmgr.c System-independent (more or less) memory management code.
jutils.c Miscellaneous utility routines.
jmemmgr.c relies on a system-dependent memory management module. The IJG
distribution includes the following implementations of the system-dependent
module:
jmemnobs.c "No backing store": assumes adequate virtual memory exists.
jmemansi.c Makes temporary files with ANSI-standard routine tmpfile().
jmemname.c Makes temporary files with program-generated file names.
jmemdos.c Custom implementation for MS-DOS (16-bit environment only):
can use extended and expanded memory as well as temp files.
jmemmac.c Custom implementation for Apple Macintosh.
Exactly one of the system-dependent modules should be configured into an
installed JPEG library (see install.doc for hints about which one to use).
On unusual systems you may find it worthwhile to make a special
system-dependent memory manager.
Non-C source code files:
jmemdosa.asm 80x86 assembly code support for jmemdos.c; used only in
MS-DOS-specific configurations of the JPEG library.
CJPEG/DJPEG/JPEGTRAN
====================
Include files:
cdjpeg.h Declarations shared by cjpeg/djpeg/jpegtran modules.
cderror.h Additional error and trace message codes for cjpeg et al.
transupp.h Declarations for jpegtran support routines in transupp.c.
C source code files:
cjpeg.c Main program for cjpeg.
djpeg.c Main program for djpeg.
jpegtran.c Main program for jpegtran.
cdjpeg.c Utility routines used by all three programs.
rdcolmap.c Code to read a colormap file for djpeg's "-map" switch.
rdswitch.c Code to process some of cjpeg's more complex switches.
Also used by jpegtran.
transupp.c Support code for jpegtran: lossless image manipulations.
Image file reader modules for cjpeg:
rdbmp.c BMP file input.
rdgif.c GIF file input (now just a stub).
rdppm.c PPM/PGM file input.
rdrle.c Utah RLE file input.
rdtarga.c Targa file input.
Image file writer modules for djpeg:
wrbmp.c BMP file output.
wrgif.c GIF file output (a mere shadow of its former self).
wrppm.c PPM/PGM file output.
wrrle.c Utah RLE file output.
wrtarga.c Targa file output.
RDJPGCOM/WRJPGCOM
=================
C source code files:
rdjpgcom.c Stand-alone rdjpgcom application.
wrjpgcom.c Stand-alone wrjpgcom application.
These programs do not depend on the IJG library. They do use
jconfig.h and jinclude.h, only to improve portability.
ADDITIONAL FILES
================
Documentation (see README for a guide to the documentation files):
README Master documentation file.
*.doc Other documentation files.
*.1 Documentation in Unix man page format.
change.log Version-to-version change highlights.
example.c Sample code for calling JPEG library.
Configuration/installation files and programs (see install.doc for more info):
configure Unix shell script to perform automatic configuration.
ltconfig Support scripts for configure (from GNU libtool).
ltmain.sh
config.guess
config.sub
install-sh Install shell script for those Unix systems lacking one.
ckconfig.c Program to generate jconfig.h on non-Unix systems.
jconfig.doc Template for making jconfig.h by hand.
makefile.* Sample makefiles for particular systems.
jconfig.* Sample jconfig.h for particular systems.
ansi2knr.c De-ANSIfier for pre-ANSI C compilers (courtesy of
L. Peter Deutsch and Aladdin Enterprises).
Test files (see install.doc for test procedure):
test*.* Source and comparison files for confidence test.
These are binary image files, NOT text files.

1063
install.doc Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,118 +0,0 @@
/*
* jbsmooth.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains cross-block smoothing routines.
* These routines are invoked via the smooth_coefficients method.
*/
#include "jinclude.h"
#ifdef BLOCK_SMOOTHING_SUPPORTED
/*
* Cross-block coefficient smoothing.
*/
METHODDEF void
smooth_coefficients (decompress_info_ptr cinfo,
jpeg_component_info *compptr,
JBLOCKROW above,
JBLOCKROW currow,
JBLOCKROW below,
JBLOCKROW output)
{
QUANT_TBL_PTR Qptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
long blocks_in_row = compptr->downsampled_width / DCTSIZE;
long col;
/* First, copy the block row as-is.
* This takes care of the first & last blocks in the row, the top/bottom
* special cases, and the higher-order coefficients in each block.
*/
jcopy_block_row(currow, output, blocks_in_row);
/* Now apply the smoothing calculation, but not to any blocks on the
* edges of the image.
*/
if (above != NULL && below != NULL) {
for (col = 1; col < blocks_in_row-1; col++) {
/* See section K.8 of the JPEG standard.
*
* As I understand it, this produces approximations
* for the low frequency AC components, based on the
* DC values of the block and its eight neighboring blocks.
* (Thus it can't be used for blocks on the image edges.)
*/
/* The layout of these variables corresponds to text and figure in K.8 */
JCOEF DC1, DC2, DC3;
JCOEF DC4, DC5, DC6;
JCOEF DC7, DC8, DC9;
long AC01, AC02;
long AC10, AC11;
long AC20;
DC1 = above [col-1][0];
DC2 = above [col ][0];
DC3 = above [col+1][0];
DC4 = currow[col-1][0];
DC5 = currow[col ][0];
DC6 = currow[col+1][0];
DC7 = below [col-1][0];
DC8 = below [col ][0];
DC9 = below [col+1][0];
#define DIVIDE_256(x) x = ( (x) < 0 ? -((128-(x))/256) : ((x)+128)/256 )
AC01 = (36 * (DC4 - DC6));
DIVIDE_256(AC01);
AC10 = (36 * (DC2 - DC8));
DIVIDE_256(AC10);
AC20 = (9 * (DC2 + DC8 - 2*DC5));
DIVIDE_256(AC20);
AC11 = (5 * ((DC1 - DC3) - (DC7 - DC9)));
DIVIDE_256(AC11);
AC02 = (9 * (DC4 + DC6 - 2*DC5));
DIVIDE_256(AC02);
/* I think that this checks to see if the quantisation
* on the transmitting side would have produced this
* answer. If so, then we use our (hopefully better)
* estimate.
*/
#define ABS(x) ((x) < 0 ? -(x) : (x))
#define COND_ASSIGN(_ac,_n,_z) if ((ABS(output[col][_n] - (_ac))<<1) <= Qptr[_z]) output[col][_n] = (JCOEF) (_ac)
COND_ASSIGN(AC01, 1, 1);
COND_ASSIGN(AC02, 2, 5);
COND_ASSIGN(AC10, 8, 2);
COND_ASSIGN(AC11, 9, 4);
COND_ASSIGN(AC20, 16, 3);
}
}
}
/*
* The method selection routine for cross-block smoothing.
*/
GLOBAL void
jselbsmooth (decompress_info_ptr cinfo)
{
/* just one implementation for now */
cinfo->methods->smooth_coefficients = smooth_coefficients;
}
#endif /* BLOCK_SMOOTHING_SUPPORTED */

280
jcapimin.c Normal file
View File

@@ -0,0 +1,280 @@
/*
* jcapimin.c
*
* Copyright (C) 1994-1998, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains application interface code for the compression half
* of the JPEG library. These are the "minimum" API routines that may be
* needed in either the normal full-compression case or the transcoding-only
* case.
*
* Most of the routines intended to be called directly by an application
* are in this file or in jcapistd.c. But also see jcparam.c for
* parameter-setup helper routines, jcomapi.c for routines shared by
* compression and decompression, and jctrans.c for the transcoding case.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* Initialization of a JPEG compression object.
* The error manager must already be set up (in case memory manager fails).
*/
GLOBAL(void)
jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize)
{
int i;
/* Guard against version mismatches between library and caller. */
cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
if (version != JPEG_LIB_VERSION)
ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
if (structsize != SIZEOF(struct jpeg_compress_struct))
ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
(int) SIZEOF(struct jpeg_compress_struct), (int) structsize);
/* For debugging purposes, we zero the whole master structure.
* But the application has already set the err pointer, and may have set
* client_data, so we have to save and restore those fields.
* Note: if application hasn't set client_data, tools like Purify may
* complain here.
*/
{
struct jpeg_error_mgr * err = cinfo->err;
void * client_data = cinfo->client_data; /* ignore Purify complaint here */
MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct));
cinfo->err = err;
cinfo->client_data = client_data;
}
cinfo->is_decompressor = FALSE;
/* Initialize a memory manager instance for this object */
jinit_memory_mgr((j_common_ptr) cinfo);
/* Zero out pointers to permanent structures. */
cinfo->progress = NULL;
cinfo->dest = NULL;
cinfo->comp_info = NULL;
for (i = 0; i < NUM_QUANT_TBLS; i++)
cinfo->quant_tbl_ptrs[i] = NULL;
for (i = 0; i < NUM_HUFF_TBLS; i++) {
cinfo->dc_huff_tbl_ptrs[i] = NULL;
cinfo->ac_huff_tbl_ptrs[i] = NULL;
}
cinfo->script_space = NULL;
cinfo->input_gamma = 1.0; /* in case application forgets */
/* OK, I'm ready */
cinfo->global_state = CSTATE_START;
}
/*
* Destruction of a JPEG compression object
*/
GLOBAL(void)
jpeg_destroy_compress (j_compress_ptr cinfo)
{
jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
}
/*
* Abort processing of a JPEG compression operation,
* but don't destroy the object itself.
*/
GLOBAL(void)
jpeg_abort_compress (j_compress_ptr cinfo)
{
jpeg_abort((j_common_ptr) cinfo); /* use common routine */
}
/*
* Forcibly suppress or un-suppress all quantization and Huffman tables.
* Marks all currently defined tables as already written (if suppress)
* or not written (if !suppress). This will control whether they get emitted
* by a subsequent jpeg_start_compress call.
*
* This routine is exported for use by applications that want to produce
* abbreviated JPEG datastreams. It logically belongs in jcparam.c, but
* since it is called by jpeg_start_compress, we put it here --- otherwise
* jcparam.o would be linked whether the application used it or not.
*/
GLOBAL(void)
jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress)
{
int i;
JQUANT_TBL * qtbl;
JHUFF_TBL * htbl;
for (i = 0; i < NUM_QUANT_TBLS; i++) {
if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL)
qtbl->sent_table = suppress;
}
for (i = 0; i < NUM_HUFF_TBLS; i++) {
if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL)
htbl->sent_table = suppress;
if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL)
htbl->sent_table = suppress;
}
}
/*
* Finish JPEG compression.
*
* If a multipass operating mode was selected, this may do a great deal of
* work including most of the actual output.
*/
GLOBAL(void)
jpeg_finish_compress (j_compress_ptr cinfo)
{
JDIMENSION iMCU_row;
if (cinfo->global_state == CSTATE_SCANNING ||
cinfo->global_state == CSTATE_RAW_OK) {
/* Terminate first pass */
if (cinfo->next_scanline < cinfo->image_height)
ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
(*cinfo->master->finish_pass) (cinfo);
} else if (cinfo->global_state != CSTATE_WRCOEFS)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* Perform any remaining passes */
while (! cinfo->master->is_last_pass) {
(*cinfo->master->prepare_for_pass) (cinfo);
for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) {
if (cinfo->progress != NULL) {
cinfo->progress->pass_counter = (long) iMCU_row;
cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows;
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
}
/* We bypass the main controller and invoke coef controller directly;
* all work is being done from the coefficient buffer.
*/
if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
}
(*cinfo->master->finish_pass) (cinfo);
}
/* Write EOI, do final cleanup */
(*cinfo->marker->write_file_trailer) (cinfo);
(*cinfo->dest->term_destination) (cinfo);
/* We can use jpeg_abort to release memory and reset global_state */
jpeg_abort((j_common_ptr) cinfo);
}
/*
* Write a special marker.
* This is only recommended for writing COM or APPn markers.
* Must be called after jpeg_start_compress() and before
* first call to jpeg_write_scanlines() or jpeg_write_raw_data().
*/
GLOBAL(void)
jpeg_write_marker (j_compress_ptr cinfo, int marker,
const JOCTET *dataptr, unsigned int datalen)
{
JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val));
if (cinfo->next_scanline != 0 ||
(cinfo->global_state != CSTATE_SCANNING &&
cinfo->global_state != CSTATE_RAW_OK &&
cinfo->global_state != CSTATE_WRCOEFS))
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
(*cinfo->marker->write_marker_header) (cinfo, marker, datalen);
write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */
while (datalen--) {
(*write_marker_byte) (cinfo, *dataptr);
dataptr++;
}
}
/* Same, but piecemeal. */
GLOBAL(void)
jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
{
if (cinfo->next_scanline != 0 ||
(cinfo->global_state != CSTATE_SCANNING &&
cinfo->global_state != CSTATE_RAW_OK &&
cinfo->global_state != CSTATE_WRCOEFS))
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
(*cinfo->marker->write_marker_header) (cinfo, marker, datalen);
}
GLOBAL(void)
jpeg_write_m_byte (j_compress_ptr cinfo, int val)
{
(*cinfo->marker->write_marker_byte) (cinfo, val);
}
/*
* Alternate compression function: just write an abbreviated table file.
* Before calling this, all parameters and a data destination must be set up.
*
* To produce a pair of files containing abbreviated tables and abbreviated
* image data, one would proceed as follows:
*
* initialize JPEG object
* set JPEG parameters
* set destination to table file
* jpeg_write_tables(cinfo);
* set destination to image file
* jpeg_start_compress(cinfo, FALSE);
* write data...
* jpeg_finish_compress(cinfo);
*
* jpeg_write_tables has the side effect of marking all tables written
* (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress
* will not re-emit the tables unless it is passed write_all_tables=TRUE.
*/
GLOBAL(void)
jpeg_write_tables (j_compress_ptr cinfo)
{
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* (Re)initialize error mgr and destination modules */
(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
(*cinfo->dest->init_destination) (cinfo);
/* Initialize the marker writer ... bit of a crock to do it here. */
jinit_marker_writer(cinfo);
/* Write them tables! */
(*cinfo->marker->write_tables_only) (cinfo);
/* And clean up. */
(*cinfo->dest->term_destination) (cinfo);
/*
* In library releases up through v6a, we called jpeg_abort() here to free
* any working memory allocated by the destination manager and marker
* writer. Some applications had a problem with that: they allocated space
* of their own from the library memory manager, and didn't want it to go
* away during write_tables. So now we do nothing. This will cause a
* memory leak if an app calls write_tables repeatedly without doing a full
* compression cycle or otherwise resetting the JPEG object. However, that
* seems less bad than unexpectedly freeing memory in the normal case.
* An app that prefers the old behavior can call jpeg_abort for itself after
* each call to jpeg_write_tables().
*/
}

161
jcapistd.c Normal file
View File

@@ -0,0 +1,161 @@
/*
* jcapistd.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains application interface code for the compression half
* of the JPEG library. These are the "standard" API routines that are
* used in the normal full-compression case. They are not used by a
* transcoding-only application. Note that if an application links in
* jpeg_start_compress, it will end up linking in the entire compressor.
* We thus must separate this file from jcapimin.c to avoid linking the
* whole compression library into a transcoder.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* Compression initialization.
* Before calling this, all parameters and a data destination must be set up.
*
* We require a write_all_tables parameter as a failsafe check when writing
* multiple datastreams from the same compression object. Since prior runs
* will have left all the tables marked sent_table=TRUE, a subsequent run
* would emit an abbreviated stream (no tables) by default. This may be what
* is wanted, but for safety's sake it should not be the default behavior:
* programmers should have to make a deliberate choice to emit abbreviated
* images. Therefore the documentation and examples should encourage people
* to pass write_all_tables=TRUE; then it will take active thought to do the
* wrong thing.
*/
GLOBAL(void)
jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables)
{
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (write_all_tables)
jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */
/* (Re)initialize error mgr and destination modules */
(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
(*cinfo->dest->init_destination) (cinfo);
/* Perform master selection of active modules */
jinit_compress_master(cinfo);
/* Set up for the first pass */
(*cinfo->master->prepare_for_pass) (cinfo);
/* Ready for application to drive first pass through jpeg_write_scanlines
* or jpeg_write_raw_data.
*/
cinfo->next_scanline = 0;
cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING);
}
/*
* Write some scanlines of data to the JPEG compressor.
*
* The return value will be the number of lines actually written.
* This should be less than the supplied num_lines only in case that
* the data destination module has requested suspension of the compressor,
* or if more than image_height scanlines are passed in.
*
* Note: we warn about excess calls to jpeg_write_scanlines() since
* this likely signals an application programmer error. However,
* excess scanlines passed in the last valid call are *silently* ignored,
* so that the application need not adjust num_lines for end-of-image
* when using a multiple-scanline buffer.
*/
GLOBAL(JDIMENSION)
jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines,
JDIMENSION num_lines)
{
JDIMENSION row_ctr, rows_left;
if (cinfo->global_state != CSTATE_SCANNING)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (cinfo->next_scanline >= cinfo->image_height)
WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
cinfo->progress->pass_counter = (long) cinfo->next_scanline;
cinfo->progress->pass_limit = (long) cinfo->image_height;
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
}
/* Give master control module another chance if this is first call to
* jpeg_write_scanlines. This lets output of the frame/scan headers be
* delayed so that application can write COM, etc, markers between
* jpeg_start_compress and jpeg_write_scanlines.
*/
if (cinfo->master->call_pass_startup)
(*cinfo->master->pass_startup) (cinfo);
/* Ignore any extra scanlines at bottom of image. */
rows_left = cinfo->image_height - cinfo->next_scanline;
if (num_lines > rows_left)
num_lines = rows_left;
row_ctr = 0;
(*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines);
cinfo->next_scanline += row_ctr;
return row_ctr;
}
/*
* Alternate entry point to write raw data.
* Processes exactly one iMCU row per call, unless suspended.
*/
GLOBAL(JDIMENSION)
jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
JDIMENSION num_lines)
{
JDIMENSION lines_per_iMCU_row;
if (cinfo->global_state != CSTATE_RAW_OK)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (cinfo->next_scanline >= cinfo->image_height) {
WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
return 0;
}
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
cinfo->progress->pass_counter = (long) cinfo->next_scanline;
cinfo->progress->pass_limit = (long) cinfo->image_height;
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
}
/* Give master control module another chance if this is first call to
* jpeg_write_raw_data. This lets output of the frame/scan headers be
* delayed so that application can write COM, etc, markers between
* jpeg_start_compress and jpeg_write_raw_data.
*/
if (cinfo->master->call_pass_startup)
(*cinfo->master->pass_startup) (cinfo);
/* Verify that at least one iMCU row has been passed. */
lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE;
if (num_lines < lines_per_iMCU_row)
ERREXIT(cinfo, JERR_BUFFER_SIZE);
/* Directly compress the row. */
if (! (*cinfo->coef->compress_data) (cinfo, data)) {
/* If compressor did not consume the whole row, suspend processing. */
return 0;
}
/* OK, we processed one iMCU row. */
cinfo->next_scanline += lines_per_iMCU_row;
return lines_per_iMCU_row;
}

View File

@@ -1,42 +0,0 @@
/*
* jcarith.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains arithmetic entropy encoding routines.
* These routines are invoked via the methods entropy_encode,
* entropy_encode_init/term, and entropy_optimize.
*/
#include "jinclude.h"
#ifdef C_ARITH_CODING_SUPPORTED
/*
* The arithmetic coding option of the JPEG standard specifies Q-coding,
* which is covered by patents held by IBM (and possibly AT&T and Mitsubishi).
* At this time it does not appear to be legal for the Independent JPEG
* Group to distribute software that implements arithmetic coding.
* We have therefore removed arithmetic coding support from the
* distributed source code.
*
* We're not happy about it either.
*/
/*
* The method selection routine for arithmetic entropy encoding.
*/
GLOBAL void
jselcarithmetic (compress_info_ptr cinfo)
{
if (cinfo->arith_code) {
ERREXIT(cinfo->emethods, "Sorry, there are legal restrictions on arithmetic coding");
}
}
#endif /* C_ARITH_CODING_SUPPORTED */

449
jccoefct.c Normal file
View File

@@ -0,0 +1,449 @@
/*
* jccoefct.c
*
* Copyright (C) 1994-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the coefficient buffer controller for compression.
* This controller is the top level of the JPEG compressor proper.
* The coefficient buffer lies between forward-DCT and entropy encoding steps.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* We use a full-image coefficient buffer when doing Huffman optimization,
* and also for writing multiple-scan JPEG files. In all cases, the DCT
* step is run during the first pass, and subsequent passes need only read
* the buffered coefficients.
*/
#ifdef ENTROPY_OPT_SUPPORTED
#define FULL_COEF_BUFFER_SUPPORTED
#else
#ifdef C_MULTISCAN_FILES_SUPPORTED
#define FULL_COEF_BUFFER_SUPPORTED
#endif
#endif
/* Private buffer controller object */
typedef struct {
struct jpeg_c_coef_controller pub; /* public fields */
JDIMENSION iMCU_row_num; /* iMCU row # within image */
JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
int MCU_vert_offset; /* counts MCU rows within iMCU row */
int MCU_rows_per_iMCU_row; /* number of such rows needed */
/* For single-pass compression, it's sufficient to buffer just one MCU
* (although this may prove a bit slow in practice). We allocate a
* workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each
* MCU constructed and sent. (On 80x86, the workspace is FAR even though
* it's not really very big; this is to keep the module interfaces unchanged
* when a large coefficient buffer is necessary.)
* In multi-pass modes, this array points to the current MCU's blocks
* within the virtual arrays.
*/
JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
/* In multi-pass modes, we need a virtual block array for each component. */
jvirt_barray_ptr whole_image[MAX_COMPONENTS];
} my_coef_controller;
typedef my_coef_controller * my_coef_ptr;
/* Forward declarations */
METHODDEF(boolean) compress_data
JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
#ifdef FULL_COEF_BUFFER_SUPPORTED
METHODDEF(boolean) compress_first_pass
JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
METHODDEF(boolean) compress_output
JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
#endif
LOCAL(void)
start_iMCU_row (j_compress_ptr cinfo)
/* Reset within-iMCU-row counters for a new row */
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
/* In an interleaved scan, an MCU row is the same as an iMCU row.
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
* But at the bottom of the image, process only what's left.
*/
if (cinfo->comps_in_scan > 1) {
coef->MCU_rows_per_iMCU_row = 1;
} else {
if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
else
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
}
coef->mcu_ctr = 0;
coef->MCU_vert_offset = 0;
}
/*
* Initialize for a processing pass.
*/
METHODDEF(void)
start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
coef->iMCU_row_num = 0;
start_iMCU_row(cinfo);
switch (pass_mode) {
case JBUF_PASS_THRU:
if (coef->whole_image[0] != NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
coef->pub.compress_data = compress_data;
break;
#ifdef FULL_COEF_BUFFER_SUPPORTED
case JBUF_SAVE_AND_PASS:
if (coef->whole_image[0] == NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
coef->pub.compress_data = compress_first_pass;
break;
case JBUF_CRANK_DEST:
if (coef->whole_image[0] == NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
coef->pub.compress_data = compress_output;
break;
#endif
default:
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
break;
}
}
/*
* Process some data in the single-pass case.
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
* per call, ie, v_samp_factor block rows for each component in the image.
* Returns TRUE if the iMCU row is completed, FALSE if suspended.
*
* NB: input_buf contains a plane for each component in image,
* which we index according to the component's SOF position.
*/
METHODDEF(boolean)
compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
int blkn, bi, ci, yindex, yoffset, blockcnt;
JDIMENSION ypos, xpos;
jpeg_component_info *compptr;
/* Loop to write as much as one whole iMCU row */
for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
yoffset++) {
for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col;
MCU_col_num++) {
/* Determine where data comes from in input_buf and do the DCT thing.
* Each call on forward_DCT processes a horizontal row of DCT blocks
* as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks
* sequentially. Dummy blocks at the right or bottom edge are filled in
* specially. The data in them does not matter for image reconstruction,
* so we fill them with values that will encode to the smallest amount of
* data, viz: all zeroes in the AC entries, DC entries equal to previous
* block's DC value. (Thanks to Thomas Kinsman for this idea.)
*/
blkn = 0;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
: compptr->last_col_width;
xpos = MCU_col_num * compptr->MCU_sample_width;
ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
if (coef->iMCU_row_num < last_iMCU_row ||
yoffset+yindex < compptr->last_row_height) {
(*cinfo->fdct->forward_DCT) (cinfo, compptr,
input_buf[compptr->component_index],
coef->MCU_buffer[blkn],
ypos, xpos, (JDIMENSION) blockcnt);
if (blockcnt < compptr->MCU_width) {
/* Create some dummy blocks at the right edge of the image. */
jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt],
(compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK));
for (bi = blockcnt; bi < compptr->MCU_width; bi++) {
coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0];
}
}
} else {
/* Create a row of dummy blocks at the bottom of the image. */
jzero_far((void FAR *) coef->MCU_buffer[blkn],
compptr->MCU_width * SIZEOF(JBLOCK));
for (bi = 0; bi < compptr->MCU_width; bi++) {
coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0];
}
}
blkn += compptr->MCU_width;
ypos += DCTSIZE;
}
}
/* Try to write the MCU. In event of a suspension failure, we will
* re-DCT the MCU on restart (a bit inefficient, could be fixed...)
*/
if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->mcu_ctr = MCU_col_num;
return FALSE;
}
}
/* Completed an MCU row, but perhaps not an iMCU row */
coef->mcu_ctr = 0;
}
/* Completed the iMCU row, advance counters for next one */
coef->iMCU_row_num++;
start_iMCU_row(cinfo);
return TRUE;
}
#ifdef FULL_COEF_BUFFER_SUPPORTED
/*
* Process some data in the first pass of a multi-pass case.
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
* per call, ie, v_samp_factor block rows for each component in the image.
* This amount of data is read from the source buffer, DCT'd and quantized,
* and saved into the virtual arrays. We also generate suitable dummy blocks
* as needed at the right and lower edges. (The dummy blocks are constructed
* in the virtual arrays, which have been padded appropriately.) This makes
* it possible for subsequent passes not to worry about real vs. dummy blocks.
*
* We must also emit the data to the entropy encoder. This is conveniently
* done by calling compress_output() after we've loaded the current strip
* of the virtual arrays.
*
* NB: input_buf contains a plane for each component in image. All
* components are DCT'd and loaded into the virtual arrays in this pass.
* However, it may be that only a subset of the components are emitted to
* the entropy encoder during this first pass; be careful about looking
* at the scan-dependent variables (MCU dimensions, etc).
*/
METHODDEF(boolean)
compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
JDIMENSION blocks_across, MCUs_across, MCUindex;
int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
JCOEF lastDC;
jpeg_component_info *compptr;
JBLOCKARRAY buffer;
JBLOCKROW thisblockrow, lastblockrow;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Align the virtual buffer for this component. */
buffer = (*cinfo->mem->access_virt_barray)
((j_common_ptr) cinfo, coef->whole_image[ci],
coef->iMCU_row_num * compptr->v_samp_factor,
(JDIMENSION) compptr->v_samp_factor, TRUE);
/* Count non-dummy DCT block rows in this iMCU row. */
if (coef->iMCU_row_num < last_iMCU_row)
block_rows = compptr->v_samp_factor;
else {
/* NB: can't use last_row_height here, since may not be set! */
block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
if (block_rows == 0) block_rows = compptr->v_samp_factor;
}
blocks_across = compptr->width_in_blocks;
h_samp_factor = compptr->h_samp_factor;
/* Count number of dummy blocks to be added at the right margin. */
ndummy = (int) (blocks_across % h_samp_factor);
if (ndummy > 0)
ndummy = h_samp_factor - ndummy;
/* Perform DCT for all non-dummy blocks in this iMCU row. Each call
* on forward_DCT processes a complete horizontal row of DCT blocks.
*/
for (block_row = 0; block_row < block_rows; block_row++) {
thisblockrow = buffer[block_row];
(*cinfo->fdct->forward_DCT) (cinfo, compptr,
input_buf[ci], thisblockrow,
(JDIMENSION) (block_row * DCTSIZE),
(JDIMENSION) 0, blocks_across);
if (ndummy > 0) {
/* Create dummy blocks at the right edge of the image. */
thisblockrow += blocks_across; /* => first dummy block */
jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK));
lastDC = thisblockrow[-1][0];
for (bi = 0; bi < ndummy; bi++) {
thisblockrow[bi][0] = lastDC;
}
}
}
/* If at end of image, create dummy block rows as needed.
* The tricky part here is that within each MCU, we want the DC values
* of the dummy blocks to match the last real block's DC value.
* This squeezes a few more bytes out of the resulting file...
*/
if (coef->iMCU_row_num == last_iMCU_row) {
blocks_across += ndummy; /* include lower right corner */
MCUs_across = blocks_across / h_samp_factor;
for (block_row = block_rows; block_row < compptr->v_samp_factor;
block_row++) {
thisblockrow = buffer[block_row];
lastblockrow = buffer[block_row-1];
jzero_far((void FAR *) thisblockrow,
(size_t) (blocks_across * SIZEOF(JBLOCK)));
for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) {
lastDC = lastblockrow[h_samp_factor-1][0];
for (bi = 0; bi < h_samp_factor; bi++) {
thisblockrow[bi][0] = lastDC;
}
thisblockrow += h_samp_factor; /* advance to next MCU in row */
lastblockrow += h_samp_factor;
}
}
}
}
/* NB: compress_output will increment iMCU_row_num if successful.
* A suspension return will result in redoing all the work above next time.
*/
/* Emit data to the entropy encoder, sharing code with subsequent passes */
return compress_output(cinfo, input_buf);
}
/*
* Process some data in subsequent passes of a multi-pass case.
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
* per call, ie, v_samp_factor block rows for each component in the scan.
* The data is obtained from the virtual arrays and fed to the entropy coder.
* Returns TRUE if the iMCU row is completed, FALSE if suspended.
*
* NB: input_buf is ignored; it is likely to be a NULL pointer.
*/
METHODDEF(boolean)
compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
int blkn, ci, xindex, yindex, yoffset;
JDIMENSION start_col;
JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
JBLOCKROW buffer_ptr;
jpeg_component_info *compptr;
/* Align the virtual buffers for the components used in this scan.
* NB: during first pass, this is safe only because the buffers will
* already be aligned properly, so jmemmgr.c won't need to do any I/O.
*/
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
buffer[ci] = (*cinfo->mem->access_virt_barray)
((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
coef->iMCU_row_num * compptr->v_samp_factor,
(JDIMENSION) compptr->v_samp_factor, FALSE);
}
/* Loop to process one whole iMCU row */
for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
yoffset++) {
for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
MCU_col_num++) {
/* Construct list of pointers to DCT blocks belonging to this MCU */
blkn = 0; /* index of current DCT block within MCU */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
start_col = MCU_col_num * compptr->MCU_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
coef->MCU_buffer[blkn++] = buffer_ptr++;
}
}
}
/* Try to write the MCU. */
if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->mcu_ctr = MCU_col_num;
return FALSE;
}
}
/* Completed an MCU row, but perhaps not an iMCU row */
coef->mcu_ctr = 0;
}
/* Completed the iMCU row, advance counters for next one */
coef->iMCU_row_num++;
start_iMCU_row(cinfo);
return TRUE;
}
#endif /* FULL_COEF_BUFFER_SUPPORTED */
/*
* Initialize coefficient buffer controller.
*/
GLOBAL(void)
jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
{
my_coef_ptr coef;
coef = (my_coef_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_coef_controller));
cinfo->coef = (struct jpeg_c_coef_controller *) coef;
coef->pub.start_pass = start_pass_coef;
/* Create the coefficient buffer. */
if (need_full_buffer) {
#ifdef FULL_COEF_BUFFER_SUPPORTED
/* Allocate a full-image virtual array for each component, */
/* padded to a multiple of samp_factor DCT blocks in each direction. */
int ci;
jpeg_component_info *compptr;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
(long) compptr->h_samp_factor),
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
(long) compptr->v_samp_factor),
(JDIMENSION) compptr->v_samp_factor);
}
#else
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
#endif
} else {
/* We only need a single-MCU buffer. */
JBLOCKROW buffer;
int i;
buffer = (JBLOCKROW)
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
coef->MCU_buffer[i] = buffer + i;
}
coef->whole_image[0] = NULL; /* flag for no virtual arrays */
}
}

534
jccolor.c
View File

@@ -1,19 +1,31 @@
/*
* jccolor.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1996, Thomas G. Lane.
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright 2009 D. R. Commander
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains input colorspace conversion routines.
* These routines are invoked via the methods get_sample_rows
* and colorin_init/term.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jsimd.h"
static JSAMPARRAY pixel_row; /* Workspace for a pixel row in input format */
/* Private subobject */
typedef struct {
struct jpeg_color_converter pub; /* public fields */
/* Private state for RGB->YCC conversion */
INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */
} my_color_converter;
typedef my_color_converter * my_cconvert_ptr;
/**************** RGB -> YCbCr conversion: most common case **************/
@@ -23,9 +35,14 @@ static JSAMPARRAY pixel_row; /* Workspace for a pixel row in input format */
* normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
* The conversion equations to be implemented are therefore
* Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
* Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + MAXJSAMPLE/2
* Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + MAXJSAMPLE/2
* Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE
* Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE
* (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
* Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2,
* rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and
* negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0)
* were not represented exactly. Now we sacrifice exact representation of
* maximum red and maximum blue in order to get exact grayscales.
*
* To avoid floating-point arithmetic, we represent the fractional constants
* as integers scaled up by 2^16 (about 4 digits precision); we have to divide
@@ -37,15 +54,12 @@ static JSAMPARRAY pixel_row; /* Workspace for a pixel row in input format */
* for 12-bit samples it is still acceptable. It's not very reasonable for
* 16-bit samples, but if you want lossless storage you shouldn't be changing
* colorspace anyway.
* The MAXJSAMPLE/2 offsets and the rounding fudge-factor of 0.5 are included
* The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
* in the tables to save adding them separately in the inner loop.
*/
#ifdef SIXTEEN_BIT_SAMPLES
#define SCALEBITS 14 /* avoid overflow */
#else
#define SCALEBITS 16 /* speedier right-shift on some machines */
#endif
#define SCALEBITS 16 /* speediest right-shift on some machines */
#define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS)
#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
@@ -55,7 +69,6 @@ static JSAMPARRAY pixel_row; /* Workspace for a pixel row in input format */
* machines (more than can hold all eight addresses, anyway).
*/
static INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */
#define R_Y_OFF 0 /* offset to R => Y section */
#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */
#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */
@@ -68,22 +81,89 @@ static INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */
#define TABLE_SIZE (8*(MAXJSAMPLE+1))
#if BITS_IN_JSAMPLE == 8
const unsigned char red_lut[256] = {
0 , 0 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 3 , 3 , 3 , 4 , 4 , 4 , 4 ,
5 , 5 , 5 , 6 , 6 , 6 , 7 , 7 , 7 , 7 , 8 , 8 , 8 , 9 , 9 , 9 ,
10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14,
14, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19,
19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 24,
24, 24, 25, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 28,
29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33,
33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 36, 37, 37, 37, 38, 38,
38, 39, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 42, 43,
43, 43, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 47, 47, 47, 48,
48, 48, 48, 49, 49, 49, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52,
53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 56, 56, 56, 57, 57, 57,
57, 58, 58, 58, 59, 59, 59, 60, 60, 60, 60, 61, 61, 61, 62, 62,
62, 62, 63, 63, 63, 64, 64, 64, 65, 65, 65, 65, 66, 66, 66, 67,
67, 67, 68, 68, 68, 68, 69, 69, 69, 70, 70, 70, 71, 71, 71, 71,
72, 72, 72, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 76, 76, 76
};
const unsigned char green_lut[256] = {
0 , 1 , 1 , 2 , 2 , 3 , 4 , 4 , 5 , 5 , 6 , 6 ,
7 , 8 , 8 , 9 , 9 , 10 , 11 , 11 , 12 , 12 , 13 , 14 ,
14 , 15 , 15 , 16 , 16 , 17 , 18 , 18 , 19 , 19 , 20 , 21 ,
21 , 22 , 22 , 23 , 23 , 24 , 25 , 25 , 26 , 26 , 27 , 28 ,
28 , 29 , 29 , 30 , 31 , 31 , 32 , 32 , 33 , 33 , 34 , 35 ,
35 , 36 , 36 , 37 , 38 , 38 , 39 , 39 , 40 , 41 , 41 , 42 ,
42 , 43 , 43 , 44 , 45 , 45 , 46 , 46 , 47 , 48 , 48 , 49 ,
49 , 50 , 50 , 51 , 52 , 52 , 53 , 53 , 54 , 55 , 55 , 56 ,
56 , 57 , 58 , 58 , 59 , 59 , 60 , 60 , 61 , 62 , 62 , 63 ,
63 , 64 , 65 , 65 , 66 , 66 , 67 , 68 , 68 , 69 , 69 , 70 ,
70 , 71 , 72 , 72 , 73 , 73 , 74 , 75 , 75 , 76 , 76 , 77 ,
77 , 78 , 79 , 79 , 80 , 80 , 81 , 82 , 82 , 83 , 83 , 84 ,
85 , 85 , 86 , 86 , 87 , 87 , 88 , 89 , 89 , 90 , 90 , 91 ,
92 , 92 , 93 , 93 , 94 , 95 , 95 , 96 , 96 , 97 , 97 , 98 ,
99 , 99 , 100, 100, 101, 102, 102, 103, 103, 104, 104, 105,
106, 106, 107, 107, 108, 109, 109, 110, 110, 111, 112, 112,
113, 113, 114, 114, 115, 116, 116, 117, 117, 118, 119, 119,
120, 120, 121, 122, 122, 123, 123, 124, 124, 125, 126, 126,
127, 127, 128, 129, 129, 130, 130, 131, 131, 132, 133, 133,
34, 134, 135, 136, 136, 137, 137, 138, 139, 139, 140, 140,
141, 141, 142, 143, 143, 144, 144, 145, 146, 146, 147, 147,
148, 149, 149, 150
};
const unsigned char blue_lut[256] = {
0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 2 , 2 ,
2 , 2 , 2 , 2 , 2 , 2 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 4 ,
4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ,
5 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 7 , 7 , 7 , 7 , 7 , 7 ,
7 , 7 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 9 , 9 , 9 , 9 , 9 ,
9 , 9 , 9 , 9 , 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13,
13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14,
15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18,
18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20,
20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22,
22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24,
24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25,
26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27,
27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29
};
#endif
/*
* Initialize for colorspace conversion.
* Initialize for RGB->YCC colorspace conversion.
*/
METHODDEF void
rgb_ycc_init (compress_info_ptr cinfo)
METHODDEF(void)
rgb_ycc_start (j_compress_ptr cinfo)
{
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
INT32 * rgb_ycc_tab;
INT32 i;
/* Allocate a workspace for the result of get_input_row. */
pixel_row = (*cinfo->emethods->alloc_small_sarray)
(cinfo->image_width, (long) cinfo->input_components);
/* Allocate and fill in the conversion tables. */
rgb_ycc_tab = (INT32 *) (*cinfo->emethods->alloc_small)
(TABLE_SIZE * SIZEOF(INT32));
cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(TABLE_SIZE * SIZEOF(INT32)));
for (i = 0; i <= MAXJSAMPLE; i++) {
rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i;
@@ -91,9 +171,13 @@ rgb_ycc_init (compress_info_ptr cinfo)
rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i;
rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i;
rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + ONE_HALF*(MAXJSAMPLE+1);
/* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
* This ensures that the maximum output will round to MAXJSAMPLE
* not MAXJSAMPLE+1, and thus that we don't have to range-limit.
*/
rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
/* B=>Cb and R=>Cr tables are the same
rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + ONE_HALF*(MAXJSAMPLE+1);
rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
*/
rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i;
rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i;
@@ -102,40 +186,41 @@ rgb_ycc_init (compress_info_ptr cinfo)
/*
* Fetch some rows of pixels from get_input_row and convert to the
* JPEG colorspace.
* Convert some rows of samples to the JPEG colorspace.
*
* Note that we change from the application's interleaved-pixel format
* to our internal noninterleaved, one-plane-per-component format.
* The input buffer is therefore three times as wide as the output buffer.
*
* A starting row offset is provided only for the output buffer. The caller
* can easily adjust the passed input_buf value to accommodate any row
* offset required on that side.
*/
METHODDEF void
get_rgb_ycc_rows (compress_info_ptr cinfo,
int rows_to_read, JSAMPIMAGE image_data)
METHODDEF(void)
rgb_ycc_convert (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
JDIMENSION output_row, int num_rows)
{
#ifdef SIXTEEN_BIT_SAMPLES
register UINT16 r, g, b;
#else
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
register int r, g, b;
#endif
register INT32 * ctab = rgb_ycc_tab;
register JSAMPROW inptr0, inptr1, inptr2;
register INT32 * ctab = cconvert->rgb_ycc_tab;
register JSAMPROW inptr;
register JSAMPROW outptr0, outptr1, outptr2;
register long col;
long width = cinfo->image_width;
int row;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->image_width;
for (row = 0; row < rows_to_read; row++) {
/* Read one row from the source file */
(*cinfo->methods->get_input_row) (cinfo, pixel_row);
/* Convert colorspace */
inptr0 = pixel_row[0];
inptr1 = pixel_row[1];
inptr2 = pixel_row[2];
outptr0 = image_data[0][row];
outptr1 = image_data[1][row];
outptr2 = image_data[2][row];
for (col = 0; col < width; col++) {
r = GETJSAMPLE(inptr0[col]);
g = GETJSAMPLE(inptr1[col]);
b = GETJSAMPLE(inptr2[col]);
while (--num_rows >= 0) {
inptr = *input_buf++;
outptr0 = output_buf[0][output_row];
outptr1 = output_buf[1][output_row];
outptr2 = output_buf[2][output_row];
output_row++;
for (col = 0; col < num_cols; col++) {
r = GETJSAMPLE(inptr[rgb_red[cinfo->in_color_space]]);
g = GETJSAMPLE(inptr[rgb_green[cinfo->in_color_space]]);
b = GETJSAMPLE(inptr[rgb_blue[cinfo->in_color_space]]);
inptr += rgb_pixelsize[cinfo->in_color_space];
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
* must be too; we do not need an explicit range-limiting operation.
* Hence the value being shifted is never negative, and we don't
@@ -162,200 +247,321 @@ get_rgb_ycc_rows (compress_info_ptr cinfo,
/*
* Fetch some rows of pixels from get_input_row and convert to the
* JPEG colorspace.
* Convert some rows of samples to the JPEG colorspace.
* This version handles RGB->grayscale conversion, which is the same
* as the RGB->Y portion of RGB->YCbCr.
* We assume rgb_ycc_init has been called (we only use the Y tables).
* We assume rgb_ycc_start has been called (we only use the Y tables).
*/
METHODDEF void
get_rgb_gray_rows (compress_info_ptr cinfo,
int rows_to_read, JSAMPIMAGE image_data)
METHODDEF(void)
rgb_gray_convert (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
JDIMENSION output_row, int num_rows)
{
#ifdef SIXTEEN_BIT_SAMPLES
register UINT16 r, g, b;
#else
register int r, g, b;
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
#if BITS_IN_JSAMPLE != 8
register INT32 * ctab = cconvert->rgb_ycc_tab;
#endif
register INT32 * ctab = rgb_ycc_tab;
register JSAMPROW inptr0, inptr1, inptr2;
register JSAMPROW inptr;
register JSAMPROW outptr;
register long col;
long width = cinfo->image_width;
int row;
JSAMPLE *maxoutptr;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->image_width;
int rindex = rgb_red[cinfo->in_color_space];
int gindex = rgb_green[cinfo->in_color_space];
int bindex = rgb_blue[cinfo->in_color_space];
int rgbstride = rgb_pixelsize[cinfo->in_color_space];
for (row = 0; row < rows_to_read; row++) {
/* Read one row from the source file */
(*cinfo->methods->get_input_row) (cinfo, pixel_row);
/* Convert colorspace */
inptr0 = pixel_row[0];
inptr1 = pixel_row[1];
inptr2 = pixel_row[2];
outptr = image_data[0][row];
for (col = 0; col < width; col++) {
r = GETJSAMPLE(inptr0[col]);
g = GETJSAMPLE(inptr1[col]);
b = GETJSAMPLE(inptr2[col]);
while (--num_rows >= 0) {
inptr = *input_buf++;
outptr = output_buf[0][output_row];
maxoutptr = &outptr[num_cols];
output_row++;
for (; outptr < maxoutptr; outptr++, inptr += rgbstride) {
/* Y */
#if BITS_IN_JSAMPLE == 8
*outptr = red_lut[inptr[rindex]] + green_lut[inptr[gindex]]
+ blue_lut[inptr[bindex]];
#else
*outptr = (JSAMPLE)
((ctab[GETJSAMPLE(inptr[rindex])+R_Y_OFF]
+ ctab[GETJSAMPLE(inptr[gindex])+G_Y_OFF]
+ ctab[GETJSAMPLE(inptr[bindex])+B_Y_OFF])
>> SCALEBITS);
#endif
}
}
}
/*
* Convert some rows of samples to the JPEG colorspace.
* This version handles Adobe-style CMYK->YCCK conversion,
* where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
* conversion as above, while passing K (black) unchanged.
* We assume rgb_ycc_start has been called.
*/
METHODDEF(void)
cmyk_ycck_convert (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
JDIMENSION output_row, int num_rows)
{
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
register int r, g, b;
register INT32 * ctab = cconvert->rgb_ycc_tab;
register JSAMPROW inptr;
register JSAMPROW outptr0, outptr1, outptr2, outptr3;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->image_width;
while (--num_rows >= 0) {
inptr = *input_buf++;
outptr0 = output_buf[0][output_row];
outptr1 = output_buf[1][output_row];
outptr2 = output_buf[2][output_row];
outptr3 = output_buf[3][output_row];
output_row++;
for (col = 0; col < num_cols; col++) {
r = MAXJSAMPLE - GETJSAMPLE(inptr[0]);
g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
/* K passes through as-is */
outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */
inptr += 4;
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
* must be too; we do not need an explicit range-limiting operation.
* Hence the value being shifted is never negative, and we don't
* need the general RIGHT_SHIFT macro.
*/
/* Y */
outptr[col] = (JSAMPLE)
outptr0[col] = (JSAMPLE)
((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
>> SCALEBITS);
/* Cb */
outptr1[col] = (JSAMPLE)
((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
>> SCALEBITS);
/* Cr */
outptr2[col] = (JSAMPLE)
((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
>> SCALEBITS);
}
}
}
/*
* Initialize for colorspace conversion.
*/
METHODDEF void
colorin_init (compress_info_ptr cinfo)
{
/* Allocate a workspace for the result of get_input_row. */
pixel_row = (*cinfo->emethods->alloc_small_sarray)
(cinfo->image_width, (long) cinfo->input_components);
}
/*
* Fetch some rows of pixels from get_input_row and convert to the
* JPEG colorspace.
* Convert some rows of samples to the JPEG colorspace.
* This version handles grayscale output with no conversion.
* The source can be either plain grayscale or YCbCr (since Y == gray).
*/
METHODDEF void
get_grayscale_rows (compress_info_ptr cinfo,
int rows_to_read, JSAMPIMAGE image_data)
METHODDEF(void)
grayscale_convert (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
JDIMENSION output_row, int num_rows)
{
int row;
register JSAMPROW inptr;
register JSAMPROW outptr;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->image_width;
int instride = cinfo->input_components;
for (row = 0; row < rows_to_read; row++) {
/* Read one row from the source file */
(*cinfo->methods->get_input_row) (cinfo, pixel_row);
/* Convert colorspace (gamma mapping needed here) */
jcopy_sample_rows(pixel_row, 0, image_data[0], row,
1, cinfo->image_width);
while (--num_rows >= 0) {
inptr = *input_buf++;
outptr = output_buf[0][output_row];
output_row++;
for (col = 0; col < num_cols; col++) {
outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */
inptr += instride;
}
}
}
/*
* Fetch some rows of pixels from get_input_row and convert to the
* JPEG colorspace.
* Convert some rows of samples to the JPEG colorspace.
* This version handles multi-component colorspaces without conversion.
* We assume input_components == num_components.
*/
METHODDEF void
get_noconvert_rows (compress_info_ptr cinfo,
int rows_to_read, JSAMPIMAGE image_data)
METHODDEF(void)
null_convert (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
JDIMENSION output_row, int num_rows)
{
int row, ci;
register JSAMPROW inptr;
register JSAMPROW outptr;
register JDIMENSION col;
register int ci;
int nc = cinfo->num_components;
JDIMENSION num_cols = cinfo->image_width;
for (row = 0; row < rows_to_read; row++) {
/* Read one row from the source file */
(*cinfo->methods->get_input_row) (cinfo, pixel_row);
/* Convert colorspace (gamma mapping needed here) */
for (ci = 0; ci < cinfo->input_components; ci++) {
jcopy_sample_rows(pixel_row, ci, image_data[ci], row,
1, cinfo->image_width);
while (--num_rows >= 0) {
/* It seems fastest to make a separate pass for each component. */
for (ci = 0; ci < nc; ci++) {
inptr = *input_buf;
outptr = output_buf[ci][output_row];
for (col = 0; col < num_cols; col++) {
outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
inptr += nc;
}
}
input_buf++;
output_row++;
}
}
/*
* Finish up at the end of the file.
* Empty method for start_pass.
*/
METHODDEF void
colorin_term (compress_info_ptr cinfo)
METHODDEF(void)
null_method (j_compress_ptr cinfo)
{
/* no work (we let free_all release the workspace) */
/* no work needed */
}
/*
* The method selection routine for input colorspace conversion.
* Module initialization routine for input colorspace conversion.
*/
GLOBAL void
jselccolor (compress_info_ptr cinfo)
GLOBAL(void)
jinit_color_converter (j_compress_ptr cinfo)
{
my_cconvert_ptr cconvert;
cconvert = (my_cconvert_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_color_converter));
cinfo->cconvert = (struct jpeg_color_converter *) cconvert;
/* set start_pass to null method until we find out differently */
cconvert->pub.start_pass = null_method;
/* Make sure input_components agrees with in_color_space */
switch (cinfo->in_color_space) {
case CS_GRAYSCALE:
case JCS_GRAYSCALE:
if (cinfo->input_components != 1)
ERREXIT(cinfo->emethods, "Bogus input colorspace");
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
break;
case CS_RGB:
case CS_YCbCr:
case CS_YIQ:
case JCS_RGB:
case JCS_EXT_RGB:
case JCS_EXT_RGBX:
case JCS_EXT_BGR:
case JCS_EXT_BGRX:
case JCS_EXT_XBGR:
case JCS_EXT_XRGB:
if (cinfo->input_components != rgb_pixelsize[cinfo->in_color_space])
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
break;
case JCS_YCbCr:
if (cinfo->input_components != 3)
ERREXIT(cinfo->emethods, "Bogus input colorspace");
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
break;
case CS_CMYK:
case JCS_CMYK:
case JCS_YCCK:
if (cinfo->input_components != 4)
ERREXIT(cinfo->emethods, "Bogus input colorspace");
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
break;
default:
ERREXIT(cinfo->emethods, "Unsupported input colorspace");
default: /* JCS_UNKNOWN can be anything */
if (cinfo->input_components < 1)
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
break;
}
/* Standard init/term methods (may override below) */
cinfo->methods->colorin_init = colorin_init;
cinfo->methods->colorin_term = colorin_term;
/* Check num_components, set conversion method based on requested space */
switch (cinfo->jpeg_color_space) {
case CS_GRAYSCALE:
case JCS_GRAYSCALE:
if (cinfo->num_components != 1)
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
if (cinfo->in_color_space == CS_GRAYSCALE)
cinfo->methods->get_sample_rows = get_grayscale_rows;
else if (cinfo->in_color_space == CS_RGB) {
cinfo->methods->colorin_init = rgb_ycc_init;
cinfo->methods->get_sample_rows = get_rgb_gray_rows;
} else if (cinfo->in_color_space == CS_YCbCr)
cinfo->methods->get_sample_rows = get_grayscale_rows;
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
if (cinfo->in_color_space == JCS_GRAYSCALE)
cconvert->pub.color_convert = grayscale_convert;
else if (cinfo->in_color_space == JCS_RGB ||
cinfo->in_color_space == JCS_EXT_RGB ||
cinfo->in_color_space == JCS_EXT_RGBX ||
cinfo->in_color_space == JCS_EXT_BGR ||
cinfo->in_color_space == JCS_EXT_BGRX ||
cinfo->in_color_space == JCS_EXT_XBGR ||
cinfo->in_color_space == JCS_EXT_XRGB) {
cconvert->pub.start_pass = rgb_ycc_start;
cconvert->pub.color_convert = rgb_gray_convert;
} else if (cinfo->in_color_space == JCS_YCbCr)
cconvert->pub.color_convert = grayscale_convert;
else
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
case CS_YCbCr:
case JCS_RGB:
case JCS_EXT_RGB:
case JCS_EXT_RGBX:
case JCS_EXT_BGR:
case JCS_EXT_BGRX:
case JCS_EXT_XBGR:
case JCS_EXT_XRGB:
if (cinfo->num_components != 3)
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
if (cinfo->in_color_space == CS_RGB) {
cinfo->methods->colorin_init = rgb_ycc_init;
cinfo->methods->get_sample_rows = get_rgb_ycc_rows;
} else if (cinfo->in_color_space == CS_YCbCr)
cinfo->methods->get_sample_rows = get_noconvert_rows;
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
if (cinfo->in_color_space == cinfo->jpeg_color_space &&
rgb_pixelsize[cinfo->in_color_space] == 3)
cconvert->pub.color_convert = null_convert;
else
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
case CS_CMYK:
case JCS_YCbCr:
if (cinfo->num_components != 3)
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
if (cinfo->in_color_space == JCS_RGB ||
cinfo->in_color_space == JCS_EXT_RGB ||
cinfo->in_color_space == JCS_EXT_RGBX ||
cinfo->in_color_space == JCS_EXT_BGR ||
cinfo->in_color_space == JCS_EXT_BGRX ||
cinfo->in_color_space == JCS_EXT_XBGR ||
cinfo->in_color_space == JCS_EXT_XRGB) {
if (jsimd_can_rgb_ycc())
cconvert->pub.color_convert = jsimd_rgb_ycc_convert;
else {
cconvert->pub.start_pass = rgb_ycc_start;
cconvert->pub.color_convert = rgb_ycc_convert;
}
} else if (cinfo->in_color_space == JCS_YCbCr)
cconvert->pub.color_convert = null_convert;
else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
case JCS_CMYK:
if (cinfo->num_components != 4)
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
if (cinfo->in_color_space == CS_CMYK)
cinfo->methods->get_sample_rows = get_noconvert_rows;
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
if (cinfo->in_color_space == JCS_CMYK)
cconvert->pub.color_convert = null_convert;
else
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
default:
ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace");
case JCS_YCCK:
if (cinfo->num_components != 4)
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
if (cinfo->in_color_space == JCS_CMYK) {
cconvert->pub.start_pass = rgb_ycc_start;
cconvert->pub.color_convert = cmyk_ycck_convert;
} else if (cinfo->in_color_space == JCS_YCCK)
cconvert->pub.color_convert = null_convert;
else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
default: /* allow null conversion of JCS_UNKNOWN */
if (cinfo->jpeg_color_space != cinfo->in_color_space ||
cinfo->num_components != cinfo->input_components)
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
cconvert->pub.color_convert = null_convert;
break;
}
}

632
jcdctmgr.c Normal file
View File

@@ -0,0 +1,632 @@
/*
* jcdctmgr.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* Copyright (C) 1999-2006, MIYASAKA Masaru.
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the forward-DCT management logic.
* This code selects a particular DCT implementation to be used,
* and it performs related housekeeping chores including coefficient
* quantization.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#include "jsimddct.h"
/* Private subobject for this module */
typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data));
typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data));
typedef JMETHOD(void, convsamp_method_ptr,
(JSAMPARRAY sample_data, JDIMENSION start_col,
DCTELEM * workspace));
typedef JMETHOD(void, float_convsamp_method_ptr,
(JSAMPARRAY sample_data, JDIMENSION start_col,
FAST_FLOAT *workspace));
typedef JMETHOD(void, quantize_method_ptr,
(JCOEFPTR coef_block, DCTELEM * divisors,
DCTELEM * workspace));
typedef JMETHOD(void, float_quantize_method_ptr,
(JCOEFPTR coef_block, FAST_FLOAT * divisors,
FAST_FLOAT * workspace));
typedef struct {
struct jpeg_forward_dct pub; /* public fields */
/* Pointer to the DCT routine actually in use */
forward_DCT_method_ptr dct;
convsamp_method_ptr convsamp;
quantize_method_ptr quantize;
/* The actual post-DCT divisors --- not identical to the quant table
* entries, because of scaling (especially for an unnormalized DCT).
* Each table is given in normal array order.
*/
DCTELEM * divisors[NUM_QUANT_TBLS];
/* work area for FDCT subroutine */
DCTELEM * workspace;
#ifdef DCT_FLOAT_SUPPORTED
/* Same as above for the floating-point case. */
float_DCT_method_ptr float_dct;
float_convsamp_method_ptr float_convsamp;
float_quantize_method_ptr float_quantize;
FAST_FLOAT * float_divisors[NUM_QUANT_TBLS];
FAST_FLOAT * float_workspace;
#endif
} my_fdct_controller;
typedef my_fdct_controller * my_fdct_ptr;
/*
* Find the highest bit in an integer through binary search.
*/
LOCAL(int)
flss (UINT16 val)
{
int bit;
bit = 16;
if (!val)
return 0;
if (!(val & 0xff00)) {
bit -= 8;
val <<= 8;
}
if (!(val & 0xf000)) {
bit -= 4;
val <<= 4;
}
if (!(val & 0xc000)) {
bit -= 2;
val <<= 2;
}
if (!(val & 0x8000)) {
bit -= 1;
val <<= 1;
}
return bit;
}
/*
* Compute values to do a division using reciprocal.
*
* This implementation is based on an algorithm described in
* "How to optimize for the Pentium family of microprocessors"
* (http://www.agner.org/assem/).
* More information about the basic algorithm can be found in
* the paper "Integer Division Using Reciprocals" by Robert Alverson.
*
* The basic idea is to replace x/d by x * d^-1. In order to store
* d^-1 with enough precision we shift it left a few places. It turns
* out that this algoright gives just enough precision, and also fits
* into DCTELEM:
*
* b = (the number of significant bits in divisor) - 1
* r = (word size) + b
* f = 2^r / divisor
*
* f will not be an integer for most cases, so we need to compensate
* for the rounding error introduced:
*
* no fractional part:
*
* result = input >> r
*
* fractional part of f < 0.5:
*
* round f down to nearest integer
* result = ((input + 1) * f) >> r
*
* fractional part of f > 0.5:
*
* round f up to nearest integer
* result = (input * f) >> r
*
* This is the original algorithm that gives truncated results. But we
* want properly rounded results, so we replace "input" with
* "input + divisor/2".
*
* 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)
* dctbl[3] = r - (word size)
*
* dctbl[2] is for stupid instruction sets where the shift operation
* isn't member wise (e.g. MMX).
*
* The reason dctbl[2] and dctbl[3] reduce the shift with (word size)
* is that most SIMD implementations have a "multiply and store top
* half" operation.
*
* Lastly, we store each of the values in their own table instead
* of in a consecutive manner, yet again in order to allow SIMD
* routines.
*/
LOCAL(void)
compute_reciprocal (UINT16 divisor, DCTELEM * dtbl)
{
UDCTELEM2 fq, fr;
UDCTELEM c;
int b, r;
b = flss(divisor) - 1;
r = sizeof(DCTELEM) * 8 + b;
fq = ((UDCTELEM2)1 << r) / divisor;
fr = ((UDCTELEM2)1 << r) % divisor;
c = divisor / 2; /* for rounding */
if (fr == 0) { /* divisor is power of two */
/* fq will be one bit too large to fit in DCTELEM, so adjust */
fq >>= 1;
r--;
} else if (fr <= (divisor / 2)) { /* fractional part is < 0.5 */
c++;
} else { /* fractional part is > 0.5 */
fq++;
}
dtbl[DCTSIZE2 * 0] = (DCTELEM) fq; /* reciprocal */
dtbl[DCTSIZE2 * 1] = (DCTELEM) c; /* correction + roundfactor */
dtbl[DCTSIZE2 * 2] = (DCTELEM) (1 << (sizeof(DCTELEM)*8*2 - r)); /* scale */
dtbl[DCTSIZE2 * 3] = (DCTELEM) r - sizeof(DCTELEM)*8; /* shift */
}
/*
* Initialize for a processing pass.
* Verify that all referenced Q-tables are present, and set up
* the divisor table for each one.
* In the current implementation, DCT of all components is done during
* the first pass, even if only some components will be output in the
* first scan. Hence all components should be examined here.
*/
METHODDEF(void)
start_pass_fdctmgr (j_compress_ptr cinfo)
{
my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
int ci, qtblno, i;
jpeg_component_info *compptr;
JQUANT_TBL * qtbl;
DCTELEM * dtbl;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
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)
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
qtbl = cinfo->quant_tbl_ptrs[qtblno];
/* Compute divisors for this quant table */
/* We may do this more than once for same table, but it's not a big deal */
switch (cinfo->dct_method) {
#ifdef DCT_ISLOW_SUPPORTED
case JDCT_ISLOW:
/* For LL&M IDCT method, divisors are equal to raw quantization
* 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,
(DCTSIZE2 * 4) * SIZEOF(DCTELEM));
}
dtbl = fdct->divisors[qtblno];
for (i = 0; i < DCTSIZE2; i++) {
compute_reciprocal(qtbl->quantval[i] << 3, &dtbl[i]);
}
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.
*/
#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
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++) {
compute_reciprocal(
DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
(INT32) aanscales[i]),
CONST_BITS-3), &dtbl[i]);
}
}
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
};
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++;
}
}
}
break;
#endif
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
break;
}
}
}
/*
* Load data into workspace, applying unsigned->signed conversion.
*/
METHODDEF(void)
convsamp (JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM * workspace)
{
register DCTELEM *workspaceptr;
register JSAMPROW elemptr;
register int elemr;
workspaceptr = workspace;
for (elemr = 0; elemr < DCTSIZE; elemr++) {
elemptr = sample_data[elemr] + start_col;
#if DCTSIZE == 8 /* unroll the inner loop */
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
#else
{
register int elemc;
for (elemc = DCTSIZE; elemc > 0; elemc--)
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
}
#endif
}
}
/*
* Quantize/descale the coefficients, and store into coef_blocks[].
*/
METHODDEF(void)
quantize (JCOEFPTR coef_block, DCTELEM * divisors, DCTELEM * workspace)
{
int i;
DCTELEM temp;
UDCTELEM recip, corr, shift;
UDCTELEM2 product;
JCOEFPTR output_ptr = coef_block;
for (i = 0; i < DCTSIZE2; i++) {
temp = workspace[i];
recip = divisors[i + DCTSIZE2 * 0];
corr = divisors[i + DCTSIZE2 * 1];
shift = divisors[i + DCTSIZE2 * 3];
if (temp < 0) {
temp = -temp;
product = (UDCTELEM2)(temp + corr) * recip;
product >>= shift + sizeof(DCTELEM)*8;
temp = product;
temp = -temp;
} else {
product = (UDCTELEM2)(temp + corr) * recip;
product >>= shift + sizeof(DCTELEM)*8;
temp = product;
}
output_ptr[i] = (JCOEF) temp;
}
}
/*
* Perform forward DCT on one or more blocks of a component.
*
* The input samples are taken from the sample_data[] array starting at
* position start_row/start_col, and moving to the right for any additional
* blocks. The quantized coefficients are returned in coef_blocks[].
*/
METHODDEF(void)
forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
JDIMENSION start_row, JDIMENSION start_col,
JDIMENSION num_blocks)
/* This version is used for integer DCT implementations. */
{
/* This routine is heavily used, so it's worth coding it tightly. */
my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no];
DCTELEM * workspace;
JDIMENSION bi;
/* Make sure the compiler doesn't look up these every pass */
forward_DCT_method_ptr do_dct = fdct->dct;
convsamp_method_ptr do_convsamp = fdct->convsamp;
quantize_method_ptr do_quantize = fdct->quantize;
workspace = fdct->workspace;
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 */
(*do_convsamp) (sample_data, start_col, workspace);
/* Perform the DCT */
(*do_dct) (workspace);
/* Quantize/descale the coefficients, and store into coef_blocks[] */
(*do_quantize) (coef_blocks[bi], divisors, workspace);
}
}
#ifdef DCT_FLOAT_SUPPORTED
METHODDEF(void)
convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT * workspace)
{
register FAST_FLOAT *workspaceptr;
register JSAMPROW elemptr;
register int elemr;
workspaceptr = workspace;
for (elemr = 0; elemr < DCTSIZE; elemr++) {
elemptr = sample_data[elemr] + start_col;
#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);
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
#else
{
register int elemc;
for (elemc = DCTSIZE; elemc > 0; elemc--)
*workspaceptr++ = (FAST_FLOAT)
(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
}
#endif
}
}
METHODDEF(void)
quantize_float (JCOEFPTR coef_block, FAST_FLOAT * divisors, FAST_FLOAT * workspace)
{
register FAST_FLOAT temp;
register int i;
register JCOEFPTR output_ptr = coef_block;
for (i = 0; i < DCTSIZE2; i++) {
/* Apply the quantization and scaling factor */
temp = workspace[i] * divisors[i];
/* Round to nearest integer.
* Since C does not specify the direction of rounding for negative
* quotients, we have to force the dividend positive for portability.
* The maximum coefficient size is +-16K (for 12-bit data), so this
* code should work for either 16-bit or 32-bit ints.
*/
output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384);
}
}
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,
JDIMENSION num_blocks)
/* This version is used for floating-point DCT implementations. */
{
/* This routine is heavily used, so it's worth coding it tightly. */
my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no];
FAST_FLOAT * workspace;
JDIMENSION bi;
/* Make sure the compiler doesn't look up these every pass */
float_DCT_method_ptr do_dct = fdct->float_dct;
float_convsamp_method_ptr do_convsamp = fdct->float_convsamp;
float_quantize_method_ptr do_quantize = fdct->float_quantize;
workspace = fdct->float_workspace;
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 */
(*do_convsamp) (sample_data, start_col, workspace);
/* Perform the DCT */
(*do_dct) (workspace);
/* Quantize/descale the coefficients, and store into coef_blocks[] */
(*do_quantize) (coef_blocks[bi], divisors, workspace);
}
}
#endif /* DCT_FLOAT_SUPPORTED */
/*
* Initialize FDCT manager.
*/
GLOBAL(void)
jinit_forward_dct (j_compress_ptr cinfo)
{
my_fdct_ptr fdct;
int i;
fdct = (my_fdct_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_fdct_controller));
cinfo->fdct = (struct jpeg_forward_dct *) fdct;
fdct->pub.start_pass = start_pass_fdctmgr;
/* First determine the DCT... */
switch (cinfo->dct_method) {
#ifdef DCT_ISLOW_SUPPORTED
case JDCT_ISLOW:
fdct->pub.forward_DCT = forward_DCT;
if (jsimd_can_fdct_islow())
fdct->dct = jsimd_fdct_islow;
else
fdct->dct = jpeg_fdct_islow;
break;
#endif
#ifdef DCT_IFAST_SUPPORTED
case JDCT_IFAST:
fdct->pub.forward_DCT = forward_DCT;
if (jsimd_can_fdct_ifast())
fdct->dct = jsimd_fdct_ifast;
else
fdct->dct = jpeg_fdct_ifast;
break;
#endif
#ifdef DCT_FLOAT_SUPPORTED
case JDCT_FLOAT:
fdct->pub.forward_DCT = forward_DCT_float;
if (jsimd_can_fdct_float())
fdct->float_dct = jsimd_fdct_float;
else
fdct->float_dct = jpeg_fdct_float;
break;
#endif
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
break;
}
/* ...then the supporting stages. */
switch (cinfo->dct_method) {
#ifdef DCT_ISLOW_SUPPORTED
case JDCT_ISLOW:
#endif
#ifdef DCT_IFAST_SUPPORTED
case JDCT_IFAST:
#endif
#if defined(DCT_ISLOW_SUPPORTED) || defined(DCT_IFAST_SUPPORTED)
if (jsimd_can_convsamp())
fdct->convsamp = jsimd_convsamp;
else
fdct->convsamp = convsamp;
if (jsimd_can_quantize())
fdct->quantize = jsimd_quantize;
else
fdct->quantize = quantize;
break;
#endif
#ifdef DCT_FLOAT_SUPPORTED
case JDCT_FLOAT:
if (jsimd_can_convsamp_float())
fdct->float_convsamp = jsimd_convsamp_float;
else
fdct->float_convsamp = convsamp_float;
if (jsimd_can_quantize_float())
fdct->float_quantize = jsimd_quantize_float;
else
fdct->float_quantize = quantize_float;
break;
#endif
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
break;
}
/* Allocate workspace memory */
#ifdef DCT_FLOAT_SUPPORTED
if (cinfo->dct_method == JDCT_FLOAT)
fdct->float_workspace = (FAST_FLOAT *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(FAST_FLOAT) * DCTSIZE2);
else
#endif
fdct->workspace = (DCTELEM *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(DCTELEM) * DCTSIZE2);
/* Mark divisor tables unallocated */
for (i = 0; i < NUM_QUANT_TBLS; i++) {
fdct->divisors[i] = NULL;
#ifdef DCT_FLOAT_SUPPORTED
fdct->float_divisors[i] = NULL;
#endif
}
}

View File

@@ -1,391 +0,0 @@
/*
* jcdeflts.c
*
* Copyright (C) 1991, 1992, 1993, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains optional default-setting code for the JPEG compressor.
* User interfaces do not have to use this file, but those that don't use it
* must know a lot more about the innards of the JPEG code.
*/
#include "jinclude.h"
/* Default do-nothing progress monitoring routine.
* This can be overridden by a user interface that wishes to
* provide progress monitoring; just set methods->progress_monitor
* after j_c_defaults is done. The routine will be called periodically
* during the compression process.
*
* During any one pass, loopcounter increases from 0 up to (not including)
* looplimit; the step size is not necessarily 1. Both the step size and
* the limit may differ between passes. The expected total number of passes
* is in cinfo->total_passes, and the number of passes already completed is
* in cinfo->completed_passes. Thus the fraction of work completed may be
* estimated as
* completed_passes + (loopcounter/looplimit)
* ------------------------------------------
* total_passes
* ignoring the fact that the passes may not be equal amounts of work.
*/
METHODDEF void
progress_monitor (compress_info_ptr cinfo, long loopcounter, long looplimit)
{
/* do nothing */
}
/*
* Huffman table setup routines
*/
LOCAL void
add_huff_table (compress_info_ptr cinfo,
HUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
/* Define a Huffman table */
{
if (*htblptr == NULL)
*htblptr = (HUFF_TBL *) (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL));
MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
MEMCOPY((*htblptr)->huffval, val, SIZEOF((*htblptr)->huffval));
/* Initialize sent_table FALSE so table will be written to JPEG file.
* In an application where we are writing non-interchange JPEG files,
* it might be desirable to save space by leaving default Huffman tables
* out of the file. To do that, just initialize sent_table = TRUE...
*/
(*htblptr)->sent_table = FALSE;
}
LOCAL void
std_huff_tables (compress_info_ptr cinfo)
/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
/* IMPORTANT: these are only valid for 8-bit data precision! */
{
static const UINT8 dc_luminance_bits[17] =
{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
static const UINT8 dc_luminance_val[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
static const UINT8 dc_chrominance_bits[17] =
{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
static const UINT8 dc_chrominance_val[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
static const UINT8 ac_luminance_bits[17] =
{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
static const UINT8 ac_luminance_val[] =
{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa };
static const UINT8 ac_chrominance_bits[17] =
{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
static const UINT8 ac_chrominance_val[] =
{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa };
add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0],
dc_luminance_bits, dc_luminance_val);
add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0],
ac_luminance_bits, ac_luminance_val);
add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1],
dc_chrominance_bits, dc_chrominance_val);
add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1],
ac_chrominance_bits, ac_chrominance_val);
}
/*
* Quantization table setup routines
*/
GLOBAL void
j_add_quant_table (compress_info_ptr cinfo, int which_tbl,
const QUANT_VAL *basic_table, int scale_factor,
boolean force_baseline)
/* Define a quantization table equal to the basic_table times
* a scale factor (given as a percentage).
* If force_baseline is TRUE, the computed quantization table entries
* are limited to 1..255 for JPEG baseline compatibility.
*/
{
QUANT_TBL_PTR * qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
int i;
long temp;
if (*qtblptr == NULL)
*qtblptr = (QUANT_TBL_PTR) (*cinfo->emethods->alloc_small) (SIZEOF(QUANT_TBL));
for (i = 0; i < DCTSIZE2; i++) {
temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
/* limit the values to the valid range */
if (temp <= 0L) temp = 1L;
#ifdef EIGHT_BIT_SAMPLES
if (temp > 32767L) temp = 32767L; /* QUANT_VALs are 'short' */
#else
if (temp > 65535L) temp = 65535L; /* QUANT_VALs are 'UINT16' */
#endif
if (force_baseline && temp > 255L)
temp = 255L; /* limit to baseline range if requested */
(*qtblptr)[i] = (QUANT_VAL) temp;
}
}
GLOBAL int
j_quality_scaling (int quality)
/* Convert a user-specified quality rating to a percentage scaling factor
* for an underlying quantization table, using our recommended scaling curve.
* The input 'quality' factor should be 0 (terrible) to 100 (very good).
*/
{
/* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */
if (quality <= 0) quality = 1;
if (quality > 100) quality = 100;
/* The basic table is used as-is (scaling 100) for a quality of 50.
* Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
* note that at Q=100 the scaling is 0, which will cause j_add_quant_table
* to make all the table entries 1 (hence, no quantization loss).
* Qualities 1..50 are converted to scaling percentage 5000/Q.
*/
if (quality < 50)
quality = 5000 / quality;
else
quality = 200 - quality*2;
return quality;
}
GLOBAL void
j_set_quality (compress_info_ptr cinfo, int quality, boolean force_baseline)
/* Set or change the 'quality' (quantization) setting, using default tables.
* This is the standard quality-adjusting entry point for typical user
* interfaces; only those who want detailed control over quantization tables
* would use the preceding two routines directly.
*/
{
/* This is the sample quantization table given in the JPEG spec section K.1,
* but expressed in zigzag order (as are all of our quant. tables).
* The spec says that the values given produce "good" quality, and
* when divided by 2, "very good" quality. (These two settings are
* selected by quality=50 and quality=75 respectively.)
*/
static const QUANT_VAL std_luminance_quant_tbl[DCTSIZE2] = {
16, 11, 12, 14, 12, 10, 16, 14,
13, 14, 18, 17, 16, 19, 24, 40,
26, 24, 22, 22, 24, 49, 35, 37,
29, 40, 58, 51, 61, 60, 57, 51,
56, 55, 64, 72, 92, 78, 64, 68,
87, 69, 55, 56, 80, 109, 81, 87,
95, 98, 103, 104, 103, 62, 77, 113,
121, 112, 100, 120, 92, 101, 103, 99
};
static const QUANT_VAL std_chrominance_quant_tbl[DCTSIZE2] = {
17, 18, 18, 24, 21, 24, 47, 26,
26, 47, 99, 66, 56, 66, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99
};
/* Convert user 0-100 rating to percentage scaling */
quality = j_quality_scaling(quality);
/* Set up two quantization tables using the specified quality scaling */
j_add_quant_table(cinfo, 0, std_luminance_quant_tbl,
quality, force_baseline);
j_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
quality, force_baseline);
}
/* Default parameter setup for compression.
*
* User interfaces that don't choose to use this routine must do their
* own setup of all these parameters. Alternately, you can call this
* to establish defaults and then alter parameters selectively. This
* is the recommended approach since, if we add any new parameters,
* your code will still work (they'll be set to reasonable defaults).
*
* See above for the meaning of the 'quality' and 'force_baseline' parameters.
* Typically, the application's default quality setting will be passed to this
* routine. A later call on j_set_quality() can be used to change to a
* user-specified quality setting.
*
* This routine sets up for a color image; to output a grayscale image,
* do this first and call j_monochrome_default() afterwards.
* (The latter can be called within c_ui_method_selection, so the
* choice can depend on the input file header.)
* Note that if you want a JPEG colorspace other than GRAYSCALE or YCbCr,
* you should also change the component ID codes, and you should NOT emit
* a JFIF header (set write_JFIF_header = FALSE).
*
* CAUTION: if you want to compress multiple images per run, it's necessary
* to call j_c_defaults before *each* call to jpeg_compress, since subsidiary
* structures like the Huffman tables are automatically freed during cleanup.
*/
GLOBAL void
j_c_defaults (compress_info_ptr cinfo, int quality, boolean force_baseline)
/* NB: the external methods must already be set up. */
{
short i;
jpeg_component_info * compptr;
/* Initialize pointers as needed to mark stuff unallocated. */
cinfo->comp_info = NULL;
for (i = 0; i < NUM_QUANT_TBLS; i++)
cinfo->quant_tbl_ptrs[i] = NULL;
for (i = 0; i < NUM_HUFF_TBLS; i++) {
cinfo->dc_huff_tbl_ptrs[i] = NULL;
cinfo->ac_huff_tbl_ptrs[i] = NULL;
}
cinfo->data_precision = BITS_IN_JSAMPLE; /* default; can be overridden by input_init */
cinfo->density_unit = 0; /* Pixel size is unknown by default */
cinfo->X_density = 1; /* Pixel aspect ratio is square by default */
cinfo->Y_density = 1;
cinfo->input_gamma = 1.0; /* no gamma correction by default */
cinfo->write_JFIF_header = TRUE; /* write a JFIF marker */
cinfo->comment_text = NULL; /* but no COM block */
/* Prepare three color components; first is luminance which is also usable */
/* for grayscale. The others are assumed to be UV or similar chrominance. */
cinfo->jpeg_color_space = CS_YCbCr;
cinfo->num_components = 3;
cinfo->comp_info = (jpeg_component_info *)
(*cinfo->emethods->alloc_small) (4 * SIZEOF(jpeg_component_info));
/* Note: we allocate a 4-entry comp_info array so that user interface can
* easily change over to CMYK color space if desired.
*/
compptr = &cinfo->comp_info[0];
compptr->component_index = 0;
compptr->component_id = 1; /* JFIF specifies IDs 1,2,3 */
compptr->h_samp_factor = 2; /* default to 2x2 subsamples of chrominance */
compptr->v_samp_factor = 2;
compptr->quant_tbl_no = 0; /* use tables 0 for luminance */
compptr->dc_tbl_no = 0;
compptr->ac_tbl_no = 0;
compptr = &cinfo->comp_info[1];
compptr->component_index = 1;
compptr->component_id = 2;
compptr->h_samp_factor = 1;
compptr->v_samp_factor = 1;
compptr->quant_tbl_no = 1; /* use tables 1 for chrominance */
compptr->dc_tbl_no = 1;
compptr->ac_tbl_no = 1;
compptr = &cinfo->comp_info[2];
compptr->component_index = 2;
compptr->component_id = 3;
compptr->h_samp_factor = 1;
compptr->v_samp_factor = 1;
compptr->quant_tbl_no = 1; /* use tables 1 for chrominance */
compptr->dc_tbl_no = 1;
compptr->ac_tbl_no = 1;
/* Set up two quantization tables using the specified quality scaling */
j_set_quality(cinfo, quality, force_baseline);
/* Set up two Huffman tables in case user interface wants Huffman coding */
std_huff_tables(cinfo);
/* Initialize default arithmetic coding conditioning */
for (i = 0; i < NUM_ARITH_TBLS; i++) {
cinfo->arith_dc_L[i] = 0;
cinfo->arith_dc_U[i] = 1;
cinfo->arith_ac_K[i] = 5;
}
/* Use Huffman coding, not arithmetic coding, by default */
cinfo->arith_code = FALSE;
/* Color images are interleaved by default */
cinfo->interleave = TRUE;
/* By default, don't do extra passes to optimize entropy coding */
cinfo->optimize_coding = FALSE;
/* By default, use the simpler non-cosited sampling alignment */
cinfo->CCIR601_sampling = FALSE;
/* No input smoothing */
cinfo->smoothing_factor = 0;
/* No restart markers */
cinfo->restart_interval = 0;
cinfo->restart_in_rows = 0;
/* Install default do-nothing progress monitoring method. */
cinfo->methods->progress_monitor = progress_monitor;
}
GLOBAL void
j_monochrome_default (compress_info_ptr cinfo)
/* Change the j_c_defaults() values to emit a monochrome JPEG file. */
{
jpeg_component_info * compptr;
cinfo->jpeg_color_space = CS_GRAYSCALE;
cinfo->num_components = 1;
/* Set single component to 1x1 subsampling */
compptr = &cinfo->comp_info[0];
compptr->h_samp_factor = 1;
compptr->v_samp_factor = 1;
}

View File

@@ -1,75 +0,0 @@
/*
* jcexpand.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains image edge-expansion routines.
* These routines are invoked via the edge_expand method.
*/
#include "jinclude.h"
/*
* Expand an image so that it is a multiple of the MCU dimensions.
* This is to be accomplished by duplicating the rightmost column
* and/or bottommost row of pixels. The image has not yet been
* downsampled, so all components have the same dimensions.
*/
METHODDEF void
edge_expand (compress_info_ptr cinfo,
long input_cols, int input_rows,
long output_cols, int output_rows,
JSAMPIMAGE image_data)
{
/* Expand horizontally */
if (input_cols < output_cols) {
register JSAMPROW ptr;
register JSAMPLE pixval;
register long count;
register int row;
short ci;
long numcols = output_cols - input_cols;
for (ci = 0; ci < cinfo->num_components; ci++) {
for (row = 0; row < input_rows; row++) {
ptr = image_data[ci][row] + (input_cols-1);
pixval = GETJSAMPLE(*ptr++);
for (count = numcols; count > 0; count--)
*ptr++ = pixval;
}
}
}
/* Expand vertically */
/* This happens only once at the bottom of the image, */
/* so it needn't be super-efficient */
if (input_rows < output_rows) {
register int row;
short ci;
JSAMPARRAY this_component;
for (ci = 0; ci < cinfo->num_components; ci++) {
this_component = image_data[ci];
for (row = input_rows; row < output_rows; row++) {
jcopy_sample_rows(this_component, input_rows-1, this_component, row,
1, output_cols);
}
}
}
}
/*
* The method selection routine for edge expansion.
*/
GLOBAL void
jselexpand (compress_info_ptr cinfo)
{
/* just one implementation for now */
cinfo->methods->edge_expand = edge_expand;
}

1156
jchuff.c

File diff suppressed because it is too large Load Diff

47
jchuff.h Normal file
View File

@@ -0,0 +1,47 @@
/*
* jchuff.h
*
* Copyright (C) 1991-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains declarations for Huffman entropy encoding routines
* that are shared between the sequential encoder (jchuff.c) and the
* progressive encoder (jcphuff.c). No other modules need to see these.
*/
/* The legal range of a DCT coefficient is
* -1024 .. +1023 for 8-bit data;
* -16384 .. +16383 for 12-bit data.
* Hence the magnitude should always fit in 10 or 14 bits respectively.
*/
#if BITS_IN_JSAMPLE == 8
#define MAX_COEF_BITS 10
#else
#define MAX_COEF_BITS 14
#endif
/* Derived data constructed for each Huffman table */
typedef struct {
unsigned int ehufco[256]; /* code for each symbol */
char ehufsi[256]; /* length of code for each symbol */
/* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */
} c_derived_tbl;
/* Short forms of external names for systems with brain-damaged linkers. */
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define jpeg_make_c_derived_tbl jMkCDerived
#define jpeg_gen_optimal_table jGenOptTbl
#endif /* NEED_SHORT_EXTERNAL_NAMES */
/* Expand a Huffman table definition into the derived format */
EXTERN(void) jpeg_make_c_derived_tbl
JPP((j_compress_ptr cinfo, boolean isDC, int tblno,
c_derived_tbl ** pdtbl));
/* Generate an optimal table definition given the specified counts */
EXTERN(void) jpeg_gen_optimal_table
JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]));

72
jcinit.c Normal file
View File

@@ -0,0 +1,72 @@
/*
* jcinit.c
*
* Copyright (C) 1991-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains initialization logic for the JPEG compressor.
* This routine is in charge of selecting the modules to be executed and
* making an initialization call to each one.
*
* Logically, this code belongs in jcmaster.c. It's split out because
* linking this routine implies linking the entire compression library.
* For a transcoding-only application, we want to be able to use jcmaster.c
* without linking in the whole library.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* Master selection of compression modules.
* This is done once at the start of processing an image. We determine
* which modules will be used and give them appropriate initialization calls.
*/
GLOBAL(void)
jinit_compress_master (j_compress_ptr cinfo)
{
/* Initialize master control (includes parameter checking/processing) */
jinit_c_master_control(cinfo, FALSE /* full compression */);
/* Preprocessing */
if (! cinfo->raw_data_in) {
jinit_color_converter(cinfo);
jinit_downsampler(cinfo);
jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */);
}
/* Forward DCT */
jinit_forward_dct(cinfo);
/* Entropy encoding: either Huffman or arithmetic coding. */
if (cinfo->arith_code) {
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
} else {
if (cinfo->progressive_mode) {
#ifdef C_PROGRESSIVE_SUPPORTED
jinit_phuff_encoder(cinfo);
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
} else
jinit_huff_encoder(cinfo);
}
/* Need a full-image coefficient buffer in any multi-pass mode. */
jinit_c_coef_controller(cinfo,
(boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding));
jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);
jinit_marker_writer(cinfo);
/* We can now tell the memory manager to allocate virtual arrays. */
(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
/* Write the datastream header (SOI) immediately.
* Frame and scan headers are postponed till later.
* This lets application insert special markers after the SOI.
*/
(*cinfo->marker->write_file_header) (cinfo);
}

733
jcmain.c
View File

@@ -1,733 +0,0 @@
/*
* jcmain.c
*
* Copyright (C) 1991, 1992, 1993, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains a command-line user interface for the JPEG compressor.
* It should work on any system with Unix- or MS-DOS-style command lines.
*
* Two different command line styles are permitted, depending on the
* compile-time switch TWO_FILE_COMMANDLINE:
* cjpeg [options] inputfile outputfile
* cjpeg [options] [inputfile]
* In the second style, output is always to standard output, which you'd
* normally redirect to a file or pipe to some other program. Input is
* either from a named file or from standard input (typically redirected).
* The second style is convenient on Unix but is unhelpful on systems that
* don't support pipes. Also, you MUST use the first style if your system
* doesn't do binary I/O to stdin/stdout.
* To simplify script writing, the "-outfile" switch is provided. The syntax
* cjpeg [options] -outfile outputfile inputfile
* works regardless of which command line style is used.
*/
#include "jinclude.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare exit() */
#endif
#include <ctype.h> /* to declare isupper(), tolower() */
#ifdef NEED_SIGNAL_CATCHER
#include <signal.h> /* to declare signal() */
#endif
#ifdef USE_SETMODE
#include <fcntl.h> /* to declare setmode() */
#endif
#ifdef THINK_C
#include <console.h> /* command-line reader for Macintosh */
#endif
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
#define READ_BINARY "r"
#define WRITE_BINARY "w"
#else
#define READ_BINARY "rb"
#define WRITE_BINARY "wb"
#endif
#ifndef EXIT_FAILURE /* define exit() codes if not provided */
#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
#ifdef VMS
#define EXIT_SUCCESS 1 /* VMS is very nonstandard */
#else
#define EXIT_SUCCESS 0
#endif
#endif
#include "jversion.h" /* for version message */
/*
* This routine determines what format the input file is,
* and selects the appropriate input-reading module.
*
* To determine which family of input formats the file belongs to,
* we may look only at the first byte of the file, since C does not
* guarantee that more than one character can be pushed back with ungetc.
* Looking at additional bytes would require one of these approaches:
* 1) assume we can fseek() the input file (fails for piped input);
* 2) assume we can push back more than one character (works in
* some C implementations, but unportable);
* 3) provide our own buffering as is done in djpeg (breaks input readers
* that want to use stdio directly, such as the RLE library);
* or 4) don't put back the data, and modify the input_init methods to assume
* they start reading after the start of file (also breaks RLE library).
* #1 is attractive for MS-DOS but is untenable on Unix.
*
* The most portable solution for file types that can't be identified by their
* first byte is to make the user tell us what they are. This is also the
* only approach for "raw" file types that contain only arbitrary values.
* We presently apply this method for Targa files. Most of the time Targa
* files start with 0x00, so we recognize that case. Potentially, however,
* a Targa file could start with any byte value (byte 0 is the length of the
* seldom-used ID field), so we provide a switch to force Targa input mode.
*/
static boolean is_targa; /* records user -targa switch */
LOCAL void
select_file_type (compress_info_ptr cinfo)
{
int c;
if (is_targa) {
#ifdef TARGA_SUPPORTED
jselrtarga(cinfo);
#else
ERREXIT(cinfo->emethods, "Targa support was not compiled");
#endif
return;
}
if ((c = getc(cinfo->input_file)) == EOF)
ERREXIT(cinfo->emethods, "Empty input file");
switch (c) {
#ifdef GIF_SUPPORTED
case 'G':
jselrgif(cinfo);
break;
#endif
#ifdef PPM_SUPPORTED
case 'P':
jselrppm(cinfo);
break;
#endif
#ifdef RLE_SUPPORTED
case 'R':
jselrrle(cinfo);
break;
#endif
#ifdef TARGA_SUPPORTED
case 0x00:
jselrtarga(cinfo);
break;
#endif
default:
#ifdef TARGA_SUPPORTED
ERREXIT(cinfo->emethods, "Unrecognized input file format --- perhaps you need -targa");
#else
ERREXIT(cinfo->emethods, "Unrecognized input file format");
#endif
break;
}
if (ungetc(c, cinfo->input_file) == EOF)
ERREXIT(cinfo->emethods, "ungetc failed");
}
/*
* This routine gets control after the input file header has been read.
* It must determine what output JPEG file format is to be written,
* and make any other compression parameter changes that are desirable.
*/
METHODDEF void
c_ui_method_selection (compress_info_ptr cinfo)
{
/* If the input is gray scale, generate a monochrome JPEG file. */
if (cinfo->in_color_space == CS_GRAYSCALE)
j_monochrome_default(cinfo);
/* For now, always select JFIF output format. */
#ifdef JFIF_SUPPORTED
jselwjfif(cinfo);
#else
You shoulda defined JFIF_SUPPORTED. /* deliberate syntax error */
#endif
}
/*
* Signal catcher to ensure that temporary files are removed before aborting.
* NB: for Amiga Manx C this is actually a global routine named _abort();
* see -Dsignal_catcher=_abort in CFLAGS. Talk about bogus...
*/
#ifdef NEED_SIGNAL_CATCHER
static external_methods_ptr emethods; /* for access to free_all */
GLOBAL void
signal_catcher (int signum)
{
if (emethods != NULL) {
emethods->trace_level = 0; /* turn off trace output */
(*emethods->free_all) (); /* clean up memory allocation & temp files */
}
exit(EXIT_FAILURE);
}
#endif
/*
* Optional routine to display a percent-done figure on stderr.
* See jcdeflts.c for explanation of the information used.
*/
#ifdef PROGRESS_REPORT
METHODDEF void
progress_monitor (compress_info_ptr cinfo, long loopcounter, long looplimit)
{
if (cinfo->total_passes > 1) {
fprintf(stderr, "\rPass %d/%d: %3d%% ",
cinfo->completed_passes+1, cinfo->total_passes,
(int) (loopcounter*100L/looplimit));
} else {
fprintf(stderr, "\r %3d%% ",
(int) (loopcounter*100L/looplimit));
}
fflush(stderr);
}
#endif
/*
* Argument-parsing code.
* The switch parser is designed to be useful with DOS-style command line
* syntax, ie, intermixed switches and file names, where only the switches
* to the left of a given file name affect processing of that file.
* The main program in this file doesn't actually use this capability...
*/
static char * progname; /* program name for error messages */
static char * outfilename; /* for -outfile switch */
LOCAL void
usage (void)
/* complain about bad command line */
{
fprintf(stderr, "usage: %s [switches] ", progname);
#ifdef TWO_FILE_COMMANDLINE
fprintf(stderr, "inputfile outputfile\n");
#else
fprintf(stderr, "[inputfile]\n");
#endif
fprintf(stderr, "Switches (names may be abbreviated):\n");
fprintf(stderr, " -quality N Compression quality (0..100; 5-95 is useful range)\n");
fprintf(stderr, " -grayscale Create monochrome JPEG file\n");
#ifdef ENTROPY_OPT_SUPPORTED
fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
#endif
#ifdef TARGA_SUPPORTED
fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n");
#endif
fprintf(stderr, "Switches for advanced users:\n");
fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
#ifdef INPUT_SMOOTHING_SUPPORTED
fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n");
#endif
fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
fprintf(stderr, " -verbose or -debug Emit debug output\n");
fprintf(stderr, "Switches for wizards:\n");
#ifdef C_ARITH_CODING_SUPPORTED
fprintf(stderr, " -arithmetic Use arithmetic coding\n");
#endif
#ifdef C_MULTISCAN_FILES_SUPPORTED
fprintf(stderr, " -nointerleave Create noninterleaved JPEG file\n");
#endif
fprintf(stderr, " -qtables file Use quantization tables given in file\n");
fprintf(stderr, " -sample HxV[,...] Set JPEG sampling factors\n");
exit(EXIT_FAILURE);
}
LOCAL boolean
keymatch (char * arg, const char * keyword, int minchars)
/* Case-insensitive matching of (possibly abbreviated) keyword switches. */
/* keyword is the constant keyword (must be lower case already), */
/* minchars is length of minimum legal abbreviation. */
{
register int ca, ck;
register int nmatched = 0;
while ((ca = *arg++) != '\0') {
if ((ck = *keyword++) == '\0')
return FALSE; /* arg longer than keyword, no good */
if (isupper(ca)) /* force arg to lcase (assume ck is already) */
ca = tolower(ca);
if (ca != ck)
return FALSE; /* no good */
nmatched++; /* count matched characters */
}
/* reached end of argument; fail if it's too short for unique abbrev */
if (nmatched < minchars)
return FALSE;
return TRUE; /* A-OK */
}
LOCAL int
qt_getc (FILE * file)
/* Read next char, skipping over any comments (# to end of line) */
/* A comment/newline sequence is returned as a newline */
{
register int ch;
ch = getc(file);
if (ch == '#') {
do {
ch = getc(file);
} while (ch != '\n' && ch != EOF);
}
return ch;
}
LOCAL long
read_qt_integer (FILE * file)
/* Read an unsigned decimal integer from a quantization-table file */
/* Swallows one trailing character after the integer */
{
register int ch;
register long val;
/* Skip any leading whitespace, detect EOF */
do {
ch = qt_getc(file);
if (ch == EOF)
return EOF;
} while (isspace(ch));
if (! isdigit(ch)) {
fprintf(stderr, "%s: bogus data in quantization file\n", progname);
exit(EXIT_FAILURE);
}
val = ch - '0';
while (ch = qt_getc(file), isdigit(ch)) {
val *= 10;
val += ch - '0';
}
return val;
}
LOCAL void
read_quant_tables (compress_info_ptr cinfo, char * filename, int scale_factor)
/* Read a set of quantization tables from the specified file.
* The file is plain ASCII text: decimal numbers with whitespace between.
* Comments preceded by '#' may be included in the file.
* There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
* The tables are implicitly numbered 0,1,etc.
*/
{
/* ZIG[i] is the zigzag-order position of the i'th element of a DCT block */
/* read in natural order (left to right, top to bottom). */
static const short ZIG[DCTSIZE2] = {
0, 1, 5, 6, 14, 15, 27, 28,
2, 4, 7, 13, 16, 26, 29, 42,
3, 8, 12, 17, 25, 30, 41, 43,
9, 11, 18, 24, 31, 40, 44, 53,
10, 19, 23, 32, 39, 45, 52, 54,
20, 22, 33, 38, 46, 51, 55, 60,
21, 34, 37, 47, 50, 56, 59, 61,
35, 36, 48, 49, 57, 58, 62, 63
};
FILE * fp;
int tblno, i;
long val;
QUANT_TBL table;
if ((fp = fopen(filename, "r")) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, filename);
exit(EXIT_FAILURE);
}
tblno = 0;
while ((val = read_qt_integer(fp)) != EOF) { /* read 1st element of table */
if (tblno >= NUM_QUANT_TBLS) {
fprintf(stderr, "%s: too many tables in file %s\n", progname, filename);
exit(EXIT_FAILURE);
}
table[0] = (QUANT_VAL) val;
for (i = 1; i < DCTSIZE2; i++) {
if ((val = read_qt_integer(fp)) == EOF) {
fprintf(stderr, "%s: incomplete table in file %s\n", progname, filename);
exit(EXIT_FAILURE);
}
table[ZIG[i]] = (QUANT_VAL) val;
}
j_add_quant_table(cinfo, tblno, table, scale_factor, FALSE);
tblno++;
}
fclose(fp);
}
LOCAL void
set_sample_factors (compress_info_ptr cinfo, char *arg)
/* Process a sample-factors parameter string, of the form */
/* HxV[,HxV,...] */
{
#define MAX_COMPONENTS 4 /* # of comp_info slots made by jcdeflts.c */
int ci, val1, val2;
char ch1, ch2;
for (ci = 0; ci < MAX_COMPONENTS; ci++) {
if (*arg) {
ch2 = ','; /* if not set by sscanf, will be ',' */
if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
usage();
if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',')
usage(); /* syntax check */
if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) {
fprintf(stderr, "JPEG sampling factors must be 1..4\n");
exit(EXIT_FAILURE);
}
cinfo->comp_info[ci].h_samp_factor = val1;
cinfo->comp_info[ci].v_samp_factor = val2;
while (*arg && *arg++ != ',') /* advance to next segment of arg string */
;
} else {
/* reached end of parameter, set remaining components to 1x1 sampling */
cinfo->comp_info[ci].h_samp_factor = 1;
cinfo->comp_info[ci].v_samp_factor = 1;
}
}
}
LOCAL int
parse_switches (compress_info_ptr cinfo, int last_file_arg_seen,
int argc, char **argv)
/* Initialize cinfo with default switch settings, then parse option switches.
* Returns argv[] index of first file-name argument (== argc if none).
* Any file names with indexes <= last_file_arg_seen are ignored;
* they have presumably been processed in a previous iteration.
* (Pass 0 for last_file_arg_seen on the first or only iteration.)
*/
{
int argn;
char * arg;
char * qtablefile = NULL; /* saves -qtables filename if any */
int q_scale_factor = 100; /* default to no scaling for -qtables */
/* (Re-)initialize the system-dependent error and memory managers. */
jselerror(cinfo->emethods); /* error/trace message routines */
jselmemmgr(cinfo->emethods); /* memory allocation routines */
cinfo->methods->c_ui_method_selection = c_ui_method_selection;
/* Now OK to enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
emethods = cinfo->emethods;
#endif
/* Set up default JPEG parameters. */
/* Note that default -quality level here need not, and does not,
* match the default scaling for an explicit -qtables argument.
*/
j_c_defaults(cinfo, 75, FALSE); /* default quality level = 75 */
is_targa = FALSE;
outfilename = NULL;
/* Scan command line options, adjust parameters */
for (argn = 1; argn < argc; argn++) {
arg = argv[argn];
if (*arg != '-') {
/* Not a switch, must be a file name argument */
if (argn <= last_file_arg_seen) {
outfilename = NULL; /* -outfile applies to just one input file */
continue; /* ignore this name if previously processed */
}
break; /* else done parsing switches */
}
arg++; /* advance past switch marker character */
if (keymatch(arg, "arithmetic", 1)) {
/* Use arithmetic coding. */
#ifdef C_ARITH_CODING_SUPPORTED
cinfo->arith_code = TRUE;
#else
fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
progname);
exit(EXIT_FAILURE);
#endif
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
/* Enable debug printouts. */
/* On first -d, print version identification */
if (last_file_arg_seen == 0 && cinfo->emethods->trace_level == 0)
fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
JVERSION, JCOPYRIGHT);
cinfo->emethods->trace_level++;
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
/* Force a monochrome JPEG file to be generated. */
j_monochrome_default(cinfo);
} else if (keymatch(arg, "maxmemory", 1)) {
/* Maximum memory in Kb (or Mb with 'm'). */
long lval;
char ch = 'x';
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
usage();
if (ch == 'm' || ch == 'M')
lval *= 1000L;
cinfo->emethods->max_memory_to_use = lval * 1000L;
} else if (keymatch(arg, "nointerleave", 3)) {
/* Create noninterleaved file. */
#ifdef C_MULTISCAN_FILES_SUPPORTED
cinfo->interleave = FALSE;
#else
fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n",
progname);
exit(EXIT_FAILURE);
#endif
} else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
/* Enable entropy parm optimization. */
#ifdef ENTROPY_OPT_SUPPORTED
cinfo->optimize_coding = TRUE;
#else
fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
progname);
exit(EXIT_FAILURE);
#endif
} else if (keymatch(arg, "outfile", 3)) {
/* Set output file name. */
if (++argn >= argc) /* advance to next argument */
usage();
outfilename = argv[argn]; /* save it away for later use */
} else if (keymatch(arg, "quality", 1)) {
/* Quality factor (quantization table scaling factor). */
int val;
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%d", &val) != 1)
usage();
/* Set quantization tables (will be overridden if -qtables also given).
* Note: we make force_baseline FALSE.
* This means non-baseline JPEG files can be created with low Q values.
* To ensure only baseline files are generated, pass TRUE instead.
*/
j_set_quality(cinfo, val, FALSE);
/* Change scale factor in case -qtables is present. */
q_scale_factor = j_quality_scaling(val);
} else if (keymatch(arg, "qtables", 2)) {
/* Quantization tables fetched from file. */
if (++argn >= argc) /* advance to next argument */
usage();
qtablefile = argv[argn];
/* we postpone actually reading the file in case -quality comes later */
} else if (keymatch(arg, "restart", 1)) {
/* Restart interval in MCU rows (or in MCUs with 'b'). */
long lval;
char ch = 'x';
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
usage();
if (lval < 0 || lval > 65535L)
usage();
if (ch == 'b' || ch == 'B')
cinfo->restart_interval = (UINT16) lval;
else
cinfo->restart_in_rows = (int) lval;
} else if (keymatch(arg, "sample", 2)) {
/* Set sampling factors. */
if (++argn >= argc) /* advance to next argument */
usage();
set_sample_factors(cinfo, argv[argn]);
} else if (keymatch(arg, "smooth", 2)) {
/* Set input smoothing factor. */
int val;
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%d", &val) != 1)
usage();
if (val < 0 || val > 100)
usage();
cinfo->smoothing_factor = val;
} else if (keymatch(arg, "targa", 1)) {
/* Input file is Targa format. */
is_targa = TRUE;
} else {
usage(); /* bogus switch */
}
}
/* Post-switch-scanning cleanup */
if (qtablefile != NULL) /* process -qtables if it was present */
read_quant_tables(cinfo, qtablefile, q_scale_factor);
return argn; /* return index of next arg (file name) */
}
/*
* The main program.
*/
GLOBAL int
main (int argc, char **argv)
{
struct Compress_info_struct cinfo;
struct Compress_methods_struct c_methods;
struct External_methods_struct e_methods;
int file_index;
/* On Mac, fetch a command line. */
#ifdef THINK_C
argc = ccommand(&argv);
#endif
progname = argv[0];
/* Set up links to method structures. */
cinfo.methods = &c_methods;
cinfo.emethods = &e_methods;
/* Install, but don't yet enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
emethods = NULL;
signal(SIGINT, signal_catcher);
#ifdef SIGTERM /* not all systems have SIGTERM */
signal(SIGTERM, signal_catcher);
#endif
#endif
/* Scan command line: set up compression parameters, find file names. */
file_index = parse_switches(&cinfo, 0, argc, argv);
#ifdef TWO_FILE_COMMANDLINE
/* Must have either -outfile switch or explicit output file name */
if (outfilename == NULL) {
if (file_index != argc-2) {
fprintf(stderr, "%s: must name one input and one output file\n",
progname);
usage();
}
outfilename = argv[file_index+1];
} else {
if (file_index != argc-1) {
fprintf(stderr, "%s: must name one input and one output file\n",
progname);
usage();
}
}
#else
/* Unix style: expect zero or one file name */
if (file_index < argc-1) {
fprintf(stderr, "%s: only one input file\n", progname);
usage();
}
#endif /* TWO_FILE_COMMANDLINE */
/* Open the input file. */
if (file_index < argc) {
if ((cinfo.input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
exit(EXIT_FAILURE);
}
} else {
/* default input file is stdin */
#ifdef USE_SETMODE /* need to hack file mode? */
setmode(fileno(stdin), O_BINARY);
#endif
#ifdef USE_FDOPEN /* need to re-open in binary mode? */
if ((cinfo.input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open stdin\n", progname);
exit(EXIT_FAILURE);
}
#else
cinfo.input_file = stdin;
#endif
}
/* Open the output file. */
if (outfilename != NULL) {
if ((cinfo.output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
exit(EXIT_FAILURE);
}
} else {
/* default output file is stdout */
#ifdef USE_SETMODE /* need to hack file mode? */
setmode(fileno(stdout), O_BINARY);
#endif
#ifdef USE_FDOPEN /* need to re-open in binary mode? */
if ((cinfo.output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open stdout\n", progname);
exit(EXIT_FAILURE);
}
#else
cinfo.output_file = stdout;
#endif
}
/* Figure out the input file format, and set up to read it. */
select_file_type(&cinfo);
#ifdef PROGRESS_REPORT
/* Start up progress display, unless trace output is on */
if (e_methods.trace_level == 0)
c_methods.progress_monitor = progress_monitor;
#endif
/* Do it to it! */
jpeg_compress(&cinfo);
#ifdef PROGRESS_REPORT
/* Clear away progress display */
if (e_methods.trace_level == 0) {
fprintf(stderr, "\r \r");
fflush(stderr);
}
#endif
/* All done. */
exit(EXIT_SUCCESS);
return 0; /* suppress no-return-value warnings */
}

293
jcmainct.c Normal file
View File

@@ -0,0 +1,293 @@
/*
* jcmainct.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the main buffer controller for compression.
* The main buffer lies between the pre-processor and the JPEG
* compressor proper; it holds downsampled data in the JPEG colorspace.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Note: currently, there is no operating mode in which a full-image buffer
* is needed at this step. If there were, that mode could not be used with
* "raw data" input, since this module is bypassed in that case. However,
* we've left the code here for possible use in special applications.
*/
#undef FULL_MAIN_BUFFER_SUPPORTED
/* Private buffer controller object */
typedef struct {
struct jpeg_c_main_controller pub; /* public fields */
JDIMENSION cur_iMCU_row; /* number of current iMCU row */
JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */
boolean suspended; /* remember if we suspended output */
J_BUF_MODE pass_mode; /* current operating mode */
/* If using just a strip buffer, this points to the entire set of buffers
* (we allocate one for each component). In the full-image case, this
* points to the currently accessible strips of the virtual arrays.
*/
JSAMPARRAY buffer[MAX_COMPONENTS];
#ifdef FULL_MAIN_BUFFER_SUPPORTED
/* If using full-image storage, this array holds pointers to virtual-array
* control blocks for each component. Unused if not full-image storage.
*/
jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
#endif
} my_main_controller;
typedef my_main_controller * my_main_ptr;
/* Forward declarations */
METHODDEF(void) process_data_simple_main
JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
#ifdef FULL_MAIN_BUFFER_SUPPORTED
METHODDEF(void) process_data_buffer_main
JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
#endif
/*
* Initialize for a processing pass.
*/
METHODDEF(void)
start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
my_main_ptr main = (my_main_ptr) cinfo->main;
/* Do nothing in raw-data mode. */
if (cinfo->raw_data_in)
return;
main->cur_iMCU_row = 0; /* initialize counters */
main->rowgroup_ctr = 0;
main->suspended = FALSE;
main->pass_mode = pass_mode; /* save mode for use by process_data */
switch (pass_mode) {
case JBUF_PASS_THRU:
#ifdef FULL_MAIN_BUFFER_SUPPORTED
if (main->whole_image[0] != NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
#endif
main->pub.process_data = process_data_simple_main;
break;
#ifdef FULL_MAIN_BUFFER_SUPPORTED
case JBUF_SAVE_SOURCE:
case JBUF_CRANK_DEST:
case JBUF_SAVE_AND_PASS:
if (main->whole_image[0] == NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
main->pub.process_data = process_data_buffer_main;
break;
#endif
default:
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
break;
}
}
/*
* Process some data.
* This routine handles the simple pass-through mode,
* where we have only a strip buffer.
*/
METHODDEF(void)
process_data_simple_main (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
JDIMENSION in_rows_avail)
{
my_main_ptr main = (my_main_ptr) cinfo->main;
while (main->cur_iMCU_row < cinfo->total_iMCU_rows) {
/* Read input data if we haven't filled the main buffer yet */
if (main->rowgroup_ctr < DCTSIZE)
(*cinfo->prep->pre_process_data) (cinfo,
input_buf, in_row_ctr, in_rows_avail,
main->buffer, &main->rowgroup_ctr,
(JDIMENSION) DCTSIZE);
/* If we don't have a full iMCU row buffered, return to application for
* more data. Note that preprocessor will always pad to fill the iMCU row
* at the bottom of the image.
*/
if (main->rowgroup_ctr != DCTSIZE)
return;
/* Send the completed row to the compressor */
if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) {
/* If compressor did not consume the whole row, then we must need to
* suspend processing and return to the application. In this situation
* we pretend we didn't yet consume the last input row; otherwise, if
* it happened to be the last row of the image, the application would
* think we were done.
*/
if (! main->suspended) {
(*in_row_ctr)--;
main->suspended = TRUE;
}
return;
}
/* We did finish the row. Undo our little suspension hack if a previous
* call suspended; then mark the main buffer empty.
*/
if (main->suspended) {
(*in_row_ctr)++;
main->suspended = FALSE;
}
main->rowgroup_ctr = 0;
main->cur_iMCU_row++;
}
}
#ifdef FULL_MAIN_BUFFER_SUPPORTED
/*
* Process some data.
* This routine handles all of the modes that use a full-size buffer.
*/
METHODDEF(void)
process_data_buffer_main (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
JDIMENSION in_rows_avail)
{
my_main_ptr main = (my_main_ptr) cinfo->main;
int ci;
jpeg_component_info *compptr;
boolean writing = (main->pass_mode != JBUF_CRANK_DEST);
while (main->cur_iMCU_row < cinfo->total_iMCU_rows) {
/* Realign the virtual buffers if at the start of an iMCU row. */
if (main->rowgroup_ctr == 0) {
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
main->buffer[ci] = (*cinfo->mem->access_virt_sarray)
((j_common_ptr) cinfo, main->whole_image[ci],
main->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE),
(JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing);
}
/* In a read pass, pretend we just read some source data. */
if (! writing) {
*in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE;
main->rowgroup_ctr = DCTSIZE;
}
}
/* If a write pass, read input data until the current iMCU row is full. */
/* Note: preprocessor will pad if necessary to fill the last iMCU row. */
if (writing) {
(*cinfo->prep->pre_process_data) (cinfo,
input_buf, in_row_ctr, in_rows_avail,
main->buffer, &main->rowgroup_ctr,
(JDIMENSION) DCTSIZE);
/* Return to application if we need more data to fill the iMCU row. */
if (main->rowgroup_ctr < DCTSIZE)
return;
}
/* Emit data, unless this is a sink-only pass. */
if (main->pass_mode != JBUF_SAVE_SOURCE) {
if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) {
/* If compressor did not consume the whole row, then we must need to
* suspend processing and return to the application. In this situation
* we pretend we didn't yet consume the last input row; otherwise, if
* it happened to be the last row of the image, the application would
* think we were done.
*/
if (! main->suspended) {
(*in_row_ctr)--;
main->suspended = TRUE;
}
return;
}
/* We did finish the row. Undo our little suspension hack if a previous
* call suspended; then mark the main buffer empty.
*/
if (main->suspended) {
(*in_row_ctr)++;
main->suspended = FALSE;
}
}
/* If get here, we are done with this iMCU row. Mark buffer empty. */
main->rowgroup_ctr = 0;
main->cur_iMCU_row++;
}
}
#endif /* FULL_MAIN_BUFFER_SUPPORTED */
/*
* Initialize main buffer controller.
*/
GLOBAL(void)
jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
{
my_main_ptr main;
int ci;
jpeg_component_info *compptr;
main = (my_main_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_main_controller));
cinfo->main = (struct jpeg_c_main_controller *) main;
main->pub.start_pass = start_pass_main;
/* We don't need to create a buffer in raw-data mode. */
if (cinfo->raw_data_in)
return;
/* Create the buffer. It holds downsampled data, so each component
* may be of a different size.
*/
if (need_full_buffer) {
#ifdef FULL_MAIN_BUFFER_SUPPORTED
/* Allocate a full-image virtual array for each component */
/* Note we pad the bottom to a multiple of the iMCU height */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
main->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
compptr->width_in_blocks * DCTSIZE,
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
(long) compptr->v_samp_factor) * DCTSIZE,
(JDIMENSION) (compptr->v_samp_factor * DCTSIZE));
}
#else
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
#endif
} else {
#ifdef FULL_MAIN_BUFFER_SUPPORTED
main->whole_image[0] = NULL; /* flag for no virtual arrays */
#endif
/* Allocate a strip buffer for each component */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
main->buffer[ci] = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
compptr->width_in_blocks * DCTSIZE,
(JDIMENSION) (compptr->v_samp_factor * DCTSIZE));
}
}
}

664
jcmarker.c Normal file
View File

@@ -0,0 +1,664 @@
/*
* jcmarker.c
*
* Copyright (C) 1991-1998, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains routines to write JPEG datastream markers.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
typedef enum { /* JPEG marker codes */
M_SOF0 = 0xc0,
M_SOF1 = 0xc1,
M_SOF2 = 0xc2,
M_SOF3 = 0xc3,
M_SOF5 = 0xc5,
M_SOF6 = 0xc6,
M_SOF7 = 0xc7,
M_JPG = 0xc8,
M_SOF9 = 0xc9,
M_SOF10 = 0xca,
M_SOF11 = 0xcb,
M_SOF13 = 0xcd,
M_SOF14 = 0xce,
M_SOF15 = 0xcf,
M_DHT = 0xc4,
M_DAC = 0xcc,
M_RST0 = 0xd0,
M_RST1 = 0xd1,
M_RST2 = 0xd2,
M_RST3 = 0xd3,
M_RST4 = 0xd4,
M_RST5 = 0xd5,
M_RST6 = 0xd6,
M_RST7 = 0xd7,
M_SOI = 0xd8,
M_EOI = 0xd9,
M_SOS = 0xda,
M_DQT = 0xdb,
M_DNL = 0xdc,
M_DRI = 0xdd,
M_DHP = 0xde,
M_EXP = 0xdf,
M_APP0 = 0xe0,
M_APP1 = 0xe1,
M_APP2 = 0xe2,
M_APP3 = 0xe3,
M_APP4 = 0xe4,
M_APP5 = 0xe5,
M_APP6 = 0xe6,
M_APP7 = 0xe7,
M_APP8 = 0xe8,
M_APP9 = 0xe9,
M_APP10 = 0xea,
M_APP11 = 0xeb,
M_APP12 = 0xec,
M_APP13 = 0xed,
M_APP14 = 0xee,
M_APP15 = 0xef,
M_JPG0 = 0xf0,
M_JPG13 = 0xfd,
M_COM = 0xfe,
M_TEM = 0x01,
M_ERROR = 0x100
} JPEG_MARKER;
/* Private state */
typedef struct {
struct jpeg_marker_writer pub; /* public fields */
unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */
} my_marker_writer;
typedef my_marker_writer * my_marker_ptr;
/*
* Basic output routines.
*
* Note that we do not support suspension while writing a marker.
* Therefore, an application using suspension must ensure that there is
* enough buffer space for the initial markers (typ. 600-700 bytes) before
* calling jpeg_start_compress, and enough space to write the trailing EOI
* (a few bytes) before calling jpeg_finish_compress. Multipass compression
* modes are not supported at all with suspension, so those two are the only
* points where markers will be written.
*/
LOCAL(void)
emit_byte (j_compress_ptr cinfo, int val)
/* Emit a byte */
{
struct jpeg_destination_mgr * dest = cinfo->dest;
*(dest->next_output_byte)++ = (JOCTET) val;
if (--dest->free_in_buffer == 0) {
if (! (*dest->empty_output_buffer) (cinfo))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
}
}
LOCAL(void)
emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark)
/* Emit a marker code */
{
emit_byte(cinfo, 0xFF);
emit_byte(cinfo, (int) mark);
}
LOCAL(void)
emit_2bytes (j_compress_ptr cinfo, int value)
/* Emit a 2-byte integer; these are always MSB first in JPEG files */
{
emit_byte(cinfo, (value >> 8) & 0xFF);
emit_byte(cinfo, value & 0xFF);
}
/*
* Routines to write specific marker types.
*/
LOCAL(int)
emit_dqt (j_compress_ptr cinfo, int index)
/* Emit a DQT marker */
/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
{
JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index];
int prec;
int i;
if (qtbl == NULL)
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index);
prec = 0;
for (i = 0; i < DCTSIZE2; i++) {
if (qtbl->quantval[i] > 255)
prec = 1;
}
if (! qtbl->sent_table) {
emit_marker(cinfo, M_DQT);
emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2);
emit_byte(cinfo, index + (prec<<4));
for (i = 0; i < DCTSIZE2; i++) {
/* The table entries must be emitted in zigzag order. */
unsigned int qval = qtbl->quantval[jpeg_natural_order[i]];
if (prec)
emit_byte(cinfo, (int) (qval >> 8));
emit_byte(cinfo, (int) (qval & 0xFF));
}
qtbl->sent_table = TRUE;
}
return prec;
}
LOCAL(void)
emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
/* Emit a DHT marker */
{
JHUFF_TBL * htbl;
int length, i;
if (is_ac) {
htbl = cinfo->ac_huff_tbl_ptrs[index];
index += 0x10; /* output index has AC bit set */
} else {
htbl = cinfo->dc_huff_tbl_ptrs[index];
}
if (htbl == NULL)
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index);
if (! htbl->sent_table) {
emit_marker(cinfo, M_DHT);
length = 0;
for (i = 1; i <= 16; i++)
length += htbl->bits[i];
emit_2bytes(cinfo, length + 2 + 1 + 16);
emit_byte(cinfo, index);
for (i = 1; i <= 16; i++)
emit_byte(cinfo, htbl->bits[i]);
for (i = 0; i < length; i++)
emit_byte(cinfo, htbl->huffval[i]);
htbl->sent_table = TRUE;
}
}
LOCAL(void)
emit_dac (j_compress_ptr cinfo)
/* Emit a DAC marker */
/* Since the useful info is so small, we want to emit all the tables in */
/* one DAC marker. Therefore this routine does its own scan of the table. */
{
#ifdef C_ARITH_CODING_SUPPORTED
char dc_in_use[NUM_ARITH_TBLS];
char ac_in_use[NUM_ARITH_TBLS];
int length, i;
jpeg_component_info *compptr;
for (i = 0; i < NUM_ARITH_TBLS; i++)
dc_in_use[i] = ac_in_use[i] = 0;
for (i = 0; i < cinfo->comps_in_scan; i++) {
compptr = cinfo->cur_comp_info[i];
dc_in_use[compptr->dc_tbl_no] = 1;
ac_in_use[compptr->ac_tbl_no] = 1;
}
length = 0;
for (i = 0; i < NUM_ARITH_TBLS; i++)
length += dc_in_use[i] + ac_in_use[i];
emit_marker(cinfo, M_DAC);
emit_2bytes(cinfo, length*2 + 2);
for (i = 0; i < NUM_ARITH_TBLS; i++) {
if (dc_in_use[i]) {
emit_byte(cinfo, i);
emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4));
}
if (ac_in_use[i]) {
emit_byte(cinfo, i + 0x10);
emit_byte(cinfo, cinfo->arith_ac_K[i]);
}
}
#endif /* C_ARITH_CODING_SUPPORTED */
}
LOCAL(void)
emit_dri (j_compress_ptr cinfo)
/* Emit a DRI marker */
{
emit_marker(cinfo, M_DRI);
emit_2bytes(cinfo, 4); /* fixed length */
emit_2bytes(cinfo, (int) cinfo->restart_interval);
}
LOCAL(void)
emit_sof (j_compress_ptr cinfo, JPEG_MARKER code)
/* Emit a SOF marker */
{
int ci;
jpeg_component_info *compptr;
emit_marker(cinfo, code);
emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */
/* Make sure image isn't bigger than SOF field can handle */
if ((long) cinfo->image_height > 65535L ||
(long) cinfo->image_width > 65535L)
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535);
emit_byte(cinfo, cinfo->data_precision);
emit_2bytes(cinfo, (int) cinfo->image_height);
emit_2bytes(cinfo, (int) cinfo->image_width);
emit_byte(cinfo, cinfo->num_components);
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
emit_byte(cinfo, compptr->component_id);
emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor);
emit_byte(cinfo, compptr->quant_tbl_no);
}
}
LOCAL(void)
emit_sos (j_compress_ptr cinfo)
/* Emit a SOS marker */
{
int i, td, ta;
jpeg_component_info *compptr;
emit_marker(cinfo, M_SOS);
emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */
emit_byte(cinfo, cinfo->comps_in_scan);
for (i = 0; i < cinfo->comps_in_scan; i++) {
compptr = cinfo->cur_comp_info[i];
emit_byte(cinfo, compptr->component_id);
td = compptr->dc_tbl_no;
ta = compptr->ac_tbl_no;
if (cinfo->progressive_mode) {
/* Progressive mode: only DC or only AC tables are used in one scan;
* furthermore, Huffman coding of DC refinement uses no table at all.
* We emit 0 for unused field(s); this is recommended by the P&M text
* but does not seem to be specified in the standard.
*/
if (cinfo->Ss == 0) {
ta = 0; /* DC scan */
if (cinfo->Ah != 0 && !cinfo->arith_code)
td = 0; /* no DC table either */
} else {
td = 0; /* AC scan */
}
}
emit_byte(cinfo, (td << 4) + ta);
}
emit_byte(cinfo, cinfo->Ss);
emit_byte(cinfo, cinfo->Se);
emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al);
}
LOCAL(void)
emit_jfif_app0 (j_compress_ptr cinfo)
/* Emit a JFIF-compliant APP0 marker */
{
/*
* Length of APP0 block (2 bytes)
* Block ID (4 bytes - ASCII "JFIF")
* Zero byte (1 byte to terminate the ID string)
* Version Major, Minor (2 bytes - major first)
* Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm)
* Xdpu (2 bytes - dots per unit horizontal)
* Ydpu (2 bytes - dots per unit vertical)
* Thumbnail X size (1 byte)
* Thumbnail Y size (1 byte)
*/
emit_marker(cinfo, M_APP0);
emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */
emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */
emit_byte(cinfo, 0x46);
emit_byte(cinfo, 0x49);
emit_byte(cinfo, 0x46);
emit_byte(cinfo, 0);
emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */
emit_byte(cinfo, cinfo->JFIF_minor_version);
emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */
emit_2bytes(cinfo, (int) cinfo->X_density);
emit_2bytes(cinfo, (int) cinfo->Y_density);
emit_byte(cinfo, 0); /* No thumbnail image */
emit_byte(cinfo, 0);
}
LOCAL(void)
emit_adobe_app14 (j_compress_ptr cinfo)
/* Emit an Adobe APP14 marker */
{
/*
* Length of APP14 block (2 bytes)
* Block ID (5 bytes - ASCII "Adobe")
* Version Number (2 bytes - currently 100)
* Flags0 (2 bytes - currently 0)
* Flags1 (2 bytes - currently 0)
* Color transform (1 byte)
*
* Although Adobe TN 5116 mentions Version = 101, all the Adobe files
* now in circulation seem to use Version = 100, so that's what we write.
*
* We write the color transform byte as 1 if the JPEG color space is
* YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with
* whether the encoder performed a transformation, which is pretty useless.
*/
emit_marker(cinfo, M_APP14);
emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */
emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */
emit_byte(cinfo, 0x64);
emit_byte(cinfo, 0x6F);
emit_byte(cinfo, 0x62);
emit_byte(cinfo, 0x65);
emit_2bytes(cinfo, 100); /* Version */
emit_2bytes(cinfo, 0); /* Flags0 */
emit_2bytes(cinfo, 0); /* Flags1 */
switch (cinfo->jpeg_color_space) {
case JCS_YCbCr:
emit_byte(cinfo, 1); /* Color transform = 1 */
break;
case JCS_YCCK:
emit_byte(cinfo, 2); /* Color transform = 2 */
break;
default:
emit_byte(cinfo, 0); /* Color transform = 0 */
break;
}
}
/*
* These routines allow writing an arbitrary marker with parameters.
* The only intended use is to emit COM or APPn markers after calling
* write_file_header and before calling write_frame_header.
* Other uses are not guaranteed to produce desirable results.
* Counting the parameter bytes properly is the caller's responsibility.
*/
METHODDEF(void)
write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
/* Emit an arbitrary marker header */
{
if (datalen > (unsigned int) 65533) /* safety check */
ERREXIT(cinfo, JERR_BAD_LENGTH);
emit_marker(cinfo, (JPEG_MARKER) marker);
emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */
}
METHODDEF(void)
write_marker_byte (j_compress_ptr cinfo, int val)
/* Emit one byte of marker parameters following write_marker_header */
{
emit_byte(cinfo, val);
}
/*
* Write datastream header.
* This consists of an SOI and optional APPn markers.
* We recommend use of the JFIF marker, but not the Adobe marker,
* when using YCbCr or grayscale data. The JFIF marker should NOT
* be used for any other JPEG colorspace. The Adobe marker is helpful
* to distinguish RGB, CMYK, and YCCK colorspaces.
* Note that an application can write additional header markers after
* jpeg_start_compress returns.
*/
METHODDEF(void)
write_file_header (j_compress_ptr cinfo)
{
my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
emit_marker(cinfo, M_SOI); /* first the SOI */
/* SOI is defined to reset restart interval to 0 */
marker->last_restart_interval = 0;
if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */
emit_jfif_app0(cinfo);
if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */
emit_adobe_app14(cinfo);
}
/*
* Write frame header.
* This consists of DQT and SOFn markers.
* Note that we do not emit the SOF until we have emitted the DQT(s).
* This avoids compatibility problems with incorrect implementations that
* try to error-check the quant table numbers as soon as they see the SOF.
*/
METHODDEF(void)
write_frame_header (j_compress_ptr cinfo)
{
int ci, prec;
boolean is_baseline;
jpeg_component_info *compptr;
/* Emit DQT for each quantization table.
* Note that emit_dqt() suppresses any duplicate tables.
*/
prec = 0;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
prec += emit_dqt(cinfo, compptr->quant_tbl_no);
}
/* now prec is nonzero iff there are any 16-bit quant tables. */
/* Check for a non-baseline specification.
* Note we assume that Huffman table numbers won't be changed later.
*/
if (cinfo->arith_code || cinfo->progressive_mode ||
cinfo->data_precision != 8) {
is_baseline = FALSE;
} else {
is_baseline = TRUE;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1)
is_baseline = FALSE;
}
if (prec && is_baseline) {
is_baseline = FALSE;
/* If it's baseline except for quantizer size, warn the user */
TRACEMS(cinfo, 0, JTRC_16BIT_TABLES);
}
}
/* Emit the proper SOF marker */
if (cinfo->arith_code) {
emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */
} else {
if (cinfo->progressive_mode)
emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */
else if (is_baseline)
emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */
else
emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */
}
}
/*
* Write scan header.
* This consists of DHT or DAC markers, optional DRI, and SOS.
* Compressed data will be written following the SOS.
*/
METHODDEF(void)
write_scan_header (j_compress_ptr cinfo)
{
my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
int i;
jpeg_component_info *compptr;
if (cinfo->arith_code) {
/* Emit arith conditioning info. We may have some duplication
* if the file has multiple scans, but it's so small it's hardly
* worth worrying about.
*/
emit_dac(cinfo);
} else {
/* Emit Huffman tables.
* Note that emit_dht() suppresses any duplicate tables.
*/
for (i = 0; i < cinfo->comps_in_scan; i++) {
compptr = cinfo->cur_comp_info[i];
if (cinfo->progressive_mode) {
/* Progressive mode: only DC or only AC tables are used in one scan */
if (cinfo->Ss == 0) {
if (cinfo->Ah == 0) /* DC needs no table for refinement scan */
emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
} else {
emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
}
} else {
/* Sequential mode: need both DC and AC tables */
emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
}
}
}
/* Emit DRI if required --- note that DRI value could change for each scan.
* We avoid wasting space with unnecessary DRIs, however.
*/
if (cinfo->restart_interval != marker->last_restart_interval) {
emit_dri(cinfo);
marker->last_restart_interval = cinfo->restart_interval;
}
emit_sos(cinfo);
}
/*
* Write datastream trailer.
*/
METHODDEF(void)
write_file_trailer (j_compress_ptr cinfo)
{
emit_marker(cinfo, M_EOI);
}
/*
* Write an abbreviated table-specification datastream.
* This consists of SOI, DQT and DHT tables, and EOI.
* Any table that is defined and not marked sent_table = TRUE will be
* emitted. Note that all tables will be marked sent_table = TRUE at exit.
*/
METHODDEF(void)
write_tables_only (j_compress_ptr cinfo)
{
int i;
emit_marker(cinfo, M_SOI);
for (i = 0; i < NUM_QUANT_TBLS; i++) {
if (cinfo->quant_tbl_ptrs[i] != NULL)
(void) emit_dqt(cinfo, i);
}
if (! cinfo->arith_code) {
for (i = 0; i < NUM_HUFF_TBLS; i++) {
if (cinfo->dc_huff_tbl_ptrs[i] != NULL)
emit_dht(cinfo, i, FALSE);
if (cinfo->ac_huff_tbl_ptrs[i] != NULL)
emit_dht(cinfo, i, TRUE);
}
}
emit_marker(cinfo, M_EOI);
}
/*
* Initialize the marker writer module.
*/
GLOBAL(void)
jinit_marker_writer (j_compress_ptr cinfo)
{
my_marker_ptr marker;
/* Create the subobject */
marker = (my_marker_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_marker_writer));
cinfo->marker = (struct jpeg_marker_writer *) marker;
/* Initialize method pointers */
marker->pub.write_file_header = write_file_header;
marker->pub.write_frame_header = write_frame_header;
marker->pub.write_scan_header = write_scan_header;
marker->pub.write_file_trailer = write_file_trailer;
marker->pub.write_tables_only = write_tables_only;
marker->pub.write_marker_header = write_marker_header;
marker->pub.write_marker_byte = write_marker_byte;
/* Initialize private state */
marker->last_restart_interval = 0;
}

View File

@@ -1,133 +1,590 @@
/*
* jcmaster.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the main control for the JPEG compressor.
* The system-dependent (user interface) code should call jpeg_compress()
* after doing appropriate setup of the compress_info_struct parameter.
* This file contains master control logic for the JPEG compressor.
* These routines are concerned with parameter validation, initial setup,
* and inter-pass control (determining the number of passes and the work
* to be done in each pass).
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
METHODDEF void
c_per_scan_method_selection (compress_info_ptr cinfo)
/* Central point for per-scan method selection */
/* Private state */
typedef enum {
main_pass, /* input data, also do first output step */
huff_opt_pass, /* Huffman code optimization pass */
output_pass /* data output pass */
} c_pass_type;
typedef struct {
struct jpeg_comp_master pub; /* public fields */
c_pass_type pass_type; /* the type of the current pass */
int pass_number; /* # of passes completed */
int total_passes; /* total # of passes needed */
int scan_number; /* current index in scan_info[] */
} my_comp_master;
typedef my_comp_master * my_master_ptr;
/*
* Support routines that do various essential calculations.
*/
LOCAL(void)
initial_setup (j_compress_ptr cinfo)
/* Do computations that are needed before master selection phase */
{
/* Edge expansion */
jselexpand(cinfo);
/* Downsampling of pixels */
jseldownsample(cinfo);
/* MCU extraction */
jselcmcu(cinfo);
}
LOCAL void
c_initial_method_selection (compress_info_ptr cinfo)
/* Central point for initial method selection */
{
/* Input image reading method selection is already done. */
/* So is output file header formatting (both are done by user interface). */
/* Gamma and color space conversion */
jselccolor(cinfo);
/* Entropy encoding: either Huffman or arithmetic coding. */
#ifdef C_ARITH_CODING_SUPPORTED
jselcarithmetic(cinfo);
#else
cinfo->arith_code = FALSE; /* force Huffman mode */
#endif
jselchuffman(cinfo);
/* Pipeline control */
jselcpipeline(cinfo);
/* Overall control (that's me!) */
cinfo->methods->c_per_scan_method_selection = c_per_scan_method_selection;
}
LOCAL void
initial_setup (compress_info_ptr cinfo)
/* Do computations that are needed before initial method selection */
{
short ci;
int ci;
jpeg_component_info *compptr;
long samplesperrow;
JDIMENSION jd_samplesperrow;
/* Sanity check on image dimensions */
if (cinfo->image_height <= 0 || cinfo->image_width <= 0
|| cinfo->num_components <= 0 || cinfo->input_components <= 0)
ERREXIT(cinfo, JERR_EMPTY_IMAGE);
/* Make sure image isn't bigger than I can handle */
if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
(long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
/* Width of an input scanline must be representable as JDIMENSION. */
samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components;
jd_samplesperrow = (JDIMENSION) samplesperrow;
if ((long) jd_samplesperrow != samplesperrow)
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
/* For now, precision must match compiled-in value... */
if (cinfo->data_precision != BITS_IN_JSAMPLE)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
/* Check that number of components won't exceed internal array sizes */
if (cinfo->num_components > MAX_COMPONENTS)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
MAX_COMPONENTS);
/* Compute maximum sampling factors; check factor validity */
cinfo->max_h_samp_factor = 1;
cinfo->max_v_samp_factor = 1;
for (ci = 0; ci < cinfo->num_components; ci++) {
compptr = &cinfo->comp_info[ci];
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
ERREXIT(cinfo->emethods, "Bogus sampling factors");
ERREXIT(cinfo, JERR_BAD_SAMPLING);
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
compptr->h_samp_factor);
cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
compptr->v_samp_factor);
}
/* Compute dimensions of components */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Fill in the correct component_index value; don't rely on application */
compptr->component_index = ci;
/* For compression, we never do DCT scaling. */
compptr->DCT_scaled_size = DCTSIZE;
/* Size in DCT blocks */
compptr->width_in_blocks = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
(long) (cinfo->max_h_samp_factor * DCTSIZE));
compptr->height_in_blocks = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
(long) (cinfo->max_v_samp_factor * DCTSIZE));
/* Size in samples */
compptr->downsampled_width = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
(long) cinfo->max_h_samp_factor);
compptr->downsampled_height = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
(long) cinfo->max_v_samp_factor);
/* Mark component needed (this flag isn't actually used for compression) */
compptr->component_needed = TRUE;
}
/* Compute number of fully interleaved MCU rows (number of times that
* main controller will call coefficient controller).
*/
cinfo->total_iMCU_rows = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height,
(long) (cinfo->max_v_samp_factor*DCTSIZE));
}
#ifdef C_MULTISCAN_FILES_SUPPORTED
LOCAL(void)
validate_script (j_compress_ptr cinfo)
/* Verify that the scan script in cinfo->scan_info[] is valid; also
* determine whether it uses progressive JPEG, and set cinfo->progressive_mode.
*/
{
const jpeg_scan_info * scanptr;
int scanno, ncomps, ci, coefi, thisi;
int Ss, Se, Ah, Al;
boolean component_sent[MAX_COMPONENTS];
#ifdef C_PROGRESSIVE_SUPPORTED
int * last_bitpos_ptr;
int last_bitpos[MAX_COMPONENTS][DCTSIZE2];
/* -1 until that coefficient has been seen; then last Al for it */
#endif
if (cinfo->num_scans <= 0)
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0);
/* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
* for progressive JPEG, no scan can have this.
*/
scanptr = cinfo->scan_info;
if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) {
#ifdef C_PROGRESSIVE_SUPPORTED
cinfo->progressive_mode = TRUE;
last_bitpos_ptr = & last_bitpos[0][0];
for (ci = 0; ci < cinfo->num_components; ci++)
for (coefi = 0; coefi < DCTSIZE2; coefi++)
*last_bitpos_ptr++ = -1;
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
} else {
cinfo->progressive_mode = FALSE;
for (ci = 0; ci < cinfo->num_components; ci++)
component_sent[ci] = FALSE;
}
for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) {
/* Validate component indexes */
ncomps = scanptr->comps_in_scan;
if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN);
for (ci = 0; ci < ncomps; ci++) {
thisi = scanptr->component_index[ci];
if (thisi < 0 || thisi >= cinfo->num_components)
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
/* Components must appear in SOF order within each scan */
if (ci > 0 && thisi <= scanptr->component_index[ci-1])
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
}
/* Validate progression parameters */
Ss = scanptr->Ss;
Se = scanptr->Se;
Ah = scanptr->Ah;
Al = scanptr->Al;
if (cinfo->progressive_mode) {
#ifdef C_PROGRESSIVE_SUPPORTED
/* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that
* seems wrong: the upper bound ought to depend on data precision.
* Perhaps they really meant 0..N+1 for N-bit precision.
* Here we allow 0..10 for 8-bit data; Al larger than 10 results in
* out-of-range reconstructed DC values during the first DC scan,
* which might cause problems for some decoders.
*/
#if BITS_IN_JSAMPLE == 8
#define MAX_AH_AL 10
#else
#define MAX_AH_AL 13
#endif
if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 ||
Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
if (Ss == 0) {
if (Se != 0) /* DC and AC together not OK */
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
} else {
if (ncomps != 1) /* AC scans must be for only one component */
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
}
for (ci = 0; ci < ncomps; ci++) {
last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0];
if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
for (coefi = Ss; coefi <= Se; coefi++) {
if (last_bitpos_ptr[coefi] < 0) {
/* first scan of this coefficient */
if (Ah != 0)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
} else {
/* not first scan */
if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
}
last_bitpos_ptr[coefi] = Al;
}
}
#endif
} else {
/* For sequential JPEG, all progression parameters must be these: */
if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
/* Make sure components are not sent twice */
for (ci = 0; ci < ncomps; ci++) {
thisi = scanptr->component_index[ci];
if (component_sent[thisi])
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
component_sent[thisi] = TRUE;
}
}
}
/* Now verify that everything got sent. */
if (cinfo->progressive_mode) {
#ifdef C_PROGRESSIVE_SUPPORTED
/* For progressive mode, we only check that at least some DC data
* got sent for each component; the spec does not require that all bits
* of all coefficients be transmitted. Would it be wiser to enforce
* transmission of all coefficient bits??
*/
for (ci = 0; ci < cinfo->num_components; ci++) {
if (last_bitpos[ci][0] < 0)
ERREXIT(cinfo, JERR_MISSING_DATA);
}
#endif
} else {
for (ci = 0; ci < cinfo->num_components; ci++) {
if (! component_sent[ci])
ERREXIT(cinfo, JERR_MISSING_DATA);
}
}
}
#endif /* C_MULTISCAN_FILES_SUPPORTED */
LOCAL(void)
select_scan_parameters (j_compress_ptr cinfo)
/* Set up the scan parameters for the current scan */
{
int ci;
#ifdef C_MULTISCAN_FILES_SUPPORTED
if (cinfo->scan_info != NULL) {
/* Prepare for current scan --- the script is already validated */
my_master_ptr master = (my_master_ptr) cinfo->master;
const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number;
cinfo->comps_in_scan = scanptr->comps_in_scan;
for (ci = 0; ci < scanptr->comps_in_scan; ci++) {
cinfo->cur_comp_info[ci] =
&cinfo->comp_info[scanptr->component_index[ci]];
}
cinfo->Ss = scanptr->Ss;
cinfo->Se = scanptr->Se;
cinfo->Ah = scanptr->Ah;
cinfo->Al = scanptr->Al;
}
else
#endif
{
/* Prepare for single sequential-JPEG scan containing all components */
if (cinfo->num_components > MAX_COMPS_IN_SCAN)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
MAX_COMPS_IN_SCAN);
cinfo->comps_in_scan = cinfo->num_components;
for (ci = 0; ci < cinfo->num_components; ci++) {
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
}
cinfo->Ss = 0;
cinfo->Se = DCTSIZE2-1;
cinfo->Ah = 0;
cinfo->Al = 0;
}
}
LOCAL(void)
per_scan_setup (j_compress_ptr cinfo)
/* Do computations that are needed before processing a JPEG scan */
/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */
{
int ci, mcublks, tmp;
jpeg_component_info *compptr;
if (cinfo->comps_in_scan == 1) {
/* Noninterleaved (single-component) scan */
compptr = cinfo->cur_comp_info[0];
/* Overall image size in MCUs */
cinfo->MCUs_per_row = compptr->width_in_blocks;
cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
/* For noninterleaved scan, always one block per MCU */
compptr->MCU_width = 1;
compptr->MCU_height = 1;
compptr->MCU_blocks = 1;
compptr->MCU_sample_width = DCTSIZE;
compptr->last_col_width = 1;
/* For noninterleaved scans, it is convenient to define last_row_height
* as the number of block rows present in the last iMCU row.
*/
tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
if (tmp == 0) tmp = compptr->v_samp_factor;
compptr->last_row_height = tmp;
/* Prepare array describing MCU composition */
cinfo->blocks_in_MCU = 1;
cinfo->MCU_membership[0] = 0;
} else {
/* Interleaved (multi-component) scan */
if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
MAX_COMPS_IN_SCAN);
/* Overall image size in MCUs */
cinfo->MCUs_per_row = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width,
(long) (cinfo->max_h_samp_factor*DCTSIZE));
cinfo->MCU_rows_in_scan = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height,
(long) (cinfo->max_v_samp_factor*DCTSIZE));
cinfo->blocks_in_MCU = 0;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* Sampling factors give # of blocks of component in each MCU */
compptr->MCU_width = compptr->h_samp_factor;
compptr->MCU_height = compptr->v_samp_factor;
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE;
/* Figure number of non-dummy blocks in last MCU column & row */
tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
if (tmp == 0) tmp = compptr->MCU_width;
compptr->last_col_width = tmp;
tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
if (tmp == 0) tmp = compptr->MCU_height;
compptr->last_row_height = tmp;
/* Prepare array describing MCU composition */
mcublks = compptr->MCU_blocks;
if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU)
ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
while (mcublks-- > 0) {
cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
}
}
}
/* Compute logical downsampled dimensions of components */
for (ci = 0; ci < cinfo->num_components; ci++) {
compptr = &cinfo->comp_info[ci];
compptr->true_comp_width = (cinfo->image_width * compptr->h_samp_factor
+ cinfo->max_h_samp_factor - 1)
/ cinfo->max_h_samp_factor;
compptr->true_comp_height = (cinfo->image_height * compptr->v_samp_factor
+ cinfo->max_v_samp_factor - 1)
/ cinfo->max_v_samp_factor;
/* Convert restart specified in rows to actual MCU count. */
/* Note that count must fit in 16 bits, so we provide limiting. */
if (cinfo->restart_in_rows > 0) {
long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row;
cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L);
}
}
/*
* This is the main entry point to the JPEG compressor.
* Per-pass setup.
* This is called at the beginning of each pass. We determine which modules
* will be active during this pass and give them appropriate start_pass calls.
* We also set is_last_pass to indicate whether any more passes will be
* required.
*/
GLOBAL void
jpeg_compress (compress_info_ptr cinfo)
METHODDEF(void)
prepare_for_pass (j_compress_ptr cinfo)
{
/* Init pass counts to 0 --- total_passes is adjusted in method selection */
cinfo->total_passes = 0;
cinfo->completed_passes = 0;
my_master_ptr master = (my_master_ptr) cinfo->master;
/* Read the input file header: determine image size & component count.
* NOTE: the user interface must have initialized the input_init method
* pointer (eg, by calling jselrppm) before calling me.
* The other file reading methods (get_input_row etc.) were probably
* set at the same time, but could be set up by input_init itself,
* or by c_ui_method_selection.
switch (master->pass_type) {
case main_pass:
/* Initial pass: will collect input data, and do either Huffman
* optimization or data output for the first scan.
*/
(*cinfo->methods->input_init) (cinfo);
/* Give UI a chance to adjust compression parameters and select */
/* output file format based on results of input_init. */
(*cinfo->methods->c_ui_method_selection) (cinfo);
/* Now select methods for compression steps. */
initial_setup(cinfo);
c_initial_method_selection(cinfo);
/* Initialize the output file & other modules as needed */
/* (entropy_encoder is inited by pipeline controller) */
(*cinfo->methods->colorin_init) (cinfo);
(*cinfo->methods->write_file_header) (cinfo);
/* And let the pipeline controller do the rest. */
(*cinfo->methods->c_pipeline_controller) (cinfo);
/* Finish output file, release working storage, etc */
(*cinfo->methods->write_file_trailer) (cinfo);
(*cinfo->methods->colorin_term) (cinfo);
(*cinfo->methods->input_term) (cinfo);
(*cinfo->emethods->free_all) ();
/* My, that was easy, wasn't it? */
select_scan_parameters(cinfo);
per_scan_setup(cinfo);
if (! cinfo->raw_data_in) {
(*cinfo->cconvert->start_pass) (cinfo);
(*cinfo->downsample->start_pass) (cinfo);
(*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU);
}
(*cinfo->fdct->start_pass) (cinfo);
(*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding);
(*cinfo->coef->start_pass) (cinfo,
(master->total_passes > 1 ?
JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
(*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
if (cinfo->optimize_coding) {
/* No immediate data output; postpone writing frame/scan headers */
master->pub.call_pass_startup = FALSE;
} else {
/* Will write frame/scan headers at first jpeg_write_scanlines call */
master->pub.call_pass_startup = TRUE;
}
break;
#ifdef ENTROPY_OPT_SUPPORTED
case huff_opt_pass:
/* Do Huffman optimization for a scan after the first one. */
select_scan_parameters(cinfo);
per_scan_setup(cinfo);
if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) {
(*cinfo->entropy->start_pass) (cinfo, TRUE);
(*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
master->pub.call_pass_startup = FALSE;
break;
}
/* Special case: Huffman DC refinement scans need no Huffman table
* and therefore we can skip the optimization pass for them.
*/
master->pass_type = output_pass;
master->pass_number++;
/*FALLTHROUGH*/
#endif
case output_pass:
/* Do a data-output pass. */
/* We need not repeat per-scan setup if prior optimization pass did it. */
if (! cinfo->optimize_coding) {
select_scan_parameters(cinfo);
per_scan_setup(cinfo);
}
(*cinfo->entropy->start_pass) (cinfo, FALSE);
(*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
/* We emit frame/scan headers now */
if (master->scan_number == 0)
(*cinfo->marker->write_frame_header) (cinfo);
(*cinfo->marker->write_scan_header) (cinfo);
master->pub.call_pass_startup = FALSE;
break;
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
}
master->pub.is_last_pass = (master->pass_number == master->total_passes-1);
/* Set up progress monitor's pass info if present */
if (cinfo->progress != NULL) {
cinfo->progress->completed_passes = master->pass_number;
cinfo->progress->total_passes = master->total_passes;
}
}
/*
* Special start-of-pass hook.
* This is called by jpeg_write_scanlines if call_pass_startup is TRUE.
* In single-pass processing, we need this hook because we don't want to
* write frame/scan headers during jpeg_start_compress; we want to let the
* application write COM markers etc. between jpeg_start_compress and the
* jpeg_write_scanlines loop.
* In multi-pass processing, this routine is not used.
*/
METHODDEF(void)
pass_startup (j_compress_ptr cinfo)
{
cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */
(*cinfo->marker->write_frame_header) (cinfo);
(*cinfo->marker->write_scan_header) (cinfo);
}
/*
* Finish up at end of pass.
*/
METHODDEF(void)
finish_pass_master (j_compress_ptr cinfo)
{
my_master_ptr master = (my_master_ptr) cinfo->master;
/* The entropy coder always needs an end-of-pass call,
* either to analyze statistics or to flush its output buffer.
*/
(*cinfo->entropy->finish_pass) (cinfo);
/* Update state for next pass */
switch (master->pass_type) {
case main_pass:
/* next pass is either output of scan 0 (after optimization)
* or output of scan 1 (if no optimization).
*/
master->pass_type = output_pass;
if (! cinfo->optimize_coding)
master->scan_number++;
break;
case huff_opt_pass:
/* next pass is always output of current scan */
master->pass_type = output_pass;
break;
case output_pass:
/* next pass is either optimization or output of next scan */
if (cinfo->optimize_coding)
master->pass_type = huff_opt_pass;
master->scan_number++;
break;
}
master->pass_number++;
}
/*
* Initialize master compression control.
*/
GLOBAL(void)
jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
{
my_master_ptr master;
master = (my_master_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_comp_master));
cinfo->master = (struct jpeg_comp_master *) master;
master->pub.prepare_for_pass = prepare_for_pass;
master->pub.pass_startup = pass_startup;
master->pub.finish_pass = finish_pass_master;
master->pub.is_last_pass = FALSE;
/* Validate parameters, determine derived values */
initial_setup(cinfo);
if (cinfo->scan_info != NULL) {
#ifdef C_MULTISCAN_FILES_SUPPORTED
validate_script(cinfo);
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
} else {
cinfo->progressive_mode = FALSE;
cinfo->num_scans = 1;
}
if (cinfo->progressive_mode) /* TEMPORARY HACK ??? */
cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */
/* Initialize my private state */
if (transcode_only) {
/* no main pass in transcoding */
if (cinfo->optimize_coding)
master->pass_type = huff_opt_pass;
else
master->pass_type = output_pass;
} else {
/* for normal compression, first pass is always this type: */
master->pass_type = main_pass;
}
master->scan_number = 0;
master->pass_number = 0;
if (cinfo->optimize_coding)
master->total_passes = cinfo->num_scans * 2;
else
master->total_passes = cinfo->num_scans;
}

228
jcmcu.c
View File

@@ -1,228 +0,0 @@
/*
* jcmcu.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains MCU extraction routines and quantization scaling.
* These routines are invoked via the extract_MCUs and
* extract_init/term methods.
*/
#include "jinclude.h"
/*
* If this file is compiled with -DDCT_ERR_STATS, it will reverse-DCT each
* block and sum the total errors across the whole picture. This provides
* a convenient method of using real picture data to test the roundoff error
* of a DCT algorithm. DCT_ERR_STATS should *not* be defined for a production
* compression program, since compression is much slower with it defined.
* Also note that jrevdct.o must be linked into the compressor when this
* switch is defined.
*/
#ifdef DCT_ERR_STATS
static int dcterrorsum; /* these hold the error statistics */
static int dcterrormax;
static int dctcoefcount; /* This will probably overflow on a 16-bit-int machine */
#endif
/* ZAG[i] is the natural-order position of the i'th element of zigzag order. */
static const int ZAG[DCTSIZE2] = {
0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34,
27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36,
29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46,
53, 60, 61, 54, 47, 55, 62, 63
};
LOCAL void
extract_block (JSAMPARRAY input_data, int start_row, long start_col,
JBLOCK output_data, QUANT_TBL_PTR quanttbl)
/* Extract one 8x8 block from the specified location in the sample array; */
/* perform forward DCT, quantization scaling, and zigzag reordering on it. */
{
/* This routine is heavily used, so it's worth coding it tightly. */
DCTBLOCK block;
#ifdef DCT_ERR_STATS
DCTBLOCK svblock; /* saves input data for comparison */
#endif
{ register JSAMPROW elemptr;
register DCTELEM *localblkptr = block;
register int elemr;
for (elemr = DCTSIZE; elemr > 0; elemr--) {
elemptr = input_data[start_row++] + start_col;
#if DCTSIZE == 8 /* unroll the inner loop */
*localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
#else
{ register int elemc;
for (elemc = DCTSIZE; elemc > 0; elemc--) {
*localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
}
}
#endif
}
}
#ifdef DCT_ERR_STATS
MEMCOPY(svblock, block, SIZEOF(DCTBLOCK));
#endif
j_fwd_dct(block);
{ register JCOEF temp;
register QUANT_VAL qval;
register int i;
for (i = 0; i < DCTSIZE2; i++) {
qval = *quanttbl++;
temp = (JCOEF) block[ZAG[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) (a >= b) ? (a /= b) : (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_data++ = temp;
}
}
#ifdef DCT_ERR_STATS
j_rev_dct(block);
{ register int diff;
register int i;
for (i = 0; i < DCTSIZE2; i++) {
diff = block[i] - svblock[i];
if (diff < 0) diff = -diff;
dcterrorsum += diff;
if (dcterrormax < diff) dcterrormax = diff;
}
dctcoefcount += DCTSIZE2;
}
#endif
}
/*
* Extract samples in MCU order, process & hand off to output_method.
* The input is always exactly N MCU rows worth of data.
*/
METHODDEF void
extract_MCUs (compress_info_ptr cinfo,
JSAMPIMAGE image_data,
int num_mcu_rows,
MCU_output_method_ptr output_method)
{
JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
int mcurow;
long mcuindex;
short blkn, ci, xpos, ypos;
jpeg_component_info * compptr;
QUANT_TBL_PTR quant_ptr;
for (mcurow = 0; mcurow < num_mcu_rows; mcurow++) {
for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
/* Extract data from the image array, DCT it, and quantize it */
blkn = 0;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
quant_ptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
for (ypos = 0; ypos < compptr->MCU_height; ypos++) {
for (xpos = 0; xpos < compptr->MCU_width; xpos++) {
extract_block(image_data[ci],
(mcurow * compptr->MCU_height + ypos)*DCTSIZE,
(mcuindex * compptr->MCU_width + xpos)*DCTSIZE,
MCU_data[blkn], quant_ptr);
blkn++;
}
}
}
/* Send the MCU whereever the pipeline controller wants it to go */
(*output_method) (cinfo, MCU_data);
}
}
}
/*
* Initialize for processing a scan.
*/
METHODDEF void
extract_init (compress_info_ptr cinfo)
{
/* no work for now */
#ifdef DCT_ERR_STATS
dcterrorsum = dcterrormax = dctcoefcount = 0;
#endif
}
/*
* Clean up after a scan.
*/
METHODDEF void
extract_term (compress_info_ptr cinfo)
{
/* no work for now */
#ifdef DCT_ERR_STATS
TRACEMS3(cinfo->emethods, 0, "DCT roundoff errors = %d/%d, max = %d",
dcterrorsum, dctcoefcount, dcterrormax);
#endif
}
/*
* The method selection routine for MCU extraction.
*/
GLOBAL void
jselcmcu (compress_info_ptr cinfo)
{
/* just one implementation for now */
cinfo->methods->extract_init = extract_init;
cinfo->methods->extract_MCUs = extract_MCUs;
cinfo->methods->extract_term = extract_term;
}

106
jcomapi.c Normal file
View File

@@ -0,0 +1,106 @@
/*
* jcomapi.c
*
* Copyright (C) 1994-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains application interface routines that are used for both
* compression and decompression.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* Abort processing of a JPEG compression or decompression operation,
* but don't destroy the object itself.
*
* For this, we merely clean up all the nonpermanent memory pools.
* Note that temp files (virtual arrays) are not allowed to belong to
* the permanent pool, so we will be able to close all temp files here.
* Closing a data source or destination, if necessary, is the application's
* responsibility.
*/
GLOBAL(void)
jpeg_abort (j_common_ptr cinfo)
{
int pool;
/* Do nothing if called on a not-initialized or destroyed JPEG object. */
if (cinfo->mem == NULL)
return;
/* Releasing pools in reverse order might help avoid fragmentation
* with some (brain-damaged) malloc libraries.
*/
for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) {
(*cinfo->mem->free_pool) (cinfo, pool);
}
/* Reset overall state for possible reuse of object */
if (cinfo->is_decompressor) {
cinfo->global_state = DSTATE_START;
/* Try to keep application from accessing now-deleted marker list.
* A bit kludgy to do it here, but this is the most central place.
*/
((j_decompress_ptr) cinfo)->marker_list = NULL;
} else {
cinfo->global_state = CSTATE_START;
}
}
/*
* Destruction of a JPEG object.
*
* Everything gets deallocated except the master jpeg_compress_struct itself
* and the error manager struct. Both of these are supplied by the application
* and must be freed, if necessary, by the application. (Often they are on
* the stack and so don't need to be freed anyway.)
* Closing a data source or destination, if necessary, is the application's
* responsibility.
*/
GLOBAL(void)
jpeg_destroy (j_common_ptr cinfo)
{
/* We need only tell the memory manager to release everything. */
/* NB: mem pointer is NULL if memory mgr failed to initialize. */
if (cinfo->mem != NULL)
(*cinfo->mem->self_destruct) (cinfo);
cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */
cinfo->global_state = 0; /* mark it destroyed */
}
/*
* Convenience routines for allocating quantization and Huffman tables.
* (Would jutils.c be a more reasonable place to put these?)
*/
GLOBAL(JQUANT_TBL *)
jpeg_alloc_quant_table (j_common_ptr cinfo)
{
JQUANT_TBL *tbl;
tbl = (JQUANT_TBL *)
(*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL));
tbl->sent_table = FALSE; /* make sure this is false in any new table */
return tbl;
}
GLOBAL(JHUFF_TBL *)
jpeg_alloc_huff_table (j_common_ptr cinfo)
{
JHUFF_TBL *tbl;
tbl = (JHUFF_TBL *)
(*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL));
tbl->sent_table = FALSE; /* make sure this is false in any new table */
return tbl;
}

155
jconfig.doc Normal file
View File

@@ -0,0 +1,155 @@
/*
* jconfig.doc
*
* Copyright (C) 1991-1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file documents the configuration options that are required to
* customize the JPEG software for a particular system.
*
* The actual configuration options for a particular installation are stored
* in jconfig.h. On many machines, jconfig.h can be generated automatically
* or copied from one of the "canned" jconfig files that we supply. But if
* you need to generate a jconfig.h file by hand, this file tells you how.
*
* DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING.
* EDIT A COPY NAMED JCONFIG.H.
*/
/*
* These symbols indicate the properties of your machine or compiler.
* #define the symbol if yes, #undef it if no.
*/
/* Does your compiler support function prototypes?
* (If not, you also need to use ansi2knr, see install.doc)
*/
#define HAVE_PROTOTYPES
/* Does your compiler support the declaration "unsigned char" ?
* How about "unsigned short" ?
*/
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
/* Define "void" as "char" if your compiler doesn't know about type void.
* NOTE: be sure to define void such that "void *" represents the most general
* pointer type, e.g., that returned by malloc().
*/
/* #define void char */
/* Define "const" as empty if your compiler doesn't know the "const" keyword.
*/
/* #define const */
/* Define this if an ordinary "char" type is unsigned.
* If you're not sure, leaving it undefined will work at some cost in speed.
* If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal.
*/
#undef CHAR_IS_UNSIGNED
/* Define this if your system has an ANSI-conforming <stddef.h> file.
*/
#define HAVE_STDDEF_H
/* Define this if your system has an ANSI-conforming <stdlib.h> file.
*/
#define HAVE_STDLIB_H
/* Define this if your system does not have an ANSI/SysV <string.h>,
* but does have a BSD-style <strings.h>.
*/
#undef NEED_BSD_STRINGS
/* Define this if your system does not provide typedef size_t in any of the
* ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in
* <sys/types.h> instead.
*/
#undef NEED_SYS_TYPES_H
/* For 80x86 machines, you need to define NEED_FAR_POINTERS,
* unless you are using a large-data memory model or 80386 flat-memory mode.
* On less brain-damaged CPUs this symbol must not be defined.
* (Defining this symbol causes large data structures to be referenced through
* "far" pointers and to be allocated with a special version of malloc.)
*/
#undef NEED_FAR_POINTERS
/* Define this if your linker needs global names to be unique in less
* than the first 15 characters.
*/
#undef NEED_SHORT_EXTERNAL_NAMES
/* Although a real ANSI C compiler can deal perfectly well with pointers to
* unspecified structures (see "incomplete types" in the spec), a few pre-ANSI
* and pseudo-ANSI compilers get confused. To keep one of these bozos happy,
* define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you
* actually get "missing structure definition" warnings or errors while
* compiling the JPEG code.
*/
#undef INCOMPLETE_TYPES_BROKEN
/*
* The following options affect code selection within the JPEG library,
* but they don't need to be visible to applications using the library.
* To minimize application namespace pollution, the symbols won't be
* defined unless JPEG_INTERNALS has been defined.
*/
#ifdef JPEG_INTERNALS
/* Define this if your compiler implements ">>" on signed values as a logical
* (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift,
* which is the normal and rational definition.
*/
#undef RIGHT_SHIFT_IS_UNSIGNED
#endif /* JPEG_INTERNALS */
/*
* The remaining options do not affect the JPEG library proper,
* but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c).
* Other applications can ignore these.
*/
#ifdef JPEG_CJPEG_DJPEG
/* These defines indicate which image (non-JPEG) file formats are allowed. */
#define BMP_SUPPORTED /* BMP image file format */
#define GIF_SUPPORTED /* GIF image file format */
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
#undef RLE_SUPPORTED /* Utah RLE image file format */
#define TARGA_SUPPORTED /* Targa image file format */
/* Define this if you want to name both input and output files on the command
* line, rather than using stdout and optionally stdin. You MUST do this if
* your system can't cope with binary I/O to stdin/stdout. See comments at
* head of cjpeg.c or djpeg.c.
*/
#undef TWO_FILE_COMMANDLINE
/* Define this if your system needs explicit cleanup of temporary files.
* This is crucial under MS-DOS, where the temporary "files" may be areas
* of extended memory; on most other systems it's not as important.
*/
#undef NEED_SIGNAL_CATCHER
/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb").
* This is necessary on systems that distinguish text files from binary files,
* and is harmless on most systems that don't. If you have one of the rare
* systems that complains about the "b" spec, define this symbol.
*/
#undef DONT_USE_B_MODE
/* Define this if you want percent-done progress reports from cjpeg/djpeg.
*/
#undef PROGRESS_REPORT
#endif /* JPEG_CJPEG_DJPEG */

360
jconfig.h
View File

@@ -1,360 +0,0 @@
/*
* jconfig.h
*
* Copyright (C) 1991, 1992, 1993, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains preprocessor declarations that help customize
* the JPEG software for a particular application, machine, or compiler.
* Edit these declarations as needed (or add -D flags to the Makefile).
*/
/*
* These symbols indicate the properties of your machine or compiler.
* The conditional definitions given may do the right thing already,
* but you'd best look them over closely, especially if your compiler
* does not handle full ANSI C. An ANSI-compliant C compiler should
* provide all the necessary features; __STDC__ is supposed to be
* predefined by such compilers.
*/
/*
* HAVE_STDC is tested below to see whether ANSI features are available.
* We avoid testing __STDC__ directly for arcane reasons of portability.
* (On some compilers, __STDC__ is only defined if a switch is given,
* but the switch also disables machine-specific features we need to get at.
* In that case, -DHAVE_STDC in the Makefile is a convenient solution.)
*/
#ifdef __STDC__ /* if compiler claims to be ANSI, believe it */
#define HAVE_STDC
#endif
/* Does your compiler support function prototypes? */
/* (If not, you also need to use ansi2knr, see SETUP) */
#ifdef HAVE_STDC /* ANSI C compilers always have prototypes */
#define PROTO
#else
#ifdef __cplusplus /* So do C++ compilers */
#define PROTO
#endif
#endif
/* Does your compiler support the declaration "unsigned char" ? */
/* How about "unsigned short" ? */
#ifdef HAVE_STDC /* ANSI C compilers must support both */
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
#endif
/* Define this if an ordinary "char" type is unsigned.
* If you're not sure, leaving it undefined will work at some cost in speed.
* If you defined HAVE_UNSIGNED_CHAR then it doesn't matter very much.
*/
/* #define CHAR_IS_UNSIGNED */
/* Define this if your compiler implements ">>" on signed values as a logical
* (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift,
* which is the normal and rational definition.
*/
/* #define RIGHT_SHIFT_IS_UNSIGNED */
/* Define "void" as "char" if your compiler doesn't know about type void.
* NOTE: be sure to define void such that "void *" represents the most general
* pointer type, e.g., that returned by malloc().
*/
/* #define void char */
/* Define const as empty if your compiler doesn't know the "const" keyword. */
/* (Even if it does, defining const as empty won't break anything.) */
#ifndef HAVE_STDC /* ANSI C and C++ compilers should know it. */
#ifndef __cplusplus
#define const
#endif
#endif
/* For 80x86 machines, you need to define NEED_FAR_POINTERS,
* unless you are using a large-data memory model or 80386 flat-memory mode.
* On less brain-damaged CPUs this symbol must not be defined.
* (Defining this symbol causes large data structures to be referenced through
* "far" pointers and to be allocated with a special version of malloc.)
*/
#ifdef MSDOS
#define NEED_FAR_POINTERS
#endif
/* The next three symbols only affect the system-dependent user interface
* modules (jcmain.c, jdmain.c). You can ignore these if you are supplying
* your own user interface code.
*/
/* Define this if you want to name both input and output files on the command
* line, rather than using stdout and optionally stdin. You MUST do this if
* your system can't cope with binary I/O to stdin/stdout. See comments at
* head of jcmain.c or jdmain.c.
*/
#ifdef MSDOS /* two-file style is needed for PCs */
#ifndef USE_FDOPEN /* unless you have fdopen() or setmode() */
#ifndef USE_SETMODE
#define TWO_FILE_COMMANDLINE
#endif
#endif
#endif
#ifdef THINK_C /* it's needed for Macintosh too */
#define TWO_FILE_COMMANDLINE
#endif
/* Define this if your system needs explicit cleanup of temporary files.
* This is crucial under MS-DOS, where the temporary "files" may be areas
* of extended memory; on most other systems it's not as important.
*/
#ifdef MSDOS
#define NEED_SIGNAL_CATCHER
#endif
/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb").
* This is necessary on systems that distinguish text files from binary files,
* and is harmless on most systems that don't. If you have one of the rare
* systems that complains about the "b" spec, define this symbol.
*/
/* #define DONT_USE_B_MODE */
/* If you're getting bored, that's the end of the symbols you HAVE to
* worry about. Go fix the makefile and compile.
*/
/* If your compiler supports inline functions, define INLINE
* as the inline keyword; otherwise define it as empty.
*/
#ifdef __GNUC__ /* for instance, GNU C knows about inline */
#define INLINE __inline__
#endif
#ifndef INLINE /* default is to define it as empty */
#define INLINE
#endif
/* On a few systems, type boolean and/or macros FALSE, TRUE may appear
* in standard header files. Or you may have conflicts with application-
* specific header files that you want to include together with these files.
* In that case you need only comment out these definitions.
*/
typedef int boolean;
#undef FALSE /* in case these macros already exist */
#undef TRUE
#define FALSE 0 /* values of boolean */
#define TRUE 1
/* This defines the size of the I/O buffers for entropy compression
* and decompression; you could reduce it if memory is tight.
*/
#define JPEG_BUF_SIZE 4096 /* bytes */
/* These symbols determine the JPEG functionality supported. */
/*
* These defines indicate whether to include various optional functions.
* Undefining some of these symbols will produce a smaller but less capable
* program file. Note that you can leave certain source files out of the
* compilation/linking process if you've #undef'd the corresponding symbols.
* (You may HAVE to do that if your compiler doesn't like null source files.)
*/
/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */
/* Encoder capability options: */
#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
#undef C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? (NYI) */
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */
/* Decoder capability options: */
#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing during decoding? */
#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */
#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */
/* these defines indicate which JPEG file formats are allowed */
#define JFIF_SUPPORTED /* JFIF or "raw JPEG" files */
#undef JTIFF_SUPPORTED /* JPEG-in-TIFF (not yet implemented) */
/* these defines indicate which image (non-JPEG) file formats are allowed */
#define GIF_SUPPORTED /* GIF image file format */
/* #define RLE_SUPPORTED */ /* RLE image file format (by default, no) */
#define PPM_SUPPORTED /* PPM/PGM image file format */
#define TARGA_SUPPORTED /* Targa image file format */
#undef TIFF_SUPPORTED /* TIFF image file format (not yet impl.) */
/* more capability options later, no doubt */
/*
* Define exactly one of these three symbols to indicate whether you want
* 8-bit, 12-bit, or 16-bit sample (pixel component) values. 8-bit is the
* default and is nearly always the right thing to use. You can use 12-bit if
* you need to support image formats with more than 8 bits of resolution in a
* color value. 16-bit should only be used for the lossless JPEG mode (not
* currently supported). Note that 12- and 16-bit values take up twice as
* much memory as 8-bit!
* Note: if you select 12- or 16-bit precision, it is dangerous to turn off
* ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
* precision, so jchuff.c normally uses entropy optimization to compute
* usable tables for higher precision. If you don't want to do optimization,
* you'll have to supply different default Huffman tables.
*/
#define EIGHT_BIT_SAMPLES
#undef TWELVE_BIT_SAMPLES
#undef SIXTEEN_BIT_SAMPLES
/*
* The remaining definitions don't need to be hand-edited in most cases.
* You may need to change these if you have a machine with unusual data
* types; for example, "char" not 8 bits, "short" not 16 bits,
* or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits,
* but it had better be at least 16.
*/
/* First define the representation of a single pixel element value. */
#ifdef EIGHT_BIT_SAMPLES
/* JSAMPLE should be the smallest type that will hold the values 0..255.
* You can use a signed char by having GETJSAMPLE mask it with 0xFF.
* If you have only signed chars, and you are more worried about speed than
* memory usage, it might be a win to make JSAMPLE be short.
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JSAMPLE;
#define GETJSAMPLE(value) (value)
#else /* not HAVE_UNSIGNED_CHAR */
#ifdef CHAR_IS_UNSIGNED
typedef char JSAMPLE;
#define GETJSAMPLE(value) (value)
#else /* not CHAR_IS_UNSIGNED */
typedef char JSAMPLE;
#define GETJSAMPLE(value) ((value) & 0xFF)
#endif /* CHAR_IS_UNSIGNED */
#endif /* HAVE_UNSIGNED_CHAR */
#define BITS_IN_JSAMPLE 8
#define MAXJSAMPLE 255
#define CENTERJSAMPLE 128
#endif /* EIGHT_BIT_SAMPLES */
#ifdef TWELVE_BIT_SAMPLES
/* JSAMPLE should be the smallest type that will hold the values 0..4095. */
/* On nearly all machines "short" will do nicely. */
typedef short JSAMPLE;
#define GETJSAMPLE(value) (value)
#define BITS_IN_JSAMPLE 12
#define MAXJSAMPLE 4095
#define CENTERJSAMPLE 2048
#endif /* TWELVE_BIT_SAMPLES */
#ifdef SIXTEEN_BIT_SAMPLES
/* JSAMPLE should be the smallest type that will hold the values 0..65535. */
#ifdef HAVE_UNSIGNED_SHORT
typedef unsigned short JSAMPLE;
#define GETJSAMPLE(value) (value)
#else /* not HAVE_UNSIGNED_SHORT */
/* If int is 32 bits this'll be horrendously inefficient storage-wise.
* But since we don't actually support 16-bit samples (ie lossless coding) yet,
* I'm not going to worry about making a smarter definition ...
*/
typedef unsigned int JSAMPLE;
#define GETJSAMPLE(value) (value)
#endif /* HAVE_UNSIGNED_SHORT */
#define BITS_IN_JSAMPLE 16
#define MAXJSAMPLE 65535
#define CENTERJSAMPLE 32768
#endif /* SIXTEEN_BIT_SAMPLES */
/* Here we define the representation of a DCT frequency coefficient.
* This should be a signed 16-bit value; "short" is usually right.
* It's important that this be exactly 16 bits, no more and no less;
* more will cost you a BIG hit of memory, less will give wrong answers.
*/
typedef short JCOEF;
/* The remaining typedefs are used for various table entries and so forth.
* They must be at least as wide as specified; but making them too big
* won't cost a huge amount of memory, so we don't provide special
* extraction code like we did for JSAMPLE. (In other words, these
* typedefs live at a different point on the speed/space tradeoff curve.)
*/
/* UINT8 must hold at least the values 0..255. */
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char UINT8;
#else /* not HAVE_UNSIGNED_CHAR */
#ifdef CHAR_IS_UNSIGNED
typedef char UINT8;
#else /* not CHAR_IS_UNSIGNED */
typedef short UINT8;
#endif /* CHAR_IS_UNSIGNED */
#endif /* HAVE_UNSIGNED_CHAR */
/* UINT16 must hold at least the values 0..65535. */
#ifdef HAVE_UNSIGNED_SHORT
typedef unsigned short UINT16;
#else /* not HAVE_UNSIGNED_SHORT */
typedef unsigned int UINT16;
#endif /* HAVE_UNSIGNED_SHORT */
/* INT16 must hold at least the values -32768..32767. */
#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */
typedef short INT16;
#endif
/* INT32 must hold signed 32-bit values; if your machine happens */
/* to have 64-bit longs, you might want to change this. */
#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
typedef long INT32;
#endif

49
jconfig.h.in Normal file
View File

@@ -0,0 +1,49 @@
/* Define if your compiler supports prototypes */
#undef HAVE_PROTOTYPES
/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if the system has the type `unsigned char'. */
#undef HAVE_UNSIGNED_CHAR
/* Define to 1 if the system has the type `unsigned short'. */
#undef HAVE_UNSIGNED_SHORT
/* Define if you want use complete types */
#undef INCOMPLETE_TYPES_BROKEN
/* Define if you have BSD-like bzero and bcopy */
#undef NEED_BSD_STRINGS
/* Define if you need short function names */
#undef NEED_SHORT_EXTERNAL_NAMES
/* Define if you have sys/types.h */
#undef NEED_SYS_TYPES_H
/* Define if shift is unsigned */
#undef RIGHT_SHIFT_IS_UNSIGNED
/* Use accelerated SIMD routines. */
#undef WITH_SIMD
/* Define to 1 if type `char' is unsigned and you are not using gcc. */
#ifndef __CHAR_UNSIGNED__
# undef __CHAR_UNSIGNED__
#endif
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t

617
jcparam.c Normal file
View File

@@ -0,0 +1,617 @@
/*
* jcparam.c
*
* Copyright (C) 1991-1998, Thomas G. Lane.
* Copyright (C) 2009, D. R. Commander.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains optional default-setting code for the JPEG compressor.
* Applications do not have to use this file, but those that don't use it
* must know a lot more about the innards of the JPEG code.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* Quantization table setup routines
*/
GLOBAL(void)
jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
const unsigned int *basic_table,
int scale_factor, boolean force_baseline)
/* Define a quantization table equal to the basic_table times
* a scale factor (given as a percentage).
* If force_baseline is TRUE, the computed quantization table entries
* are limited to 1..255 for JPEG baseline compatibility.
*/
{
JQUANT_TBL ** qtblptr;
int i;
long temp;
/* Safety check to ensure start_compress not called yet. */
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS)
ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl);
qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
if (*qtblptr == NULL)
*qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo);
for (i = 0; i < DCTSIZE2; i++) {
temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
/* limit the values to the valid range */
if (temp <= 0L) temp = 1L;
if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */
if (force_baseline && temp > 255L)
temp = 255L; /* limit to baseline range if requested */
(*qtblptr)->quantval[i] = (UINT16) temp;
}
/* Initialize sent_table FALSE so table will be written to JPEG file. */
(*qtblptr)->sent_table = FALSE;
}
GLOBAL(void)
jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
boolean force_baseline)
/* Set or change the 'quality' (quantization) setting, using default tables
* and a straight percentage-scaling quality scale. In most cases it's better
* to use jpeg_set_quality (below); this entry point is provided for
* applications that insist on a linear percentage scaling.
*/
{
/* These are the sample quantization tables given in JPEG spec section K.1.
* The spec says that the values given produce "good" quality, and
* when divided by 2, "very good" quality.
*/
static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = {
16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55,
14, 13, 16, 24, 40, 57, 69, 56,
14, 17, 22, 29, 51, 87, 80, 62,
18, 22, 37, 56, 68, 109, 103, 77,
24, 35, 55, 64, 81, 104, 113, 92,
49, 64, 78, 87, 103, 121, 120, 101,
72, 92, 95, 98, 112, 100, 103, 99
};
static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = {
17, 18, 24, 47, 99, 99, 99, 99,
18, 21, 26, 66, 99, 99, 99, 99,
24, 26, 56, 99, 99, 99, 99, 99,
47, 66, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99
};
/* Set up two quantization tables using the specified scaling */
jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl,
scale_factor, force_baseline);
jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
scale_factor, force_baseline);
}
GLOBAL(int)
jpeg_quality_scaling (int quality)
/* Convert a user-specified quality rating to a percentage scaling factor
* for an underlying quantization table, using our recommended scaling curve.
* The input 'quality' factor should be 0 (terrible) to 100 (very good).
*/
{
/* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */
if (quality <= 0) quality = 1;
if (quality > 100) quality = 100;
/* The basic table is used as-is (scaling 100) for a quality of 50.
* Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
* note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table
* to make all the table entries 1 (hence, minimum quantization loss).
* Qualities 1..50 are converted to scaling percentage 5000/Q.
*/
if (quality < 50)
quality = 5000 / quality;
else
quality = 200 - quality*2;
return quality;
}
GLOBAL(void)
jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline)
/* Set or change the 'quality' (quantization) setting, using default tables.
* This is the standard quality-adjusting entry point for typical user
* interfaces; only those who want detailed control over quantization tables
* would use the preceding three routines directly.
*/
{
/* Convert user 0-100 rating to percentage scaling */
quality = jpeg_quality_scaling(quality);
/* Set up standard quality tables */
jpeg_set_linear_quality(cinfo, quality, force_baseline);
}
/*
* Huffman table setup routines
*/
LOCAL(void)
add_huff_table (j_compress_ptr cinfo,
JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
/* Define a Huffman table */
{
int nsymbols, len;
if (*htblptr == NULL)
*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
/* Copy the number-of-symbols-of-each-code-length counts */
MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
/* Validate the counts. We do this here mainly so we can copy the right
* number of symbols from the val[] array, without risking marching off
* the end of memory. jchuff.c will do a more thorough test later.
*/
nsymbols = 0;
for (len = 1; len <= 16; len++)
nsymbols += bits[len];
if (nsymbols < 1 || nsymbols > 256)
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8));
/* Initialize sent_table FALSE so table will be written to JPEG file. */
(*htblptr)->sent_table = FALSE;
}
LOCAL(void)
std_huff_tables (j_compress_ptr cinfo)
/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
/* IMPORTANT: these are only valid for 8-bit data precision! */
{
static const UINT8 bits_dc_luminance[17] =
{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
static const UINT8 val_dc_luminance[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
static const UINT8 bits_dc_chrominance[17] =
{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
static const UINT8 val_dc_chrominance[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
static const UINT8 bits_ac_luminance[17] =
{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
static const UINT8 val_ac_luminance[] =
{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa };
static const UINT8 bits_ac_chrominance[17] =
{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
static const UINT8 val_ac_chrominance[] =
{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa };
add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0],
bits_dc_luminance, val_dc_luminance);
add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0],
bits_ac_luminance, val_ac_luminance);
add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1],
bits_dc_chrominance, val_dc_chrominance);
add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1],
bits_ac_chrominance, val_ac_chrominance);
}
/*
* Default parameter setup for compression.
*
* Applications that don't choose to use this routine must do their
* own setup of all these parameters. Alternately, you can call this
* to establish defaults and then alter parameters selectively. This
* is the recommended approach since, if we add any new parameters,
* your code will still work (they'll be set to reasonable defaults).
*/
GLOBAL(void)
jpeg_set_defaults (j_compress_ptr cinfo)
{
int i;
/* Safety check to ensure start_compress not called yet. */
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* Allocate comp_info array large enough for maximum component count.
* Array is made permanent in case application wants to compress
* multiple images at same param settings.
*/
if (cinfo->comp_info == NULL)
cinfo->comp_info = (jpeg_component_info *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
MAX_COMPONENTS * SIZEOF(jpeg_component_info));
/* Initialize everything not dependent on the color space */
cinfo->data_precision = BITS_IN_JSAMPLE;
/* Set up two quantization tables using default quality of 75 */
jpeg_set_quality(cinfo, 75, TRUE);
/* Set up two Huffman tables */
std_huff_tables(cinfo);
/* Initialize default arithmetic coding conditioning */
for (i = 0; i < NUM_ARITH_TBLS; i++) {
cinfo->arith_dc_L[i] = 0;
cinfo->arith_dc_U[i] = 1;
cinfo->arith_ac_K[i] = 5;
}
/* Default is no multiple-scan output */
cinfo->scan_info = NULL;
cinfo->num_scans = 0;
/* Expect normal source image, not raw downsampled data */
cinfo->raw_data_in = FALSE;
/* Use Huffman coding, not arithmetic coding, by default */
cinfo->arith_code = FALSE;
/* By default, don't do extra passes to optimize entropy coding */
cinfo->optimize_coding = FALSE;
/* The standard Huffman tables are only valid for 8-bit data precision.
* If the precision is higher, force optimization on so that usable
* tables will be computed. This test can be removed if default tables
* are supplied that are valid for the desired precision.
*/
if (cinfo->data_precision > 8)
cinfo->optimize_coding = TRUE;
/* By default, use the simpler non-cosited sampling alignment */
cinfo->CCIR601_sampling = FALSE;
/* No input smoothing */
cinfo->smoothing_factor = 0;
/* DCT algorithm preference */
cinfo->dct_method = JDCT_DEFAULT;
/* No restart markers */
cinfo->restart_interval = 0;
cinfo->restart_in_rows = 0;
/* Fill in default JFIF marker parameters. Note that whether the marker
* will actually be written is determined by jpeg_set_colorspace.
*
* By default, the library emits JFIF version code 1.01.
* An application that wants to emit JFIF 1.02 extension markers should set
* JFIF_minor_version to 2. We could probably get away with just defaulting
* to 1.02, but there may still be some decoders in use that will complain
* about that; saying 1.01 should minimize compatibility problems.
*/
cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */
cinfo->JFIF_minor_version = 1;
cinfo->density_unit = 0; /* Pixel size is unknown by default */
cinfo->X_density = 1; /* Pixel aspect ratio is square by default */
cinfo->Y_density = 1;
/* Choose JPEG colorspace based on input space, set defaults accordingly */
jpeg_default_colorspace(cinfo);
}
/*
* Select an appropriate JPEG colorspace for in_color_space.
*/
GLOBAL(void)
jpeg_default_colorspace (j_compress_ptr cinfo)
{
switch (cinfo->in_color_space) {
case JCS_GRAYSCALE:
jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
break;
case JCS_RGB:
case JCS_EXT_RGB:
case JCS_EXT_RGBX:
case JCS_EXT_BGR:
case JCS_EXT_BGRX:
case JCS_EXT_XBGR:
case JCS_EXT_XRGB:
jpeg_set_colorspace(cinfo, JCS_YCbCr);
break;
case JCS_YCbCr:
jpeg_set_colorspace(cinfo, JCS_YCbCr);
break;
case JCS_CMYK:
jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */
break;
case JCS_YCCK:
jpeg_set_colorspace(cinfo, JCS_YCCK);
break;
case JCS_UNKNOWN:
jpeg_set_colorspace(cinfo, JCS_UNKNOWN);
break;
default:
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
}
}
/*
* Set the JPEG colorspace, and choose colorspace-dependent default values.
*/
GLOBAL(void)
jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
{
jpeg_component_info * compptr;
int ci;
#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \
(compptr = &cinfo->comp_info[index], \
compptr->component_id = (id), \
compptr->h_samp_factor = (hsamp), \
compptr->v_samp_factor = (vsamp), \
compptr->quant_tbl_no = (quant), \
compptr->dc_tbl_no = (dctbl), \
compptr->ac_tbl_no = (actbl) )
/* Safety check to ensure start_compress not called yet. */
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* For all colorspaces, we use Q and Huff tables 0 for luminance components,
* tables 1 for chrominance components.
*/
cinfo->jpeg_color_space = colorspace;
cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */
cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */
switch (colorspace) {
case JCS_GRAYSCALE:
cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
cinfo->num_components = 1;
/* JFIF specifies component ID 1 */
SET_COMP(0, 1, 1,1, 0, 0,0);
break;
case JCS_RGB:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */
cinfo->num_components = 3;
SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0);
SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0);
SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0);
break;
case JCS_YCbCr:
cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
cinfo->num_components = 3;
/* JFIF specifies component IDs 1,2,3 */
/* We default to 2x2 subsamples of chrominance */
SET_COMP(0, 1, 2,2, 0, 0,0);
SET_COMP(1, 2, 1,1, 1, 1,1);
SET_COMP(2, 3, 1,1, 1, 1,1);
break;
case JCS_CMYK:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */
cinfo->num_components = 4;
SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0);
SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0);
SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0);
SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0);
break;
case JCS_YCCK:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */
cinfo->num_components = 4;
SET_COMP(0, 1, 2,2, 0, 0,0);
SET_COMP(1, 2, 1,1, 1, 1,1);
SET_COMP(2, 3, 1,1, 1, 1,1);
SET_COMP(3, 4, 2,2, 0, 0,0);
break;
case JCS_UNKNOWN:
cinfo->num_components = cinfo->input_components;
if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
MAX_COMPONENTS);
for (ci = 0; ci < cinfo->num_components; ci++) {
SET_COMP(ci, ci, 1,1, 0, 0,0);
}
break;
default:
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
}
}
#ifdef C_PROGRESSIVE_SUPPORTED
LOCAL(jpeg_scan_info *)
fill_a_scan (jpeg_scan_info * scanptr, int ci,
int Ss, int Se, int Ah, int Al)
/* Support routine: generate one scan for specified component */
{
scanptr->comps_in_scan = 1;
scanptr->component_index[0] = ci;
scanptr->Ss = Ss;
scanptr->Se = Se;
scanptr->Ah = Ah;
scanptr->Al = Al;
scanptr++;
return scanptr;
}
LOCAL(jpeg_scan_info *)
fill_scans (jpeg_scan_info * scanptr, int ncomps,
int Ss, int Se, int Ah, int Al)
/* Support routine: generate one scan for each component */
{
int ci;
for (ci = 0; ci < ncomps; ci++) {
scanptr->comps_in_scan = 1;
scanptr->component_index[0] = ci;
scanptr->Ss = Ss;
scanptr->Se = Se;
scanptr->Ah = Ah;
scanptr->Al = Al;
scanptr++;
}
return scanptr;
}
LOCAL(jpeg_scan_info *)
fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al)
/* Support routine: generate interleaved DC scan if possible, else N scans */
{
int ci;
if (ncomps <= MAX_COMPS_IN_SCAN) {
/* Single interleaved DC scan */
scanptr->comps_in_scan = ncomps;
for (ci = 0; ci < ncomps; ci++)
scanptr->component_index[ci] = ci;
scanptr->Ss = scanptr->Se = 0;
scanptr->Ah = Ah;
scanptr->Al = Al;
scanptr++;
} else {
/* Noninterleaved DC scan for each component */
scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al);
}
return scanptr;
}
/*
* Create a recommended progressive-JPEG script.
* cinfo->num_components and cinfo->jpeg_color_space must be correct.
*/
GLOBAL(void)
jpeg_simple_progression (j_compress_ptr cinfo)
{
int ncomps = cinfo->num_components;
int nscans;
jpeg_scan_info * scanptr;
/* Safety check to ensure start_compress not called yet. */
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* Figure space needed for script. Calculation must match code below! */
if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
/* Custom script for YCbCr color images. */
nscans = 10;
} else {
/* All-purpose script for other color spaces. */
if (ncomps > MAX_COMPS_IN_SCAN)
nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */
else
nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */
}
/* Allocate space for script.
* We need to put it in the permanent pool in case the application performs
* multiple compressions without changing the settings. To avoid a memory
* leak if jpeg_simple_progression is called repeatedly for the same JPEG
* object, we try to re-use previously allocated space, and we allocate
* enough space to handle YCbCr even if initially asked for grayscale.
*/
if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) {
cinfo->script_space_size = MAX(nscans, 10);
cinfo->script_space = (jpeg_scan_info *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
cinfo->script_space_size * SIZEOF(jpeg_scan_info));
}
scanptr = cinfo->script_space;
cinfo->scan_info = scanptr;
cinfo->num_scans = nscans;
if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
/* Custom script for YCbCr color images. */
/* Initial DC scan */
scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
/* Initial AC scan: get some luma data out in a hurry */
scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2);
/* Chroma data is too small to be worth expending many scans on */
scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1);
scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1);
/* Complete spectral selection for luma AC */
scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2);
/* Refine next bit of luma AC */
scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1);
/* Finish DC successive approximation */
scanptr = fill_dc_scans(scanptr, ncomps, 1, 0);
/* Finish AC successive approximation */
scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0);
scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0);
/* Luma bottom bit comes last since it's usually largest scan */
scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0);
} else {
/* All-purpose script for other color spaces. */
/* Successive approximation first pass */
scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2);
scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2);
/* Successive approximation second pass */
scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1);
/* Successive approximation final pass */
scanptr = fill_dc_scans(scanptr, ncomps, 1, 0);
scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0);
}
}
#endif /* C_PROGRESSIVE_SUPPORTED */

831
jcphuff.c Normal file
View File

@@ -0,0 +1,831 @@
/*
* jcphuff.c
*
* Copyright (C) 1995-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains Huffman entropy encoding routines for progressive JPEG.
*
* We do not support output suspension in this module, since the library
* currently does not allow multiple-scan files to be written with output
* suspension.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jchuff.h" /* Declarations shared with jchuff.c */
#ifdef C_PROGRESSIVE_SUPPORTED
/* Expanded entropy encoder object for progressive Huffman encoding. */
typedef struct {
struct jpeg_entropy_encoder pub; /* public fields */
/* Mode flag: TRUE for optimization, FALSE for actual data output */
boolean gather_statistics;
/* Bit-level coding status.
* next_output_byte/free_in_buffer are local copies of cinfo->dest fields.
*/
JOCTET * next_output_byte; /* => next byte to write in buffer */
size_t free_in_buffer; /* # of byte spaces remaining in buffer */
INT32 put_buffer; /* current bit-accumulation buffer */
int put_bits; /* # of bits now in it */
j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */
/* Coding status for DC components */
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
/* Coding status for AC components */
int ac_tbl_no; /* the table number of the single component */
unsigned int EOBRUN; /* run length of EOBs */
unsigned int BE; /* # of buffered correction bits before MCU */
char * bit_buffer; /* buffer for correction bits (1 per char) */
/* packing correction bits tightly would save some space but cost time... */
unsigned int restarts_to_go; /* MCUs left in this restart interval */
int next_restart_num; /* next restart number to write (0-7) */
/* Pointers to derived tables (these workspaces have image lifespan).
* Since any one scan codes only DC or only AC, we only need one set
* of tables, not one for DC and one for AC.
*/
c_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
/* Statistics tables for optimization; again, one set is enough */
long * count_ptrs[NUM_HUFF_TBLS];
} phuff_entropy_encoder;
typedef phuff_entropy_encoder * phuff_entropy_ptr;
/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit
* buffer can hold. Larger sizes may slightly improve compression, but
* 1000 is already well into the realm of overkill.
* The minimum safe size is 64 bits.
*/
#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */
/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32.
* We assume that int right shift is unsigned if INT32 right shift is,
* which should be safe.
*/
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define ISHIFT_TEMPS int ishift_temp;
#define IRIGHT_SHIFT(x,shft) \
((ishift_temp = (x)) < 0 ? \
(ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
(ishift_temp >> (shft)))
#else
#define ISHIFT_TEMPS
#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
#endif
/* Forward declarations */
METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo,
JBLOCKROW *MCU_data));
METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo,
JBLOCKROW *MCU_data));
METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo,
JBLOCKROW *MCU_data));
METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo,
JBLOCKROW *MCU_data));
METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo));
METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo));
/*
* Initialize for a Huffman-compressed scan using progressive JPEG.
*/
METHODDEF(void)
start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
{
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
boolean is_DC_band;
int ci, tbl;
jpeg_component_info * compptr;
entropy->cinfo = cinfo;
entropy->gather_statistics = gather_statistics;
is_DC_band = (cinfo->Ss == 0);
/* We assume jcmaster.c already validated the scan parameters. */
/* Select execution routines */
if (cinfo->Ah == 0) {
if (is_DC_band)
entropy->pub.encode_mcu = encode_mcu_DC_first;
else
entropy->pub.encode_mcu = encode_mcu_AC_first;
} else {
if (is_DC_band)
entropy->pub.encode_mcu = encode_mcu_DC_refine;
else {
entropy->pub.encode_mcu = encode_mcu_AC_refine;
/* AC refinement needs a correction bit buffer */
if (entropy->bit_buffer == NULL)
entropy->bit_buffer = (char *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
MAX_CORR_BITS * SIZEOF(char));
}
}
if (gather_statistics)
entropy->pub.finish_pass = finish_pass_gather_phuff;
else
entropy->pub.finish_pass = finish_pass_phuff;
/* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1
* for AC coefficients.
*/
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* Initialize DC predictions to 0 */
entropy->last_dc_val[ci] = 0;
/* Get table index */
if (is_DC_band) {
if (cinfo->Ah != 0) /* DC refinement needs no table */
continue;
tbl = compptr->dc_tbl_no;
} else {
entropy->ac_tbl_no = tbl = compptr->ac_tbl_no;
}
if (gather_statistics) {
/* Check for invalid table index */
/* (make_c_derived_tbl does this in the other path) */
if (tbl < 0 || tbl >= NUM_HUFF_TBLS)
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl);
/* Allocate and zero the statistics tables */
/* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
if (entropy->count_ptrs[tbl] == NULL)
entropy->count_ptrs[tbl] = (long *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
257 * SIZEOF(long));
MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long));
} else {
/* Compute derived values for Huffman table */
/* We may do this more than once for a table, but it's not expensive */
jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl,
& entropy->derived_tbls[tbl]);
}
}
/* Initialize AC stuff */
entropy->EOBRUN = 0;
entropy->BE = 0;
/* Initialize bit buffer to empty */
entropy->put_buffer = 0;
entropy->put_bits = 0;
/* Initialize restart stuff */
entropy->restarts_to_go = cinfo->restart_interval;
entropy->next_restart_num = 0;
}
/* Outputting bytes to the file.
* NB: these must be called only when actually outputting,
* that is, entropy->gather_statistics == FALSE.
*/
/* Emit a byte */
#define emit_byte(entropy,val) \
{ *(entropy)->next_output_byte++ = (JOCTET) (val); \
if (--(entropy)->free_in_buffer == 0) \
dump_buffer(entropy); }
LOCAL(void)
dump_buffer (phuff_entropy_ptr entropy)
/* Empty the output buffer; we do not support suspension in this module. */
{
struct jpeg_destination_mgr * dest = entropy->cinfo->dest;
if (! (*dest->empty_output_buffer) (entropy->cinfo))
ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND);
/* After a successful buffer dump, must reset buffer pointers */
entropy->next_output_byte = dest->next_output_byte;
entropy->free_in_buffer = dest->free_in_buffer;
}
/* Outputting bits to the file */
/* Only the right 24 bits of put_buffer are used; the valid bits are
* left-justified in this part. At most 16 bits can be passed to emit_bits
* in one call, and we never retain more than 7 bits in put_buffer
* between calls, so 24 bits are sufficient.
*/
LOCAL(void)
emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
/* Emit some bits, unless we are in gather mode */
{
/* This routine is heavily used, so it's worth coding tightly. */
register INT32 put_buffer = (INT32) code;
register int put_bits = entropy->put_bits;
/* if size is 0, caller used an invalid Huffman table entry */
if (size == 0)
ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
if (entropy->gather_statistics)
return; /* do nothing if we're only getting stats */
put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
put_bits += size; /* new number of bits in buffer */
put_buffer <<= 24 - put_bits; /* align incoming bits */
put_buffer |= entropy->put_buffer; /* and merge with old buffer contents */
while (put_bits >= 8) {
int c = (int) ((put_buffer >> 16) & 0xFF);
emit_byte(entropy, c);
if (c == 0xFF) { /* need to stuff a zero byte? */
emit_byte(entropy, 0);
}
put_buffer <<= 8;
put_bits -= 8;
}
entropy->put_buffer = put_buffer; /* update variables */
entropy->put_bits = put_bits;
}
LOCAL(void)
flush_bits (phuff_entropy_ptr entropy)
{
emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */
entropy->put_buffer = 0; /* and reset bit-buffer to empty */
entropy->put_bits = 0;
}
/*
* Emit (or just count) a Huffman symbol.
*/
LOCAL(void)
emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol)
{
if (entropy->gather_statistics)
entropy->count_ptrs[tbl_no][symbol]++;
else {
c_derived_tbl * tbl = entropy->derived_tbls[tbl_no];
emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]);
}
}
/*
* Emit bits from a correction bit buffer.
*/
LOCAL(void)
emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart,
unsigned int nbits)
{
if (entropy->gather_statistics)
return; /* no real work */
while (nbits > 0) {
emit_bits(entropy, (unsigned int) (*bufstart), 1);
bufstart++;
nbits--;
}
}
/*
* Emit any pending EOBRUN symbol.
*/
LOCAL(void)
emit_eobrun (phuff_entropy_ptr entropy)
{
register int temp, nbits;
if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */
temp = entropy->EOBRUN;
nbits = 0;
while ((temp >>= 1))
nbits++;
/* safety check: shouldn't happen given limited correction-bit buffer */
if (nbits > 14)
ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4);
if (nbits)
emit_bits(entropy, entropy->EOBRUN, nbits);
entropy->EOBRUN = 0;
/* Emit any buffered correction bits */
emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE);
entropy->BE = 0;
}
}
/*
* Emit a restart marker & resynchronize predictions.
*/
LOCAL(void)
emit_restart (phuff_entropy_ptr entropy, int restart_num)
{
int ci;
emit_eobrun(entropy);
if (! entropy->gather_statistics) {
flush_bits(entropy);
emit_byte(entropy, 0xFF);
emit_byte(entropy, JPEG_RST0 + restart_num);
}
if (entropy->cinfo->Ss == 0) {
/* Re-initialize DC predictions to 0 */
for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++)
entropy->last_dc_val[ci] = 0;
} else {
/* Re-initialize all AC-related fields to 0 */
entropy->EOBRUN = 0;
entropy->BE = 0;
}
}
/*
* MCU encoding for DC initial scan (either spectral selection,
* or first pass of successive approximation).
*/
METHODDEF(boolean)
encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
register int temp, temp2;
register int nbits;
int blkn, ci;
int Al = cinfo->Al;
JBLOCKROW block;
jpeg_component_info * compptr;
ISHIFT_TEMPS
entropy->next_output_byte = cinfo->dest->next_output_byte;
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
/* Emit restart marker if needed */
if (cinfo->restart_interval)
if (entropy->restarts_to_go == 0)
emit_restart(entropy, entropy->next_restart_num);
/* Encode the MCU data blocks */
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
block = MCU_data[blkn];
ci = cinfo->MCU_membership[blkn];
compptr = cinfo->cur_comp_info[ci];
/* Compute the DC value after the required point transform by Al.
* This is simply an arithmetic right shift.
*/
temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al);
/* DC differences are figured on the point-transformed values. */
temp = temp2 - entropy->last_dc_val[ci];
entropy->last_dc_val[ci] = temp2;
/* Encode the DC coefficient difference per section G.1.2.1 */
temp2 = temp;
if (temp < 0) {
temp = -temp; /* temp is abs value of input */
/* For a negative input, want temp2 = bitwise complement of abs(input) */
/* This code assumes we are on a two's complement machine */
temp2--;
}
/* Find the number of bits needed for the magnitude of the coefficient */
nbits = 0;
while (temp) {
nbits++;
temp >>= 1;
}
/* Check for out-of-range coefficient values.
* Since we're encoding a difference, the range limit is twice as much.
*/
if (nbits > MAX_COEF_BITS+1)
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
/* Count/emit the Huffman-coded symbol for the number of bits */
emit_symbol(entropy, compptr->dc_tbl_no, nbits);
/* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */
if (nbits) /* emit_bits rejects calls with size 0 */
emit_bits(entropy, (unsigned int) temp2, nbits);
}
cinfo->dest->next_output_byte = entropy->next_output_byte;
cinfo->dest->free_in_buffer = entropy->free_in_buffer;
/* Update restart-interval state too */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0) {
entropy->restarts_to_go = cinfo->restart_interval;
entropy->next_restart_num++;
entropy->next_restart_num &= 7;
}
entropy->restarts_to_go--;
}
return TRUE;
}
/*
* MCU encoding for AC initial scan (either spectral selection,
* or first pass of successive approximation).
*/
METHODDEF(boolean)
encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
register int temp, temp2;
register int nbits;
register int r, k;
int Se = cinfo->Se;
int Al = cinfo->Al;
JBLOCKROW block;
entropy->next_output_byte = cinfo->dest->next_output_byte;
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
/* Emit restart marker if needed */
if (cinfo->restart_interval)
if (entropy->restarts_to_go == 0)
emit_restart(entropy, entropy->next_restart_num);
/* Encode the MCU data block */
block = MCU_data[0];
/* Encode the AC coefficients per section G.1.2.2, fig. G.3 */
r = 0; /* r = run length of zeros */
for (k = cinfo->Ss; k <= Se; k++) {
if ((temp = (*block)[jpeg_natural_order[k]]) == 0) {
r++;
continue;
}
/* We must apply the point transform by Al. For AC coefficients this
* is an integer division with rounding towards 0. To do this portably
* in C, we shift after obtaining the absolute value; so the code is
* interwoven with finding the abs value (temp) and output bits (temp2).
*/
if (temp < 0) {
temp = -temp; /* temp is abs value of input */
temp >>= Al; /* apply the point transform */
/* For a negative coef, want temp2 = bitwise complement of abs(coef) */
temp2 = ~temp;
} else {
temp >>= Al; /* apply the point transform */
temp2 = temp;
}
/* Watch out for case that nonzero coef is zero after point transform */
if (temp == 0) {
r++;
continue;
}
/* Emit any pending EOBRUN */
if (entropy->EOBRUN > 0)
emit_eobrun(entropy);
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
while (r > 15) {
emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
r -= 16;
}
/* Find the number of bits needed for the magnitude of the coefficient */
nbits = 1; /* there must be at least one 1 bit */
while ((temp >>= 1))
nbits++;
/* Check for out-of-range coefficient values */
if (nbits > MAX_COEF_BITS)
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
/* Count/emit Huffman symbol for run length / number of bits */
emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits);
/* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */
emit_bits(entropy, (unsigned int) temp2, nbits);
r = 0; /* reset zero run length */
}
if (r > 0) { /* If there are trailing zeroes, */
entropy->EOBRUN++; /* count an EOB */
if (entropy->EOBRUN == 0x7FFF)
emit_eobrun(entropy); /* force it out to avoid overflow */
}
cinfo->dest->next_output_byte = entropy->next_output_byte;
cinfo->dest->free_in_buffer = entropy->free_in_buffer;
/* Update restart-interval state too */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0) {
entropy->restarts_to_go = cinfo->restart_interval;
entropy->next_restart_num++;
entropy->next_restart_num &= 7;
}
entropy->restarts_to_go--;
}
return TRUE;
}
/*
* MCU encoding for DC successive approximation refinement scan.
* Note: we assume such scans can be multi-component, although the spec
* is not very clear on the point.
*/
METHODDEF(boolean)
encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
register int temp;
int blkn;
int Al = cinfo->Al;
JBLOCKROW block;
entropy->next_output_byte = cinfo->dest->next_output_byte;
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
/* Emit restart marker if needed */
if (cinfo->restart_interval)
if (entropy->restarts_to_go == 0)
emit_restart(entropy, entropy->next_restart_num);
/* Encode the MCU data blocks */
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
block = MCU_data[blkn];
/* We simply emit the Al'th bit of the DC coefficient value. */
temp = (*block)[0];
emit_bits(entropy, (unsigned int) (temp >> Al), 1);
}
cinfo->dest->next_output_byte = entropy->next_output_byte;
cinfo->dest->free_in_buffer = entropy->free_in_buffer;
/* Update restart-interval state too */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0) {
entropy->restarts_to_go = cinfo->restart_interval;
entropy->next_restart_num++;
entropy->next_restart_num &= 7;
}
entropy->restarts_to_go--;
}
return TRUE;
}
/*
* MCU encoding for AC successive approximation refinement scan.
*/
METHODDEF(boolean)
encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
register int temp;
register int r, k;
int EOB;
char *BR_buffer;
unsigned int BR;
int Se = cinfo->Se;
int Al = cinfo->Al;
JBLOCKROW block;
int absvalues[DCTSIZE2];
entropy->next_output_byte = cinfo->dest->next_output_byte;
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
/* Emit restart marker if needed */
if (cinfo->restart_interval)
if (entropy->restarts_to_go == 0)
emit_restart(entropy, entropy->next_restart_num);
/* Encode the MCU data block */
block = MCU_data[0];
/* It is convenient to make a pre-pass to determine the transformed
* coefficients' absolute values and the EOB position.
*/
EOB = 0;
for (k = cinfo->Ss; k <= Se; k++) {
temp = (*block)[jpeg_natural_order[k]];
/* We must apply the point transform by Al. For AC coefficients this
* is an integer division with rounding towards 0. To do this portably
* in C, we shift after obtaining the absolute value.
*/
if (temp < 0)
temp = -temp; /* temp is abs value of input */
temp >>= Al; /* apply the point transform */
absvalues[k] = temp; /* save abs value for main pass */
if (temp == 1)
EOB = k; /* EOB = index of last newly-nonzero coef */
}
/* Encode the AC coefficients per section G.1.2.3, fig. G.7 */
r = 0; /* r = run length of zeros */
BR = 0; /* BR = count of buffered bits added now */
BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */
for (k = cinfo->Ss; k <= Se; k++) {
if ((temp = absvalues[k]) == 0) {
r++;
continue;
}
/* Emit any required ZRLs, but not if they can be folded into EOB */
while (r > 15 && k <= EOB) {
/* emit any pending EOBRUN and the BE correction bits */
emit_eobrun(entropy);
/* Emit ZRL */
emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
r -= 16;
/* Emit buffered correction bits that must be associated with ZRL */
emit_buffered_bits(entropy, BR_buffer, BR);
BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
BR = 0;
}
/* If the coef was previously nonzero, it only needs a correction bit.
* NOTE: a straight translation of the spec's figure G.7 would suggest
* that we also need to test r > 15. But if r > 15, we can only get here
* if k > EOB, which implies that this coefficient is not 1.
*/
if (temp > 1) {
/* The correction bit is the next bit of the absolute value. */
BR_buffer[BR++] = (char) (temp & 1);
continue;
}
/* Emit any pending EOBRUN and the BE correction bits */
emit_eobrun(entropy);
/* Count/emit Huffman symbol for run length / number of bits */
emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1);
/* Emit output bit for newly-nonzero coef */
temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1;
emit_bits(entropy, (unsigned int) temp, 1);
/* Emit buffered correction bits that must be associated with this code */
emit_buffered_bits(entropy, BR_buffer, BR);
BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
BR = 0;
r = 0; /* reset zero run length */
}
if (r > 0 || BR > 0) { /* If there are trailing zeroes, */
entropy->EOBRUN++; /* count an EOB */
entropy->BE += BR; /* concat my correction bits to older ones */
/* We force out the EOB if we risk either:
* 1. overflow of the EOB counter;
* 2. overflow of the correction bit buffer during the next MCU.
*/
if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1))
emit_eobrun(entropy);
}
cinfo->dest->next_output_byte = entropy->next_output_byte;
cinfo->dest->free_in_buffer = entropy->free_in_buffer;
/* Update restart-interval state too */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0) {
entropy->restarts_to_go = cinfo->restart_interval;
entropy->next_restart_num++;
entropy->next_restart_num &= 7;
}
entropy->restarts_to_go--;
}
return TRUE;
}
/*
* Finish up at the end of a Huffman-compressed progressive scan.
*/
METHODDEF(void)
finish_pass_phuff (j_compress_ptr cinfo)
{
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
entropy->next_output_byte = cinfo->dest->next_output_byte;
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
/* Flush out any buffered data */
emit_eobrun(entropy);
flush_bits(entropy);
cinfo->dest->next_output_byte = entropy->next_output_byte;
cinfo->dest->free_in_buffer = entropy->free_in_buffer;
}
/*
* Finish up a statistics-gathering pass and create the new Huffman tables.
*/
METHODDEF(void)
finish_pass_gather_phuff (j_compress_ptr cinfo)
{
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
boolean is_DC_band;
int ci, tbl;
jpeg_component_info * compptr;
JHUFF_TBL **htblptr;
boolean did[NUM_HUFF_TBLS];
/* Flush out buffered data (all we care about is counting the EOB symbol) */
emit_eobrun(entropy);
is_DC_band = (cinfo->Ss == 0);
/* It's important not to apply jpeg_gen_optimal_table more than once
* per table, because it clobbers the input frequency counts!
*/
MEMZERO(did, SIZEOF(did));
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
if (is_DC_band) {
if (cinfo->Ah != 0) /* DC refinement needs no table */
continue;
tbl = compptr->dc_tbl_no;
} else {
tbl = compptr->ac_tbl_no;
}
if (! did[tbl]) {
if (is_DC_band)
htblptr = & cinfo->dc_huff_tbl_ptrs[tbl];
else
htblptr = & cinfo->ac_huff_tbl_ptrs[tbl];
if (*htblptr == NULL)
*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]);
did[tbl] = TRUE;
}
}
}
/*
* Module initialization routine for progressive Huffman entropy encoding.
*/
GLOBAL(void)
jinit_phuff_encoder (j_compress_ptr cinfo)
{
phuff_entropy_ptr entropy;
int i;
entropy = (phuff_entropy_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(phuff_entropy_encoder));
cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
entropy->pub.start_pass = start_pass_phuff;
/* Mark tables unallocated */
for (i = 0; i < NUM_HUFF_TBLS; i++) {
entropy->derived_tbls[i] = NULL;
entropy->count_ptrs[i] = NULL;
}
entropy->bit_buffer = NULL; /* needed only in AC refinement scan */
}
#endif /* C_PROGRESSIVE_SUPPORTED */

736
jcpipe.c
View File

@@ -1,736 +0,0 @@
/*
* jcpipe.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains compression pipeline controllers.
* These routines are invoked via the c_pipeline_controller method.
*
* There are four basic pipeline controllers, one for each combination of:
* single-scan JPEG file (single component or fully interleaved)
* vs. multiple-scan JPEG file (noninterleaved or partially interleaved).
*
* optimization of entropy encoding parameters
* vs. usage of default encoding parameters.
*
* Note that these conditions determine the needs for "big" arrays:
* multiple scans imply a big array for splitting the color components;
* entropy encoding optimization needs a big array for the MCU data.
*
* All but the simplest controller (single-scan, no optimization) can be
* compiled out through configuration options, if you need to make a minimal
* implementation.
*/
#include "jinclude.h"
/*
* About the data structures:
*
* The processing chunk size for downsampling is referred to in this file as
* a "row group": a row group is defined as Vk (v_samp_factor) sample rows of
* any component after downsampling, or Vmax (max_v_samp_factor) unsubsampled
* rows. In an interleaved scan each MCU row contains exactly DCTSIZE row
* groups of each component in the scan. In a noninterleaved scan an MCU row
* is one row of blocks, which might not be an integral number of row groups;
* for convenience we use a buffer of the same size as in interleaved scans,
* and process Vk MCU rows in each burst of downsampling.
* To provide context for the downsampling step, we have to retain the last
* two row groups of the previous MCU row while reading in the next MCU row
* (or set of Vk MCU rows). To do this without copying data about, we create
* a rather strange data structure. Exactly DCTSIZE+2 row groups of samples
* are allocated, but we create two different sets of pointers to this array.
* The second set swaps the last two pairs of row groups. By working
* alternately with the two sets of pointers, we can access the data in the
* desired order.
*/
/*
* Utility routines: common code for pipeline controllers
*/
LOCAL void
interleaved_scan_setup (compress_info_ptr cinfo)
/* Compute all derived info for an interleaved (multi-component) scan */
/* On entry, cinfo->comps_in_scan and cinfo->cur_comp_info[] are set up */
{
short ci, mcublks;
jpeg_component_info *compptr;
if (cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
cinfo->MCUs_per_row = (cinfo->image_width
+ cinfo->max_h_samp_factor*DCTSIZE - 1)
/ (cinfo->max_h_samp_factor*DCTSIZE);
cinfo->MCU_rows_in_scan = (cinfo->image_height
+ cinfo->max_v_samp_factor*DCTSIZE - 1)
/ (cinfo->max_v_samp_factor*DCTSIZE);
cinfo->blocks_in_MCU = 0;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* for interleaved scan, sampling factors give # of blocks per component */
compptr->MCU_width = compptr->h_samp_factor;
compptr->MCU_height = compptr->v_samp_factor;
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
/* compute physical dimensions of component */
compptr->downsampled_width = jround_up(compptr->true_comp_width,
(long) (compptr->MCU_width*DCTSIZE));
compptr->downsampled_height = jround_up(compptr->true_comp_height,
(long) (compptr->MCU_height*DCTSIZE));
/* Sanity check */
if (compptr->downsampled_width !=
(cinfo->MCUs_per_row * (compptr->MCU_width*DCTSIZE)))
ERREXIT(cinfo->emethods, "I'm confused about the image width");
/* Prepare array describing MCU composition */
mcublks = compptr->MCU_blocks;
if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU)
ERREXIT(cinfo->emethods, "Sampling factors too large for interleaved scan");
while (mcublks-- > 0) {
cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
}
}
/* Convert restart specified in rows to actual MCU count. */
/* Note that count must fit in 16 bits, so we provide limiting. */
if (cinfo->restart_in_rows > 0) {
long nominal = cinfo->restart_in_rows * cinfo->MCUs_per_row;
cinfo->restart_interval = (UINT16) MIN(nominal, 65535L);
}
(*cinfo->methods->c_per_scan_method_selection) (cinfo);
}
LOCAL void
noninterleaved_scan_setup (compress_info_ptr cinfo)
/* Compute all derived info for a noninterleaved (single-component) scan */
/* On entry, cinfo->comps_in_scan = 1 and cinfo->cur_comp_info[0] is set up */
{
jpeg_component_info *compptr = cinfo->cur_comp_info[0];
/* for noninterleaved scan, always one block per MCU */
compptr->MCU_width = 1;
compptr->MCU_height = 1;
compptr->MCU_blocks = 1;
/* compute physical dimensions of component */
compptr->downsampled_width = jround_up(compptr->true_comp_width,
(long) DCTSIZE);
compptr->downsampled_height = jround_up(compptr->true_comp_height,
(long) DCTSIZE);
cinfo->MCUs_per_row = compptr->downsampled_width / DCTSIZE;
cinfo->MCU_rows_in_scan = compptr->downsampled_height / DCTSIZE;
/* Prepare array describing MCU composition */
cinfo->blocks_in_MCU = 1;
cinfo->MCU_membership[0] = 0;
/* Convert restart specified in rows to actual MCU count. */
/* Note that count must fit in 16 bits, so we provide limiting. */
if (cinfo->restart_in_rows > 0) {
long nominal = cinfo->restart_in_rows * cinfo->MCUs_per_row;
cinfo->restart_interval = (UINT16) MIN(nominal, 65535L);
}
(*cinfo->methods->c_per_scan_method_selection) (cinfo);
}
LOCAL void
alloc_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2],
long fullsize_width)
/* Create a pre-downsampling data buffer having the desired structure */
/* (see comments at head of file) */
{
short ci, vs, i;
vs = cinfo->max_v_samp_factor; /* row group height */
/* Get top-level space for array pointers */
fullsize_data[0] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
(cinfo->num_components * SIZEOF(JSAMPARRAY));
fullsize_data[1] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
(cinfo->num_components * SIZEOF(JSAMPARRAY));
for (ci = 0; ci < cinfo->num_components; ci++) {
/* Allocate the real storage */
fullsize_data[0][ci] = (*cinfo->emethods->alloc_small_sarray)
(fullsize_width,
(long) (vs * (DCTSIZE+2)));
/* Create space for the scrambled-order pointers */
fullsize_data[1][ci] = (JSAMPARRAY) (*cinfo->emethods->alloc_small)
(vs * (DCTSIZE+2) * SIZEOF(JSAMPROW));
/* Duplicate the first DCTSIZE-2 row groups */
for (i = 0; i < vs * (DCTSIZE-2); i++) {
fullsize_data[1][ci][i] = fullsize_data[0][ci][i];
}
/* Copy the last four row groups in swapped order */
for (i = 0; i < vs * 2; i++) {
fullsize_data[1][ci][vs*DCTSIZE + i] = fullsize_data[0][ci][vs*(DCTSIZE-2) + i];
fullsize_data[1][ci][vs*(DCTSIZE-2) + i] = fullsize_data[0][ci][vs*DCTSIZE + i];
}
}
}
#if 0 /* this routine not currently needed */
LOCAL void
free_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2])
/* Release a sampling buffer created by alloc_sampling_buffer */
{
short ci;
for (ci = 0; ci < cinfo->num_components; ci++) {
/* Free the real storage */
(*cinfo->emethods->free_small_sarray) (fullsize_data[0][ci]);
/* Free the scrambled-order pointers */
(*cinfo->emethods->free_small) ((void *) fullsize_data[1][ci]);
}
/* Free the top-level space */
(*cinfo->emethods->free_small) ((void *) fullsize_data[0]);
(*cinfo->emethods->free_small) ((void *) fullsize_data[1]);
}
#endif
LOCAL void
downsample (compress_info_ptr cinfo,
JSAMPIMAGE fullsize_data, JSAMPIMAGE sampled_data,
long fullsize_width,
short above, short current, short below, short out)
/* Do downsampling of a single row group (of each component). */
/* above, current, below are indexes of row groups in fullsize_data; */
/* out is the index of the target row group in sampled_data. */
/* Special case: above, below can be -1 to indicate top, bottom of image. */
{
jpeg_component_info *compptr;
JSAMPARRAY above_ptr, below_ptr;
JSAMPROW dummy[MAX_SAMP_FACTOR]; /* for downsample expansion at top/bottom */
short ci, vs, i;
vs = cinfo->max_v_samp_factor; /* row group height */
for (ci = 0; ci < cinfo->num_components; ci++) {
compptr = & cinfo->comp_info[ci];
if (above >= 0)
above_ptr = fullsize_data[ci] + above * vs;
else {
/* Top of image: make a dummy above-context with copies of 1st row */
/* We assume current=0 in this case */
for (i = 0; i < vs; i++)
dummy[i] = fullsize_data[ci][0];
above_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
}
if (below >= 0)
below_ptr = fullsize_data[ci] + below * vs;
else {
/* Bot of image: make a dummy below-context with copies of last row */
for (i = 0; i < vs; i++)
dummy[i] = fullsize_data[ci][(current+1)*vs-1];
below_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
}
(*cinfo->methods->downsample[ci])
(cinfo, (int) ci,
fullsize_width, (int) vs,
compptr->downsampled_width, (int) compptr->v_samp_factor,
above_ptr,
fullsize_data[ci] + current * vs,
below_ptr,
sampled_data[ci] + out * compptr->v_samp_factor);
}
}
/* These variables are initialized by the pipeline controller for use by
* MCU_output_catcher.
* To avoid a lot of row-pointer overhead, we cram as many MCUs into each
* row of whole_scan_MCUs as we can get without exceeding 32Kbytes per row.
* NOTE: the "arbitrary" constant here must not exceed MAX_ALLOC_CHUNK
* defined in jmemsys.h, which is 64K-epsilon in most DOS implementations.
*/
#define MAX_WHOLE_ROW_BLOCKS ((int) (32768L / SIZEOF(JBLOCK))) /* max blocks/row */
static big_barray_ptr whole_scan_MCUs; /* Big array for saving the MCUs */
static int MCUs_in_big_row; /* # of MCUs in each row of whole_scan_MCUs */
static long next_whole_row; /* next row to access in whole_scan_MCUs */
static int next_MCU_index; /* next MCU in current row */
METHODDEF void
MCU_output_catcher (compress_info_ptr cinfo, JBLOCK *MCU_data)
/* Output method for siphoning off extract_MCUs output into a big array */
{
static JBLOCKARRAY rowptr;
if (next_MCU_index >= MCUs_in_big_row) {
rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
next_whole_row, TRUE);
next_whole_row++;
next_MCU_index = 0;
}
/*
* note that on 80x86, the cast applied to MCU_data implies
* near to far pointer conversion.
*/
jcopy_block_row((JBLOCKROW) MCU_data,
rowptr[0] + next_MCU_index * cinfo->blocks_in_MCU,
(long) cinfo->blocks_in_MCU);
next_MCU_index++;
}
METHODDEF void
dump_scan_MCUs (compress_info_ptr cinfo, MCU_output_method_ptr output_method)
/* Dump the MCUs saved in whole_scan_MCUs to the output method. */
/* The method may be either the entropy encoder or some routine supplied */
/* by the entropy optimizer. */
{
/* On an 80x86 machine, the entropy encoder expects the passed data block
* to be in NEAR memory (for performance reasons), so we have to copy it
* back from the big array to a local array. On less brain-damaged CPUs
* we needn't do that.
*/
#ifdef NEED_FAR_POINTERS
JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
#endif
long mcurow, mcuindex, next_row;
int next_index;
JBLOCKARRAY rowptr = NULL; /* init only to suppress compiler complaint */
next_row = 0;
next_index = MCUs_in_big_row;
for (mcurow = 0; mcurow < cinfo->MCU_rows_in_scan; mcurow++) {
(*cinfo->methods->progress_monitor) (cinfo, mcurow,
cinfo->MCU_rows_in_scan);
for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
if (next_index >= MCUs_in_big_row) {
rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
next_row, FALSE);
next_row++;
next_index = 0;
}
#ifdef NEED_FAR_POINTERS
jcopy_block_row(rowptr[0] + next_index * cinfo->blocks_in_MCU,
(JBLOCKROW) MCU_data, /* casts near to far pointer! */
(long) cinfo->blocks_in_MCU);
(*output_method) (cinfo, MCU_data);
#else
(*output_method) (cinfo, rowptr[0] + next_index * cinfo->blocks_in_MCU);
#endif
next_index++;
}
}
cinfo->completed_passes++;
}
/*
* Compression pipeline controller used for single-scan files
* with no optimization of entropy parameters.
*/
METHODDEF void
single_ccontroller (compress_info_ptr cinfo)
{
int rows_in_mem; /* # of sample rows in full-size buffers */
long fullsize_width; /* # of samples per row in full-size buffers */
long cur_pixel_row; /* counts # of pixel rows processed */
long mcu_rows_output; /* # of MCU rows actually emitted */
int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */
/* Work buffer for pre-downsampling data (see comments at head of file) */
JSAMPIMAGE fullsize_data[2];
/* Work buffer for downsampled data */
JSAMPIMAGE sampled_data;
int rows_this_time;
short ci, whichss, i;
/* Prepare for single scan containing all components */
if (cinfo->num_components > MAX_COMPS_IN_SCAN)
ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
cinfo->comps_in_scan = cinfo->num_components;
for (ci = 0; ci < cinfo->num_components; ci++) {
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
}
if (cinfo->comps_in_scan == 1) {
noninterleaved_scan_setup(cinfo);
/* Vk block rows constitute the same number of MCU rows */
mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
} else {
interleaved_scan_setup(cinfo);
/* in an interleaved scan, one MCU row contains Vk block rows */
mcu_rows_per_loop = 1;
}
cinfo->total_passes++;
/* Compute dimensions of full-size pixel buffers */
/* Note these are the same whether interleaved or not. */
rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
fullsize_width = jround_up(cinfo->image_width,
(long) (cinfo->max_h_samp_factor * DCTSIZE));
/* Allocate working memory: */
/* fullsize_data is sample data before downsampling */
alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
/* sampled_data is sample data after downsampling */
sampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
(cinfo->num_components * SIZEOF(JSAMPARRAY));
for (ci = 0; ci < cinfo->num_components; ci++) {
sampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
(cinfo->comp_info[ci].downsampled_width,
(long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
}
/* Tell the memory manager to instantiate big arrays.
* We don't need any big arrays in this controller,
* but some other module (like the input file reader) may need one.
*/
(*cinfo->emethods->alloc_big_arrays)
((long) 0, /* no more small sarrays */
(long) 0, /* no more small barrays */
(long) 0); /* no more "medium" objects */
/* Initialize output file & do per-scan object init */
(*cinfo->methods->write_scan_header) (cinfo);
cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
(*cinfo->methods->entropy_encode_init) (cinfo);
(*cinfo->methods->downsample_init) (cinfo);
(*cinfo->methods->extract_init) (cinfo);
/* Loop over input image: rows_in_mem pixel rows are processed per loop */
mcu_rows_output = 0;
whichss = 1; /* arrange to start with fullsize_data[0] */
for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
cur_pixel_row += rows_in_mem) {
(*cinfo->methods->progress_monitor) (cinfo, cur_pixel_row,
cinfo->image_height);
whichss ^= 1; /* switch to other fullsize_data buffer */
/* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */
/* Then we have exactly DCTSIZE row groups for downsampling. */
rows_this_time = (int) MIN((long) rows_in_mem,
cinfo->image_height - cur_pixel_row);
(*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
fullsize_data[whichss]);
(*cinfo->methods->edge_expand) (cinfo,
cinfo->image_width, rows_this_time,
fullsize_width, rows_in_mem,
fullsize_data[whichss]);
/* Downsample the data (all components) */
/* First time through is a special case */
if (cur_pixel_row) {
/* Downsample last row group of previous set */
downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
(short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
(short) (DCTSIZE-1));
/* and dump the previous set's downsampled data */
(*cinfo->methods->extract_MCUs) (cinfo, sampled_data,
mcu_rows_per_loop,
cinfo->methods->entropy_encode);
mcu_rows_output += mcu_rows_per_loop;
/* Downsample first row group of this set */
downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
(short) (DCTSIZE+1), (short) 0, (short) 1,
(short) 0);
} else {
/* Downsample first row group with dummy above-context */
downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
(short) (-1), (short) 0, (short) 1,
(short) 0);
}
/* Downsample second through next-to-last row groups of this set */
for (i = 1; i <= DCTSIZE-2; i++) {
downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
(short) (i-1), (short) i, (short) (i+1),
(short) i);
}
} /* end of outer loop */
/* Downsample the last row group with dummy below-context */
/* Note whichss points to last buffer side used */
downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
(short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
(short) (DCTSIZE-1));
/* Dump the remaining data (may be less than full height if uninterleaved) */
(*cinfo->methods->extract_MCUs) (cinfo, sampled_data,
(int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
cinfo->methods->entropy_encode);
/* Finish output file */
(*cinfo->methods->extract_term) (cinfo);
(*cinfo->methods->downsample_term) (cinfo);
(*cinfo->methods->entropy_encode_term) (cinfo);
(*cinfo->methods->write_scan_trailer) (cinfo);
cinfo->completed_passes++;
/* Release working memory */
/* (no work -- we let free_all release what's needful) */
}
/*
* Compression pipeline controller used for single-scan files
* with optimization of entropy parameters.
*/
#ifdef ENTROPY_OPT_SUPPORTED
METHODDEF void
single_eopt_ccontroller (compress_info_ptr cinfo)
{
int rows_in_mem; /* # of sample rows in full-size buffers */
long fullsize_width; /* # of samples per row in full-size buffers */
long cur_pixel_row; /* counts # of pixel rows processed */
long mcu_rows_output; /* # of MCU rows actually emitted */
int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */
/* Work buffer for pre-downsampling data (see comments at head of file) */
JSAMPIMAGE fullsize_data[2];
/* Work buffer for downsampled data */
JSAMPIMAGE sampled_data;
int rows_this_time;
int blocks_in_big_row;
short ci, whichss, i;
/* Prepare for single scan containing all components */
if (cinfo->num_components > MAX_COMPS_IN_SCAN)
ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
cinfo->comps_in_scan = cinfo->num_components;
for (ci = 0; ci < cinfo->num_components; ci++) {
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
}
if (cinfo->comps_in_scan == 1) {
noninterleaved_scan_setup(cinfo);
/* Vk block rows constitute the same number of MCU rows */
mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
} else {
interleaved_scan_setup(cinfo);
/* in an interleaved scan, one MCU row contains Vk block rows */
mcu_rows_per_loop = 1;
}
cinfo->total_passes += 2; /* entropy encoder must add # passes it uses */
/* Compute dimensions of full-size pixel buffers */
/* Note these are the same whether interleaved or not. */
rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
fullsize_width = jround_up(cinfo->image_width,
(long) (cinfo->max_h_samp_factor * DCTSIZE));
/* Allocate working memory: */
/* fullsize_data is sample data before downsampling */
alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
/* sampled_data is sample data after downsampling */
sampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
(cinfo->num_components * SIZEOF(JSAMPARRAY));
for (ci = 0; ci < cinfo->num_components; ci++) {
sampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
(cinfo->comp_info[ci].downsampled_width,
(long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
}
/* Figure # of MCUs to be packed in a row of whole_scan_MCUs */
MCUs_in_big_row = MAX_WHOLE_ROW_BLOCKS / cinfo->blocks_in_MCU;
blocks_in_big_row = MCUs_in_big_row * cinfo->blocks_in_MCU;
/* Request a big array: whole_scan_MCUs saves the MCU data for the scan */
whole_scan_MCUs = (*cinfo->emethods->request_big_barray)
((long) blocks_in_big_row,
(long) (cinfo->MCUs_per_row * cinfo->MCU_rows_in_scan
+ MCUs_in_big_row-1) / MCUs_in_big_row,
1L); /* unit height is 1 row */
next_whole_row = 0; /* init output ptr for MCU_output_catcher */
next_MCU_index = MCUs_in_big_row; /* forces access on first call! */
/* Tell the memory manager to instantiate big arrays */
(*cinfo->emethods->alloc_big_arrays)
((long) 0, /* no more small sarrays */
(long) 0, /* no more small barrays */
(long) 0); /* no more "medium" objects */
/* Do per-scan object init */
(*cinfo->methods->downsample_init) (cinfo);
(*cinfo->methods->extract_init) (cinfo);
/* Loop over input image: rows_in_mem pixel rows are processed per loop */
/* MCU data goes into whole_scan_MCUs, not to the entropy encoder */
mcu_rows_output = 0;
whichss = 1; /* arrange to start with fullsize_data[0] */
for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
cur_pixel_row += rows_in_mem) {
(*cinfo->methods->progress_monitor) (cinfo, cur_pixel_row,
cinfo->image_height);
whichss ^= 1; /* switch to other fullsize_data buffer */
/* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */
/* Then we have exactly DCTSIZE row groups for downsampling. */
rows_this_time = (int) MIN((long) rows_in_mem,
cinfo->image_height - cur_pixel_row);
(*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
fullsize_data[whichss]);
(*cinfo->methods->edge_expand) (cinfo,
cinfo->image_width, rows_this_time,
fullsize_width, rows_in_mem,
fullsize_data[whichss]);
/* Downsample the data (all components) */
/* First time through is a special case */
if (cur_pixel_row) {
/* Downsample last row group of previous set */
downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
(short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
(short) (DCTSIZE-1));
/* and dump the previous set's downsampled data */
(*cinfo->methods->extract_MCUs) (cinfo, sampled_data,
mcu_rows_per_loop,
MCU_output_catcher);
mcu_rows_output += mcu_rows_per_loop;
/* Downsample first row group of this set */
downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
(short) (DCTSIZE+1), (short) 0, (short) 1,
(short) 0);
} else {
/* Downsample first row group with dummy above-context */
downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
(short) (-1), (short) 0, (short) 1,
(short) 0);
}
/* Downsample second through next-to-last row groups of this set */
for (i = 1; i <= DCTSIZE-2; i++) {
downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
(short) (i-1), (short) i, (short) (i+1),
(short) i);
}
} /* end of outer loop */
/* Downsample the last row group with dummy below-context */
/* Note whichss points to last buffer side used */
downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
(short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
(short) (DCTSIZE-1));
/* Dump the remaining data (may be less than full height if uninterleaved) */
(*cinfo->methods->extract_MCUs) (cinfo, sampled_data,
(int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
MCU_output_catcher);
/* Clean up after that stuff, then find the optimal entropy parameters */
(*cinfo->methods->extract_term) (cinfo);
(*cinfo->methods->downsample_term) (cinfo);
cinfo->completed_passes++;
(*cinfo->methods->entropy_optimize) (cinfo, dump_scan_MCUs);
/* Emit scan to output file */
/* Note: we can't do write_scan_header until entropy parameters are set! */
(*cinfo->methods->write_scan_header) (cinfo);
cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
(*cinfo->methods->entropy_encode_init) (cinfo);
dump_scan_MCUs(cinfo, cinfo->methods->entropy_encode);
(*cinfo->methods->entropy_encode_term) (cinfo);
(*cinfo->methods->write_scan_trailer) (cinfo);
/* Release working memory */
/* (no work -- we let free_all release what's needful) */
}
#endif /* ENTROPY_OPT_SUPPORTED */
/*
* Compression pipeline controller used for multiple-scan files
* with no optimization of entropy parameters.
*/
#ifdef C_MULTISCAN_FILES_SUPPORTED
METHODDEF void
multi_ccontroller (compress_info_ptr cinfo)
{
ERREXIT(cinfo->emethods, "Not implemented yet");
}
#endif /* C_MULTISCAN_FILES_SUPPORTED */
/*
* Compression pipeline controller used for multiple-scan files
* with optimization of entropy parameters.
*/
#ifdef C_MULTISCAN_FILES_SUPPORTED
#ifdef ENTROPY_OPT_SUPPORTED
METHODDEF void
multi_eopt_ccontroller (compress_info_ptr cinfo)
{
ERREXIT(cinfo->emethods, "Not implemented yet");
}
#endif /* ENTROPY_OPT_SUPPORTED */
#endif /* C_MULTISCAN_FILES_SUPPORTED */
/*
* The method selection routine for compression pipeline controllers.
*/
GLOBAL void
jselcpipeline (compress_info_ptr cinfo)
{
if (cinfo->interleave || cinfo->num_components == 1) {
/* single scan needed */
#ifdef ENTROPY_OPT_SUPPORTED
if (cinfo->optimize_coding)
cinfo->methods->c_pipeline_controller = single_eopt_ccontroller;
else
#endif
cinfo->methods->c_pipeline_controller = single_ccontroller;
} else {
/* multiple scans needed */
#ifdef C_MULTISCAN_FILES_SUPPORTED
#ifdef ENTROPY_OPT_SUPPORTED
if (cinfo->optimize_coding)
cinfo->methods->c_pipeline_controller = multi_eopt_ccontroller;
else
#endif
cinfo->methods->c_pipeline_controller = multi_ccontroller;
#else
ERREXIT(cinfo->emethods, "Multiple-scan support was not compiled");
#endif
}
}

354
jcprepct.c Normal file
View File

@@ -0,0 +1,354 @@
/*
* jcprepct.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the compression preprocessing controller.
* This controller manages the color conversion, downsampling,
* and edge expansion steps.
*
* Most of the complexity here is associated with buffering input rows
* as required by the downsampler. See the comments at the head of
* jcsample.c for the downsampler's needs.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* At present, jcsample.c can request context rows only for smoothing.
* In the future, we might also need context rows for CCIR601 sampling
* or other more-complex downsampling procedures. The code to support
* context rows should be compiled only if needed.
*/
#ifdef INPUT_SMOOTHING_SUPPORTED
#define CONTEXT_ROWS_SUPPORTED
#endif
/*
* For the simple (no-context-row) case, we just need to buffer one
* row group's worth of pixels for the downsampling step. At the bottom of
* the image, we pad to a full row group by replicating the last pixel row.
* The downsampler's last output row is then replicated if needed to pad
* out to a full iMCU row.
*
* When providing context rows, we must buffer three row groups' worth of
* pixels. Three row groups are physically allocated, but the row pointer
* arrays are made five row groups high, with the extra pointers above and
* below "wrapping around" to point to the last and first real row groups.
* This allows the downsampler to access the proper context rows.
* At the top and bottom of the image, we create dummy context rows by
* copying the first or last real pixel row. This copying could be avoided
* by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
* trouble on the compression side.
*/
/* Private buffer controller object */
typedef struct {
struct jpeg_c_prep_controller pub; /* public fields */
/* Downsampling input buffer. This buffer holds color-converted data
* until we have enough to do a downsample step.
*/
JSAMPARRAY color_buf[MAX_COMPONENTS];
JDIMENSION rows_to_go; /* counts rows remaining in source image */
int next_buf_row; /* index of next row to store in color_buf */
#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */
int this_row_group; /* starting row index of group to process */
int next_buf_stop; /* downsample when we reach this index */
#endif
} my_prep_controller;
typedef my_prep_controller * my_prep_ptr;
/*
* Initialize for a processing pass.
*/
METHODDEF(void)
start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
if (pass_mode != JBUF_PASS_THRU)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
/* Initialize total-height counter for detecting bottom of image */
prep->rows_to_go = cinfo->image_height;
/* Mark the conversion buffer empty */
prep->next_buf_row = 0;
#ifdef CONTEXT_ROWS_SUPPORTED
/* Preset additional state variables for context mode.
* These aren't used in non-context mode, so we needn't test which mode.
*/
prep->this_row_group = 0;
/* Set next_buf_stop to stop after two row groups have been read in. */
prep->next_buf_stop = 2 * cinfo->max_v_samp_factor;
#endif
}
/*
* Expand an image vertically from height input_rows to height output_rows,
* by duplicating the bottom row.
*/
LOCAL(void)
expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,
int input_rows, int output_rows)
{
register int row;
for (row = input_rows; row < output_rows; row++) {
jcopy_sample_rows(image_data, input_rows-1, image_data, row,
1, num_cols);
}
}
/*
* Process some data in the simple no-context case.
*
* Preprocessor output data is counted in "row groups". A row group
* is defined to be v_samp_factor sample rows of each component.
* Downsampling will produce this much data from each max_v_samp_factor
* input rows.
*/
METHODDEF(void)
pre_process_data (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
JDIMENSION in_rows_avail,
JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
JDIMENSION out_row_groups_avail)
{
my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
int numrows, ci;
JDIMENSION inrows;
jpeg_component_info * compptr;
while (*in_row_ctr < in_rows_avail &&
*out_row_group_ctr < out_row_groups_avail) {
/* Do color conversion to fill the conversion buffer. */
inrows = in_rows_avail - *in_row_ctr;
numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
numrows = (int) MIN((JDIMENSION) numrows, inrows);
(*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
prep->color_buf,
(JDIMENSION) prep->next_buf_row,
numrows);
*in_row_ctr += numrows;
prep->next_buf_row += numrows;
prep->rows_to_go -= numrows;
/* If at bottom of image, pad to fill the conversion buffer. */
if (prep->rows_to_go == 0 &&
prep->next_buf_row < cinfo->max_v_samp_factor) {
for (ci = 0; ci < cinfo->num_components; ci++) {
expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
prep->next_buf_row, cinfo->max_v_samp_factor);
}
prep->next_buf_row = cinfo->max_v_samp_factor;
}
/* If we've filled the conversion buffer, empty it. */
if (prep->next_buf_row == cinfo->max_v_samp_factor) {
(*cinfo->downsample->downsample) (cinfo,
prep->color_buf, (JDIMENSION) 0,
output_buf, *out_row_group_ctr);
prep->next_buf_row = 0;
(*out_row_group_ctr)++;
}
/* If at bottom of image, pad the output to a full iMCU height.
* Note we assume the caller is providing a one-iMCU-height output buffer!
*/
if (prep->rows_to_go == 0 &&
*out_row_group_ctr < out_row_groups_avail) {
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
expand_bottom_edge(output_buf[ci],
compptr->width_in_blocks * DCTSIZE,
(int) (*out_row_group_ctr * compptr->v_samp_factor),
(int) (out_row_groups_avail * compptr->v_samp_factor));
}
*out_row_group_ctr = out_row_groups_avail;
break; /* can exit outer loop without test */
}
}
}
#ifdef CONTEXT_ROWS_SUPPORTED
/*
* Process some data in the context case.
*/
METHODDEF(void)
pre_process_context (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
JDIMENSION in_rows_avail,
JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
JDIMENSION out_row_groups_avail)
{
my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
int numrows, ci;
int buf_height = cinfo->max_v_samp_factor * 3;
JDIMENSION inrows;
while (*out_row_group_ctr < out_row_groups_avail) {
if (*in_row_ctr < in_rows_avail) {
/* Do color conversion to fill the conversion buffer. */
inrows = in_rows_avail - *in_row_ctr;
numrows = prep->next_buf_stop - prep->next_buf_row;
numrows = (int) MIN((JDIMENSION) numrows, inrows);
(*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
prep->color_buf,
(JDIMENSION) prep->next_buf_row,
numrows);
/* Pad at top of image, if first time through */
if (prep->rows_to_go == cinfo->image_height) {
for (ci = 0; ci < cinfo->num_components; ci++) {
int row;
for (row = 1; row <= cinfo->max_v_samp_factor; row++) {
jcopy_sample_rows(prep->color_buf[ci], 0,
prep->color_buf[ci], -row,
1, cinfo->image_width);
}
}
}
*in_row_ctr += numrows;
prep->next_buf_row += numrows;
prep->rows_to_go -= numrows;
} else {
/* Return for more data, unless we are at the bottom of the image. */
if (prep->rows_to_go != 0)
break;
/* When at bottom of image, pad to fill the conversion buffer. */
if (prep->next_buf_row < prep->next_buf_stop) {
for (ci = 0; ci < cinfo->num_components; ci++) {
expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
prep->next_buf_row, prep->next_buf_stop);
}
prep->next_buf_row = prep->next_buf_stop;
}
}
/* If we've gotten enough data, downsample a row group. */
if (prep->next_buf_row == prep->next_buf_stop) {
(*cinfo->downsample->downsample) (cinfo,
prep->color_buf,
(JDIMENSION) prep->this_row_group,
output_buf, *out_row_group_ctr);
(*out_row_group_ctr)++;
/* Advance pointers with wraparound as necessary. */
prep->this_row_group += cinfo->max_v_samp_factor;
if (prep->this_row_group >= buf_height)
prep->this_row_group = 0;
if (prep->next_buf_row >= buf_height)
prep->next_buf_row = 0;
prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor;
}
}
}
/*
* Create the wrapped-around downsampling input buffer needed for context mode.
*/
LOCAL(void)
create_context_buffer (j_compress_ptr cinfo)
{
my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
int rgroup_height = cinfo->max_v_samp_factor;
int ci, i;
jpeg_component_info * compptr;
JSAMPARRAY true_buffer, fake_buffer;
/* Grab enough space for fake row pointers for all the components;
* we need five row groups' worth of pointers for each component.
*/
fake_buffer = (JSAMPARRAY)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(cinfo->num_components * 5 * rgroup_height) *
SIZEOF(JSAMPROW));
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Allocate the actual buffer space (3 row groups) for this component.
* We make the buffer wide enough to allow the downsampler to edge-expand
* horizontally within the buffer, if it so chooses.
*/
true_buffer = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
cinfo->max_h_samp_factor) / compptr->h_samp_factor),
(JDIMENSION) (3 * rgroup_height));
/* Copy true buffer row pointers into the middle of the fake row array */
MEMCOPY(fake_buffer + rgroup_height, true_buffer,
3 * rgroup_height * SIZEOF(JSAMPROW));
/* Fill in the above and below wraparound pointers */
for (i = 0; i < rgroup_height; i++) {
fake_buffer[i] = true_buffer[2 * rgroup_height + i];
fake_buffer[4 * rgroup_height + i] = true_buffer[i];
}
prep->color_buf[ci] = fake_buffer + rgroup_height;
fake_buffer += 5 * rgroup_height; /* point to space for next component */
}
}
#endif /* CONTEXT_ROWS_SUPPORTED */
/*
* Initialize preprocessing controller.
*/
GLOBAL(void)
jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
{
my_prep_ptr prep;
int ci;
jpeg_component_info * compptr;
if (need_full_buffer) /* safety check */
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
prep = (my_prep_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_prep_controller));
cinfo->prep = (struct jpeg_c_prep_controller *) prep;
prep->pub.start_pass = start_pass_prep;
/* Allocate the color conversion buffer.
* We make the buffer wide enough to allow the downsampler to edge-expand
* horizontally within the buffer, if it so chooses.
*/
if (cinfo->downsample->need_context_rows) {
/* Set up to provide context rows */
#ifdef CONTEXT_ROWS_SUPPORTED
prep->pub.pre_process_data = pre_process_context;
create_context_buffer(cinfo);
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
} else {
/* No context, just make it tall enough for one row group */
prep->pub.pre_process_data = pre_process_data;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
cinfo->max_h_samp_factor) / compptr->h_samp_factor),
(JDIMENSION) cinfo->max_v_samp_factor);
}
}
}

View File

@@ -1,13 +1,29 @@
/*
* jcsample.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1996, Thomas G. Lane.
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains downsampling routines.
* These routines are invoked via the downsample and
* downsample_init/term methods.
*
* Downsampling input data is counted in "row groups". A row group
* is defined to be max_v_samp_factor pixel rows of each component,
* from which the downsampler produces v_samp_factor sample rows.
* A single row group is processed in each call to the downsampler module.
*
* The downsampler is responsible for edge-expansion of its output data
* to fill an integral number of DCT blocks horizontally. The source buffer
* may be modified if it is helpful for this purpose (the source buffer is
* allocated wide enough to correspond to the desired output width).
* The caller (the prep controller) is responsible for vertical padding.
*
* The downsampler may request "context rows" by setting need_context_rows
* during startup. In this case, the input arrays will contain at least
* one row group's worth of pixels above and below the passed-in data;
* the caller will create dummy rows at image top and bottom by replicating
* the first or last real pixel row.
*
* An excellent reference for image resampling is
* Digital Image Warping, George Wolberg, 1990.
@@ -30,55 +46,122 @@
* Currently, smoothing is only supported for 2h2v sampling factors.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jsimd.h"
/* Pointer to routine to downsample a single component */
typedef JMETHOD(void, downsample1_ptr,
(j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY output_data));
/* Private subobject */
typedef struct {
struct jpeg_downsampler pub; /* public fields */
/* Downsampling method pointers, one per component */
downsample1_ptr methods[MAX_COMPONENTS];
} my_downsampler;
typedef my_downsampler * my_downsample_ptr;
/*
* Initialize for downsampling a scan.
* Initialize for a downsampling pass.
*/
METHODDEF void
downsample_init (compress_info_ptr cinfo)
METHODDEF(void)
start_pass_downsample (j_compress_ptr cinfo)
{
/* no work for now */
}
/*
* Expand a component horizontally from width input_cols to width output_cols,
* by duplicating the rightmost samples.
*/
LOCAL(void)
expand_right_edge (JSAMPARRAY image_data, int num_rows,
JDIMENSION input_cols, JDIMENSION output_cols)
{
register JSAMPROW ptr;
register JSAMPLE pixval;
register int count;
int row;
int numcols = (int) (output_cols - input_cols);
if (numcols > 0) {
for (row = 0; row < num_rows; row++) {
ptr = image_data[row] + input_cols;
pixval = ptr[-1]; /* don't need GETJSAMPLE() here */
for (count = numcols; count > 0; count--)
*ptr++ = pixval;
}
}
}
/*
* Do downsampling for a whole row group (all components).
*
* In this version we simply downsample each component independently.
*/
METHODDEF(void)
sep_downsample (j_compress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION in_row_index,
JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)
{
my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
int ci;
jpeg_component_info * compptr;
JSAMPARRAY in_ptr, out_ptr;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
in_ptr = input_buf[ci] + in_row_index;
out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor);
(*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);
}
}
/*
* Downsample pixel values of a single component.
* One row group is processed per call.
* This version handles arbitrary integral sampling ratios, without smoothing.
* Note that this version is not actually used for customary sampling ratios.
*/
METHODDEF void
int_downsample (compress_info_ptr cinfo, int which_component,
long input_cols, int input_rows,
long output_cols, int output_rows,
JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
JSAMPARRAY output_data)
METHODDEF(void)
int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY output_data)
{
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
long outcol, outcol_h; /* outcol_h == outcol*h_expand */
JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
JSAMPROW inptr, outptr;
INT32 outvalue;
#ifdef DEBUG /* for debugging pipeline controller */
if (output_rows != compptr->v_samp_factor ||
input_rows != cinfo->max_v_samp_factor ||
(output_cols % compptr->h_samp_factor) != 0 ||
(input_cols % cinfo->max_h_samp_factor) != 0 ||
input_cols*compptr->h_samp_factor != output_cols*cinfo->max_h_samp_factor)
ERREXIT(cinfo->emethods, "Bogus downsample parameters");
#endif
h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
numpix = h_expand * v_expand;
numpix2 = numpix/2;
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
expand_right_edge(input_data, cinfo->max_v_samp_factor,
cinfo->image_width, output_cols * h_expand);
inrow = 0;
for (outrow = 0; outrow < output_rows; outrow++) {
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
for (outcol = 0, outcol_h = 0; outcol < output_cols;
outcol++, outcol_h += h_expand) {
@@ -98,37 +181,60 @@ int_downsample (compress_info_ptr cinfo, int which_component,
/*
* Downsample pixel values of a single component.
* This version handles the common case of 2:1 horizontal and 1:1 vertical,
* This version handles the special case of a full-size component,
* without smoothing.
*/
METHODDEF void
h2v1_downsample (compress_info_ptr cinfo, int which_component,
long input_cols, int input_rows,
long output_cols, int output_rows,
JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
JSAMPARRAY output_data)
METHODDEF(void)
fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY output_data)
{
/* Copy the data */
jcopy_sample_rows(input_data, 0, output_data, 0,
cinfo->max_v_samp_factor, cinfo->image_width);
/* Edge-expand */
expand_right_edge(output_data, cinfo->max_v_samp_factor,
cinfo->image_width, compptr->width_in_blocks * DCTSIZE);
}
/*
* Downsample pixel values of a single component.
* This version handles the common case of 2:1 horizontal and 1:1 vertical,
* without smoothing.
*
* A note about the "bias" calculations: when rounding fractional values to
* integer, we do not want to always round 0.5 up to the next integer.
* If we did that, we'd introduce a noticeable bias towards larger values.
* Instead, this code is arranged so that 0.5 will be rounded up or down at
* alternate pixel locations (a simple ordered dither pattern).
*/
METHODDEF(void)
h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int outrow;
long outcol;
JDIMENSION outcol;
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
register JSAMPROW inptr, outptr;
register int bias;
#ifdef DEBUG /* for debugging pipeline controller */
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
if (output_rows != compptr->v_samp_factor ||
input_rows != cinfo->max_v_samp_factor ||
(output_cols % compptr->h_samp_factor) != 0 ||
(input_cols % cinfo->max_h_samp_factor) != 0 ||
input_cols*compptr->h_samp_factor != output_cols*cinfo->max_h_samp_factor)
ERREXIT(cinfo->emethods, "Bogus downsample parameters");
#endif
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
expand_right_edge(input_data, cinfo->max_v_samp_factor,
cinfo->image_width, output_cols * 2);
for (outrow = 0; outrow < output_rows; outrow++) {
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
inptr = input_data[outrow];
bias = 0; /* bias = 0,1,0,1,... for successive samples */
for (outcol = 0; outcol < output_cols; outcol++) {
*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])
+ 1) >> 1);
+ bias) >> 1);
bias ^= 1; /* 0=>1, 1=>0 */
inptr += 2;
}
}
@@ -141,36 +247,34 @@ h2v1_downsample (compress_info_ptr cinfo, int which_component,
* without smoothing.
*/
METHODDEF void
h2v2_downsample (compress_info_ptr cinfo, int which_component,
long input_cols, int input_rows,
long output_cols, int output_rows,
JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
JSAMPARRAY output_data)
METHODDEF(void)
h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int inrow, outrow;
long outcol;
JDIMENSION outcol;
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
register JSAMPROW inptr0, inptr1, outptr;
register int bias;
#ifdef DEBUG /* for debugging pipeline controller */
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
if (output_rows != compptr->v_samp_factor ||
input_rows != cinfo->max_v_samp_factor ||
(output_cols % compptr->h_samp_factor) != 0 ||
(input_cols % cinfo->max_h_samp_factor) != 0 ||
input_cols*compptr->h_samp_factor != output_cols*cinfo->max_h_samp_factor)
ERREXIT(cinfo->emethods, "Bogus downsample parameters");
#endif
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
expand_right_edge(input_data, cinfo->max_v_samp_factor,
cinfo->image_width, output_cols * 2);
inrow = 0;
for (outrow = 0; outrow < output_rows; outrow++) {
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
inptr0 = input_data[inrow];
inptr1 = input_data[inrow+1];
bias = 1; /* bias = 1,2,1,2,... for successive samples */
for (outcol = 0; outcol < output_cols; outcol++) {
*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])
+ 2) >> 2);
+ bias) >> 2);
bias ^= 3; /* 1=>2, 2=>1 */
inptr0 += 2; inptr1 += 2;
}
inrow += 2;
@@ -178,57 +282,30 @@ h2v2_downsample (compress_info_ptr cinfo, int which_component,
}
/*
* Downsample pixel values of a single component.
* This version handles the special case of a full-size component,
* without smoothing.
*/
METHODDEF void
fullsize_downsample (compress_info_ptr cinfo, int which_component,
long input_cols, int input_rows,
long output_cols, int output_rows,
JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
JSAMPARRAY output_data)
{
#ifdef DEBUG /* for debugging pipeline controller */
if (input_cols != output_cols || input_rows != output_rows)
ERREXIT(cinfo->emethods, "Pipeline controller messed up");
#endif
jcopy_sample_rows(input_data, 0, output_data, 0, output_rows, output_cols);
}
#ifdef INPUT_SMOOTHING_SUPPORTED
/*
* Downsample pixel values of a single component.
* This version handles the standard case of 2:1 horizontal and 2:1 vertical,
* with smoothing.
* with smoothing. One row of context is required.
*/
METHODDEF void
h2v2_smooth_downsample (compress_info_ptr cinfo, int which_component,
long input_cols, int input_rows,
long output_cols, int output_rows,
JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
JSAMPARRAY output_data)
METHODDEF(void)
h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int inrow, outrow;
long colctr;
JDIMENSION colctr;
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
INT32 membersum, neighsum, memberscale, neighscale;
#ifdef DEBUG /* for debugging pipeline controller */
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
if (output_rows != compptr->v_samp_factor ||
input_rows != cinfo->max_v_samp_factor ||
(output_cols % compptr->h_samp_factor) != 0 ||
(input_cols % cinfo->max_h_samp_factor) != 0 ||
input_cols*compptr->h_samp_factor != output_cols*cinfo->max_h_samp_factor)
ERREXIT(cinfo->emethods, "Bogus downsample parameters");
#endif
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
cinfo->image_width, output_cols * 2);
/* We don't bother to form the individual "smoothed" input pixel values;
* we can directly compute the output which is the average of the four
@@ -247,17 +324,11 @@ h2v2_smooth_downsample (compress_info_ptr cinfo, int which_component,
neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */
inrow = 0;
for (outrow = 0; outrow < output_rows; outrow++) {
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
inptr0 = input_data[inrow];
inptr1 = input_data[inrow+1];
if (inrow == 0)
above_ptr = above[input_rows-1];
else
above_ptr = input_data[inrow-1];
if (inrow >= input_rows-2)
below_ptr = below[0];
else
below_ptr = input_data[inrow+2];
/* Special case for first column: pretend column -1 is same as column 0 */
@@ -271,7 +342,7 @@ h2v2_smooth_downsample (compress_info_ptr cinfo, int which_component,
neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
membersum = membersum * memberscale + neighsum * neighscale;
*outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16);
*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
for (colctr = output_cols - 2; colctr > 0; colctr--) {
@@ -291,7 +362,7 @@ h2v2_smooth_downsample (compress_info_ptr cinfo, int which_component,
/* form final output scaled up by 2^16 */
membersum = membersum * memberscale + neighsum * neighscale;
/* round, descale and output it */
*outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16);
*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
}
@@ -306,7 +377,7 @@ h2v2_smooth_downsample (compress_info_ptr cinfo, int which_component,
neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
membersum = membersum * memberscale + neighsum * neighscale;
*outptr = (JSAMPLE) ((membersum + 32768L) >> 16);
*outptr = (JSAMPLE) ((membersum + 32768) >> 16);
inrow += 2;
}
@@ -316,26 +387,26 @@ h2v2_smooth_downsample (compress_info_ptr cinfo, int which_component,
/*
* Downsample pixel values of a single component.
* This version handles the special case of a full-size component,
* with smoothing.
* with smoothing. One row of context is required.
*/
METHODDEF void
fullsize_smooth_downsample (compress_info_ptr cinfo, int which_component,
long input_cols, int input_rows,
long output_cols, int output_rows,
JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
JSAMPARRAY output_data)
METHODDEF(void)
fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int outrow;
long colctr;
JDIMENSION colctr;
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
register JSAMPROW inptr, above_ptr, below_ptr, outptr;
INT32 membersum, neighsum, memberscale, neighscale;
int colsum, lastcolsum, nextcolsum;
#ifdef DEBUG /* for debugging pipeline controller */
if (input_cols != output_cols || input_rows != output_rows)
ERREXIT(cinfo->emethods, "Pipeline controller messed up");
#endif
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
cinfo->image_width, output_cols);
/* Each of the eight neighbor pixels contributes a fraction SF to the
* smoothed pixel, while the main pixel contributes (1-8*SF). In order
@@ -346,16 +417,10 @@ fullsize_smooth_downsample (compress_info_ptr cinfo, int which_component,
memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */
neighscale = cinfo->smoothing_factor * 64; /* scaled SF */
for (outrow = 0; outrow < output_rows; outrow++) {
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
inptr = input_data[outrow];
if (outrow == 0)
above_ptr = above[input_rows-1];
else
above_ptr = input_data[outrow-1];
if (outrow >= input_rows-1)
below_ptr = below[0];
else
below_ptr = input_data[outrow+1];
/* Special case for first column */
@@ -366,7 +431,7 @@ fullsize_smooth_downsample (compress_info_ptr cinfo, int which_component,
GETJSAMPLE(*inptr);
neighsum = colsum + (colsum - membersum) + nextcolsum;
membersum = membersum * memberscale + neighsum * neighscale;
*outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16);
*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
lastcolsum = colsum; colsum = nextcolsum;
for (colctr = output_cols - 2; colctr > 0; colctr--) {
@@ -376,7 +441,7 @@ fullsize_smooth_downsample (compress_info_ptr cinfo, int which_component,
GETJSAMPLE(*inptr);
neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
membersum = membersum * memberscale + neighsum * neighscale;
*outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16);
*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
lastcolsum = colsum; colsum = nextcolsum;
}
@@ -384,7 +449,7 @@ fullsize_smooth_downsample (compress_info_ptr cinfo, int which_component,
membersum = GETJSAMPLE(*inptr);
neighsum = lastcolsum + (colsum - membersum) + colsum;
membersum = membersum * memberscale + neighsum * neighscale;
*outptr = (JSAMPLE) ((membersum + 32768L) >> 16);
*outptr = (JSAMPLE) ((membersum + 32768) >> 16);
}
}
@@ -393,68 +458,70 @@ fullsize_smooth_downsample (compress_info_ptr cinfo, int which_component,
/*
* Clean up after a scan.
*/
METHODDEF void
downsample_term (compress_info_ptr cinfo)
{
/* no work for now */
}
/*
* The method selection routine for downsampling.
* Module initialization routine for downsampling.
* Note that we must select a routine for each component.
*/
GLOBAL void
jseldownsample (compress_info_ptr cinfo)
GLOBAL(void)
jinit_downsampler (j_compress_ptr cinfo)
{
short ci;
my_downsample_ptr downsample;
int ci;
jpeg_component_info * compptr;
boolean smoothok = TRUE;
if (cinfo->CCIR601_sampling)
ERREXIT(cinfo->emethods, "CCIR601 downsampling not implemented yet");
downsample = (my_downsample_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_downsampler));
cinfo->downsample = (struct jpeg_downsampler *) downsample;
downsample->pub.start_pass = start_pass_downsample;
downsample->pub.downsample = sep_downsample;
downsample->pub.need_context_rows = FALSE;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
if (cinfo->CCIR601_sampling)
ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
/* Verify we can handle the sampling factors, and set up method pointers */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
compptr->v_samp_factor == cinfo->max_v_samp_factor) {
#ifdef INPUT_SMOOTHING_SUPPORTED
if (cinfo->smoothing_factor)
cinfo->methods->downsample[ci] = fullsize_smooth_downsample;
else
if (cinfo->smoothing_factor) {
downsample->methods[ci] = fullsize_smooth_downsample;
downsample->pub.need_context_rows = TRUE;
} else
#endif
cinfo->methods->downsample[ci] = fullsize_downsample;
downsample->methods[ci] = fullsize_downsample;
} else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
compptr->v_samp_factor == cinfo->max_v_samp_factor) {
smoothok = FALSE;
cinfo->methods->downsample[ci] = h2v1_downsample;
if (jsimd_can_h2v1_downsample())
downsample->methods[ci] = jsimd_h2v1_downsample;
else
downsample->methods[ci] = h2v1_downsample;
} else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) {
#ifdef INPUT_SMOOTHING_SUPPORTED
if (cinfo->smoothing_factor)
cinfo->methods->downsample[ci] = h2v2_smooth_downsample;
else
if (cinfo->smoothing_factor) {
downsample->methods[ci] = h2v2_smooth_downsample;
downsample->pub.need_context_rows = TRUE;
} else
#endif
cinfo->methods->downsample[ci] = h2v2_downsample;
if (jsimd_can_h2v2_downsample())
downsample->methods[ci] = jsimd_h2v2_downsample;
else
downsample->methods[ci] = h2v2_downsample;
} else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
(cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) {
smoothok = FALSE;
cinfo->methods->downsample[ci] = int_downsample;
downsample->methods[ci] = int_downsample;
} else
ERREXIT(cinfo->emethods, "Fractional downsampling not implemented yet");
ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
}
#ifdef INPUT_SMOOTHING_SUPPORTED
if (cinfo->smoothing_factor && !smoothok)
TRACEMS(cinfo->emethods, 0,
"Smoothing not supported with nonstandard sampling ratios");
TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);
#endif
cinfo->methods->downsample_init = downsample_init;
cinfo->methods->downsample_term = downsample_term;
}

388
jctrans.c Normal file
View File

@@ -0,0 +1,388 @@
/*
* jctrans.c
*
* Copyright (C) 1995-1998, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains library routines for transcoding compression,
* that is, writing raw DCT coefficient arrays to an output JPEG file.
* The routines in jcapimin.c will also be needed by a transcoder.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Forward declarations */
LOCAL(void) transencode_master_selection
JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
LOCAL(void) transencode_coef_controller
JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
/*
* Compression initialization for writing raw-coefficient data.
* Before calling this, all parameters and a data destination must be set up.
* Call jpeg_finish_compress() to actually write the data.
*
* The number of passed virtual arrays must match cinfo->num_components.
* Note that the virtual arrays need not be filled or even realized at
* the time write_coefficients is called; indeed, if the virtual arrays
* were requested from this compression object's memory manager, they
* typically will be realized during this routine and filled afterwards.
*/
GLOBAL(void)
jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)
{
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* Mark all tables to be written */
jpeg_suppress_tables(cinfo, FALSE);
/* (Re)initialize error mgr and destination modules */
(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
(*cinfo->dest->init_destination) (cinfo);
/* Perform master selection of active modules */
transencode_master_selection(cinfo, coef_arrays);
/* Wait for jpeg_finish_compress() call */
cinfo->next_scanline = 0; /* so jpeg_write_marker works */
cinfo->global_state = CSTATE_WRCOEFS;
}
/*
* Initialize the compression object with default parameters,
* then copy from the source object all parameters needed for lossless
* transcoding. Parameters that can be varied without loss (such as
* scan script and Huffman optimization) are left in their default states.
*/
GLOBAL(void)
jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
j_compress_ptr dstinfo)
{
JQUANT_TBL ** qtblptr;
jpeg_component_info *incomp, *outcomp;
JQUANT_TBL *c_quant, *slot_quant;
int tblno, ci, coefi;
/* Safety check to ensure start_compress not called yet. */
if (dstinfo->global_state != CSTATE_START)
ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state);
/* Copy fundamental image dimensions */
dstinfo->image_width = srcinfo->image_width;
dstinfo->image_height = srcinfo->image_height;
dstinfo->input_components = srcinfo->num_components;
dstinfo->in_color_space = srcinfo->jpeg_color_space;
/* Initialize all parameters to default values */
jpeg_set_defaults(dstinfo);
/* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB.
* Fix it to get the right header markers for the image colorspace.
*/
jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space);
dstinfo->data_precision = srcinfo->data_precision;
dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling;
/* Copy the source's quantization tables. */
for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
if (srcinfo->quant_tbl_ptrs[tblno] != NULL) {
qtblptr = & dstinfo->quant_tbl_ptrs[tblno];
if (*qtblptr == NULL)
*qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo);
MEMCOPY((*qtblptr)->quantval,
srcinfo->quant_tbl_ptrs[tblno]->quantval,
SIZEOF((*qtblptr)->quantval));
(*qtblptr)->sent_table = FALSE;
}
}
/* Copy the source's per-component info.
* Note we assume jpeg_set_defaults has allocated the dest comp_info array.
*/
dstinfo->num_components = srcinfo->num_components;
if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS)
ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components,
MAX_COMPONENTS);
for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info;
ci < dstinfo->num_components; ci++, incomp++, outcomp++) {
outcomp->component_id = incomp->component_id;
outcomp->h_samp_factor = incomp->h_samp_factor;
outcomp->v_samp_factor = incomp->v_samp_factor;
outcomp->quant_tbl_no = incomp->quant_tbl_no;
/* Make sure saved quantization table for component matches the qtable
* slot. If not, the input file re-used this qtable slot.
* IJG encoder currently cannot duplicate this.
*/
tblno = outcomp->quant_tbl_no;
if (tblno < 0 || tblno >= NUM_QUANT_TBLS ||
srcinfo->quant_tbl_ptrs[tblno] == NULL)
ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno);
slot_quant = srcinfo->quant_tbl_ptrs[tblno];
c_quant = incomp->quant_table;
if (c_quant != NULL) {
for (coefi = 0; coefi < DCTSIZE2; coefi++) {
if (c_quant->quantval[coefi] != slot_quant->quantval[coefi])
ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno);
}
}
/* Note: we do not copy the source's Huffman table assignments;
* instead we rely on jpeg_set_colorspace to have made a suitable choice.
*/
}
/* Also copy JFIF version and resolution information, if available.
* Strictly speaking this isn't "critical" info, but it's nearly
* always appropriate to copy it if available. In particular,
* if the application chooses to copy JFIF 1.02 extension markers from
* the source file, we need to copy the version to make sure we don't
* emit a file that has 1.02 extensions but a claimed version of 1.01.
* We will *not*, however, copy version info from mislabeled "2.01" files.
*/
if (srcinfo->saw_JFIF_marker) {
if (srcinfo->JFIF_major_version == 1) {
dstinfo->JFIF_major_version = srcinfo->JFIF_major_version;
dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version;
}
dstinfo->density_unit = srcinfo->density_unit;
dstinfo->X_density = srcinfo->X_density;
dstinfo->Y_density = srcinfo->Y_density;
}
}
/*
* Master selection of compression modules for transcoding.
* This substitutes for jcinit.c's initialization of the full compressor.
*/
LOCAL(void)
transencode_master_selection (j_compress_ptr cinfo,
jvirt_barray_ptr * coef_arrays)
{
/* Although we don't actually use input_components for transcoding,
* jcmaster.c's initial_setup will complain if input_components is 0.
*/
cinfo->input_components = 1;
/* Initialize master control (includes parameter checking/processing) */
jinit_c_master_control(cinfo, TRUE /* transcode only */);
/* Entropy encoding: either Huffman or arithmetic coding. */
if (cinfo->arith_code) {
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
} else {
if (cinfo->progressive_mode) {
#ifdef C_PROGRESSIVE_SUPPORTED
jinit_phuff_encoder(cinfo);
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
} else
jinit_huff_encoder(cinfo);
}
/* We need a special coefficient buffer controller. */
transencode_coef_controller(cinfo, coef_arrays);
jinit_marker_writer(cinfo);
/* We can now tell the memory manager to allocate virtual arrays. */
(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
/* Write the datastream header (SOI, JFIF) immediately.
* Frame and scan headers are postponed till later.
* This lets application insert special markers after the SOI.
*/
(*cinfo->marker->write_file_header) (cinfo);
}
/*
* The rest of this file is a special implementation of the coefficient
* buffer controller. This is similar to jccoefct.c, but it handles only
* output from presupplied virtual arrays. Furthermore, we generate any
* dummy padding blocks on-the-fly rather than expecting them to be present
* in the arrays.
*/
/* Private buffer controller object */
typedef struct {
struct jpeg_c_coef_controller pub; /* public fields */
JDIMENSION iMCU_row_num; /* iMCU row # within image */
JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
int MCU_vert_offset; /* counts MCU rows within iMCU row */
int MCU_rows_per_iMCU_row; /* number of such rows needed */
/* Virtual block array for each component. */
jvirt_barray_ptr * whole_image;
/* Workspace for constructing dummy blocks at right/bottom edges. */
JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU];
} my_coef_controller;
typedef my_coef_controller * my_coef_ptr;
LOCAL(void)
start_iMCU_row (j_compress_ptr cinfo)
/* Reset within-iMCU-row counters for a new row */
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
/* In an interleaved scan, an MCU row is the same as an iMCU row.
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
* But at the bottom of the image, process only what's left.
*/
if (cinfo->comps_in_scan > 1) {
coef->MCU_rows_per_iMCU_row = 1;
} else {
if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
else
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
}
coef->mcu_ctr = 0;
coef->MCU_vert_offset = 0;
}
/*
* Initialize for a processing pass.
*/
METHODDEF(void)
start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
if (pass_mode != JBUF_CRANK_DEST)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
coef->iMCU_row_num = 0;
start_iMCU_row(cinfo);
}
/*
* Process some data.
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
* per call, ie, v_samp_factor block rows for each component in the scan.
* The data is obtained from the virtual arrays and fed to the entropy coder.
* Returns TRUE if the iMCU row is completed, FALSE if suspended.
*
* NB: input_buf is ignored; it is likely to be a NULL pointer.
*/
METHODDEF(boolean)
compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
int blkn, ci, xindex, yindex, yoffset, blockcnt;
JDIMENSION start_col;
JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
JBLOCKROW buffer_ptr;
jpeg_component_info *compptr;
/* Align the virtual buffers for the components used in this scan. */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
buffer[ci] = (*cinfo->mem->access_virt_barray)
((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
coef->iMCU_row_num * compptr->v_samp_factor,
(JDIMENSION) compptr->v_samp_factor, FALSE);
}
/* Loop to process one whole iMCU row */
for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
yoffset++) {
for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
MCU_col_num++) {
/* Construct list of pointers to DCT blocks belonging to this MCU */
blkn = 0; /* index of current DCT block within MCU */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
start_col = MCU_col_num * compptr->MCU_width;
blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
: compptr->last_col_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
if (coef->iMCU_row_num < last_iMCU_row ||
yindex+yoffset < compptr->last_row_height) {
/* Fill in pointers to real blocks in this row */
buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
for (xindex = 0; xindex < blockcnt; xindex++)
MCU_buffer[blkn++] = buffer_ptr++;
} else {
/* At bottom of image, need a whole row of dummy blocks */
xindex = 0;
}
/* Fill in any dummy blocks needed in this row.
* Dummy blocks are filled in the same way as in jccoefct.c:
* all zeroes in the AC entries, DC entries equal to previous
* block's DC value. The init routine has already zeroed the
* AC entries, so we need only set the DC entries correctly.
*/
for (; xindex < compptr->MCU_width; xindex++) {
MCU_buffer[blkn] = coef->dummy_buffer[blkn];
MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0];
blkn++;
}
}
}
/* Try to write the MCU. */
if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->mcu_ctr = MCU_col_num;
return FALSE;
}
}
/* Completed an MCU row, but perhaps not an iMCU row */
coef->mcu_ctr = 0;
}
/* Completed the iMCU row, advance counters for next one */
coef->iMCU_row_num++;
start_iMCU_row(cinfo);
return TRUE;
}
/*
* Initialize coefficient buffer controller.
*
* Each passed coefficient array must be the right size for that
* coefficient: width_in_blocks wide and height_in_blocks high,
* with unitheight at least v_samp_factor.
*/
LOCAL(void)
transencode_coef_controller (j_compress_ptr cinfo,
jvirt_barray_ptr * coef_arrays)
{
my_coef_ptr coef;
JBLOCKROW buffer;
int i;
coef = (my_coef_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_coef_controller));
cinfo->coef = (struct jpeg_c_coef_controller *) coef;
coef->pub.start_pass = start_pass_coef;
coef->pub.compress_data = compress_output;
/* Save pointer to virtual arrays */
coef->whole_image = coef_arrays;
/* Allocate and pre-zero space for dummy DCT blocks. */
buffer = (JBLOCKROW)
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
coef->dummy_buffer[i] = buffer + i;
}
}

395
jdapimin.c Normal file
View File

@@ -0,0 +1,395 @@
/*
* jdapimin.c
*
* Copyright (C) 1994-1998, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains application interface code for the decompression half
* of the JPEG library. These are the "minimum" API routines that may be
* needed in either the normal full-decompression case or the
* transcoding-only case.
*
* Most of the routines intended to be called directly by an application
* are in this file or in jdapistd.c. But also see jcomapi.c for routines
* shared by compression and decompression, and jdtrans.c for the transcoding
* case.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* Initialization of a JPEG decompression object.
* The error manager must already be set up (in case memory manager fails).
*/
GLOBAL(void)
jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
{
int i;
/* Guard against version mismatches between library and caller. */
cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
if (version != JPEG_LIB_VERSION)
ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
if (structsize != SIZEOF(struct jpeg_decompress_struct))
ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
(int) SIZEOF(struct jpeg_decompress_struct), (int) structsize);
/* For debugging purposes, we zero the whole master structure.
* But the application has already set the err pointer, and may have set
* client_data, so we have to save and restore those fields.
* Note: if application hasn't set client_data, tools like Purify may
* complain here.
*/
{
struct jpeg_error_mgr * err = cinfo->err;
void * client_data = cinfo->client_data; /* ignore Purify complaint here */
MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct));
cinfo->err = err;
cinfo->client_data = client_data;
}
cinfo->is_decompressor = TRUE;
/* Initialize a memory manager instance for this object */
jinit_memory_mgr((j_common_ptr) cinfo);
/* Zero out pointers to permanent structures. */
cinfo->progress = NULL;
cinfo->src = NULL;
for (i = 0; i < NUM_QUANT_TBLS; i++)
cinfo->quant_tbl_ptrs[i] = NULL;
for (i = 0; i < NUM_HUFF_TBLS; i++) {
cinfo->dc_huff_tbl_ptrs[i] = NULL;
cinfo->ac_huff_tbl_ptrs[i] = NULL;
}
/* Initialize marker processor so application can override methods
* for COM, APPn markers before calling jpeg_read_header.
*/
cinfo->marker_list = NULL;
jinit_marker_reader(cinfo);
/* And initialize the overall input controller. */
jinit_input_controller(cinfo);
/* OK, I'm ready */
cinfo->global_state = DSTATE_START;
}
/*
* Destruction of a JPEG decompression object
*/
GLOBAL(void)
jpeg_destroy_decompress (j_decompress_ptr cinfo)
{
jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
}
/*
* Abort processing of a JPEG decompression operation,
* but don't destroy the object itself.
*/
GLOBAL(void)
jpeg_abort_decompress (j_decompress_ptr cinfo)
{
jpeg_abort((j_common_ptr) cinfo); /* use common routine */
}
/*
* Set default decompression parameters.
*/
LOCAL(void)
default_decompress_parms (j_decompress_ptr cinfo)
{
/* Guess the input colorspace, and set output colorspace accordingly. */
/* (Wish JPEG committee had provided a real way to specify this...) */
/* Note application may override our guesses. */
switch (cinfo->num_components) {
case 1:
cinfo->jpeg_color_space = JCS_GRAYSCALE;
cinfo->out_color_space = JCS_GRAYSCALE;
break;
case 3:
if (cinfo->saw_JFIF_marker) {
cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */
} else if (cinfo->saw_Adobe_marker) {
switch (cinfo->Adobe_transform) {
case 0:
cinfo->jpeg_color_space = JCS_RGB;
break;
case 1:
cinfo->jpeg_color_space = JCS_YCbCr;
break;
default:
WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
break;
}
} else {
/* Saw no special markers, try to guess from the component IDs */
int cid0 = cinfo->comp_info[0].component_id;
int cid1 = cinfo->comp_info[1].component_id;
int cid2 = cinfo->comp_info[2].component_id;
if (cid0 == 1 && cid1 == 2 && cid2 == 3)
cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */
else if (cid0 == 82 && cid1 == 71 && cid2 == 66)
cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
else {
TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2);
cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
}
}
/* Always guess RGB is proper output colorspace. */
cinfo->out_color_space = JCS_RGB;
break;
case 4:
if (cinfo->saw_Adobe_marker) {
switch (cinfo->Adobe_transform) {
case 0:
cinfo->jpeg_color_space = JCS_CMYK;
break;
case 2:
cinfo->jpeg_color_space = JCS_YCCK;
break;
default:
WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */
break;
}
} else {
/* No special markers, assume straight CMYK. */
cinfo->jpeg_color_space = JCS_CMYK;
}
cinfo->out_color_space = JCS_CMYK;
break;
default:
cinfo->jpeg_color_space = JCS_UNKNOWN;
cinfo->out_color_space = JCS_UNKNOWN;
break;
}
/* Set defaults for other decompression parameters. */
cinfo->scale_num = 1; /* 1:1 scaling */
cinfo->scale_denom = 1;
cinfo->output_gamma = 1.0;
cinfo->buffered_image = FALSE;
cinfo->raw_data_out = FALSE;
cinfo->dct_method = JDCT_DEFAULT;
cinfo->do_fancy_upsampling = TRUE;
cinfo->do_block_smoothing = TRUE;
cinfo->quantize_colors = FALSE;
/* We set these in case application only sets quantize_colors. */
cinfo->dither_mode = JDITHER_FS;
#ifdef QUANT_2PASS_SUPPORTED
cinfo->two_pass_quantize = TRUE;
#else
cinfo->two_pass_quantize = FALSE;
#endif
cinfo->desired_number_of_colors = 256;
cinfo->colormap = NULL;
/* Initialize for no mode change in buffered-image mode. */
cinfo->enable_1pass_quant = FALSE;
cinfo->enable_external_quant = FALSE;
cinfo->enable_2pass_quant = FALSE;
}
/*
* Decompression startup: read start of JPEG datastream to see what's there.
* Need only initialize JPEG object and supply a data source before calling.
*
* This routine will read as far as the first SOS marker (ie, actual start of
* compressed data), and will save all tables and parameters in the JPEG
* object. It will also initialize the decompression parameters to default
* values, and finally return JPEG_HEADER_OK. On return, the application may
* adjust the decompression parameters and then call jpeg_start_decompress.
* (Or, if the application only wanted to determine the image parameters,
* the data need not be decompressed. In that case, call jpeg_abort or
* jpeg_destroy to release any temporary space.)
* If an abbreviated (tables only) datastream is presented, the routine will
* return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then
* re-use the JPEG object to read the abbreviated image datastream(s).
* It is unnecessary (but OK) to call jpeg_abort in this case.
* The JPEG_SUSPENDED return code only occurs if the data source module
* requests suspension of the decompressor. In this case the application
* should load more source data and then re-call jpeg_read_header to resume
* processing.
* If a non-suspending data source is used and require_image is TRUE, then the
* return code need not be inspected since only JPEG_HEADER_OK is possible.
*
* This routine is now just a front end to jpeg_consume_input, with some
* extra error checking.
*/
GLOBAL(int)
jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
{
int retcode;
if (cinfo->global_state != DSTATE_START &&
cinfo->global_state != DSTATE_INHEADER)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
retcode = jpeg_consume_input(cinfo);
switch (retcode) {
case JPEG_REACHED_SOS:
retcode = JPEG_HEADER_OK;
break;
case JPEG_REACHED_EOI:
if (require_image) /* Complain if application wanted an image */
ERREXIT(cinfo, JERR_NO_IMAGE);
/* Reset to start state; it would be safer to require the application to
* call jpeg_abort, but we can't change it now for compatibility reasons.
* A side effect is to free any temporary memory (there shouldn't be any).
*/
jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */
retcode = JPEG_HEADER_TABLES_ONLY;
break;
case JPEG_SUSPENDED:
/* no work */
break;
}
return retcode;
}
/*
* Consume data in advance of what the decompressor requires.
* This can be called at any time once the decompressor object has
* been created and a data source has been set up.
*
* This routine is essentially a state machine that handles a couple
* of critical state-transition actions, namely initial setup and
* transition from header scanning to ready-for-start_decompress.
* All the actual input is done via the input controller's consume_input
* method.
*/
GLOBAL(int)
jpeg_consume_input (j_decompress_ptr cinfo)
{
int retcode = JPEG_SUSPENDED;
/* NB: every possible DSTATE value should be listed in this switch */
switch (cinfo->global_state) {
case DSTATE_START:
/* Start-of-datastream actions: reset appropriate modules */
(*cinfo->inputctl->reset_input_controller) (cinfo);
/* Initialize application's data source module */
(*cinfo->src->init_source) (cinfo);
cinfo->global_state = DSTATE_INHEADER;
/*FALLTHROUGH*/
case DSTATE_INHEADER:
retcode = (*cinfo->inputctl->consume_input) (cinfo);
if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */
/* Set up default parameters based on header data */
default_decompress_parms(cinfo);
/* Set global state: ready for start_decompress */
cinfo->global_state = DSTATE_READY;
}
break;
case DSTATE_READY:
/* Can't advance past first SOS until start_decompress is called */
retcode = JPEG_REACHED_SOS;
break;
case DSTATE_PRELOAD:
case DSTATE_PRESCAN:
case DSTATE_SCANNING:
case DSTATE_RAW_OK:
case DSTATE_BUFIMAGE:
case DSTATE_BUFPOST:
case DSTATE_STOPPING:
retcode = (*cinfo->inputctl->consume_input) (cinfo);
break;
default:
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
}
return retcode;
}
/*
* Have we finished reading the input file?
*/
GLOBAL(boolean)
jpeg_input_complete (j_decompress_ptr cinfo)
{
/* Check for valid jpeg object */
if (cinfo->global_state < DSTATE_START ||
cinfo->global_state > DSTATE_STOPPING)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
return cinfo->inputctl->eoi_reached;
}
/*
* Is there more than one scan?
*/
GLOBAL(boolean)
jpeg_has_multiple_scans (j_decompress_ptr cinfo)
{
/* Only valid after jpeg_read_header completes */
if (cinfo->global_state < DSTATE_READY ||
cinfo->global_state > DSTATE_STOPPING)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
return cinfo->inputctl->has_multiple_scans;
}
/*
* Finish JPEG decompression.
*
* This will normally just verify the file trailer and release temp storage.
*
* Returns FALSE if suspended. The return value need be inspected only if
* a suspending data source is used.
*/
GLOBAL(boolean)
jpeg_finish_decompress (j_decompress_ptr cinfo)
{
if ((cinfo->global_state == DSTATE_SCANNING ||
cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) {
/* Terminate final pass of non-buffered mode */
if (cinfo->output_scanline < cinfo->output_height)
ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
(*cinfo->master->finish_output_pass) (cinfo);
cinfo->global_state = DSTATE_STOPPING;
} else if (cinfo->global_state == DSTATE_BUFIMAGE) {
/* Finishing after a buffered-image operation */
cinfo->global_state = DSTATE_STOPPING;
} else if (cinfo->global_state != DSTATE_STOPPING) {
/* STOPPING = repeat call after a suspension, anything else is error */
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
}
/* Read until EOI */
while (! cinfo->inputctl->eoi_reached) {
if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
return FALSE; /* Suspend, come back later */
}
/* Do final cleanup */
(*cinfo->src->term_source) (cinfo);
/* We can use jpeg_abort to release memory and reset global_state */
jpeg_abort((j_common_ptr) cinfo);
return TRUE;
}

275
jdapistd.c Normal file
View File

@@ -0,0 +1,275 @@
/*
* jdapistd.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains application interface code for the decompression half
* of the JPEG library. These are the "standard" API routines that are
* used in the normal full-decompression case. They are not used by a
* transcoding-only application. Note that if an application links in
* jpeg_start_decompress, it will end up linking in the entire decompressor.
* We thus must separate this file from jdapimin.c to avoid linking the
* whole decompression library into a transcoder.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Forward declarations */
LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo));
/*
* Decompression initialization.
* jpeg_read_header must be completed before calling this.
*
* If a multipass operating mode was selected, this will do all but the
* last pass, and thus may take a great deal of time.
*
* Returns FALSE if suspended. The return value need be inspected only if
* a suspending data source is used.
*/
GLOBAL(boolean)
jpeg_start_decompress (j_decompress_ptr cinfo)
{
if (cinfo->global_state == DSTATE_READY) {
/* First call: initialize master control, select active modules */
jinit_master_decompress(cinfo);
if (cinfo->buffered_image) {
/* No more work here; expecting jpeg_start_output next */
cinfo->global_state = DSTATE_BUFIMAGE;
return TRUE;
}
cinfo->global_state = DSTATE_PRELOAD;
}
if (cinfo->global_state == DSTATE_PRELOAD) {
/* If file has multiple scans, absorb them all into the coef buffer */
if (cinfo->inputctl->has_multiple_scans) {
#ifdef D_MULTISCAN_FILES_SUPPORTED
for (;;) {
int retcode;
/* Call progress monitor hook if present */
if (cinfo->progress != NULL)
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
/* Absorb some more input */
retcode = (*cinfo->inputctl->consume_input) (cinfo);
if (retcode == JPEG_SUSPENDED)
return FALSE;
if (retcode == JPEG_REACHED_EOI)
break;
/* Advance progress counter if appropriate */
if (cinfo->progress != NULL &&
(retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
/* jdmaster underestimated number of scans; ratchet up one scan */
cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
}
}
}
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif /* D_MULTISCAN_FILES_SUPPORTED */
}
cinfo->output_scan_number = cinfo->input_scan_number;
} else if (cinfo->global_state != DSTATE_PRESCAN)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* Perform any dummy output passes, and set up for the final pass */
return output_pass_setup(cinfo);
}
/*
* Set up for an output pass, and perform any dummy pass(es) needed.
* Common subroutine for jpeg_start_decompress and jpeg_start_output.
* Entry: global_state = DSTATE_PRESCAN only if previously suspended.
* Exit: If done, returns TRUE and sets global_state for proper output mode.
* If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN.
*/
LOCAL(boolean)
output_pass_setup (j_decompress_ptr cinfo)
{
if (cinfo->global_state != DSTATE_PRESCAN) {
/* First call: do pass setup */
(*cinfo->master->prepare_for_output_pass) (cinfo);
cinfo->output_scanline = 0;
cinfo->global_state = DSTATE_PRESCAN;
}
/* Loop over any required dummy passes */
while (cinfo->master->is_dummy_pass) {
#ifdef QUANT_2PASS_SUPPORTED
/* Crank through the dummy pass */
while (cinfo->output_scanline < cinfo->output_height) {
JDIMENSION last_scanline;
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
cinfo->progress->pass_counter = (long) cinfo->output_scanline;
cinfo->progress->pass_limit = (long) cinfo->output_height;
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
}
/* Process some data */
last_scanline = cinfo->output_scanline;
(*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL,
&cinfo->output_scanline, (JDIMENSION) 0);
if (cinfo->output_scanline == last_scanline)
return FALSE; /* No progress made, must suspend */
}
/* Finish up dummy pass, and set up for another one */
(*cinfo->master->finish_output_pass) (cinfo);
(*cinfo->master->prepare_for_output_pass) (cinfo);
cinfo->output_scanline = 0;
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif /* QUANT_2PASS_SUPPORTED */
}
/* Ready for application to drive output pass through
* jpeg_read_scanlines or jpeg_read_raw_data.
*/
cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING;
return TRUE;
}
/*
* Read some scanlines of data from the JPEG decompressor.
*
* The return value will be the number of lines actually read.
* This may be less than the number requested in several cases,
* including bottom of image, data source suspension, and operating
* modes that emit multiple scanlines at a time.
*
* Note: we warn about excess calls to jpeg_read_scanlines() since
* this likely signals an application programmer error. However,
* an oversize buffer (max_lines > scanlines remaining) is not an error.
*/
GLOBAL(JDIMENSION)
jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
JDIMENSION max_lines)
{
JDIMENSION row_ctr;
if (cinfo->global_state != DSTATE_SCANNING)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (cinfo->output_scanline >= cinfo->output_height) {
WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
return 0;
}
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
cinfo->progress->pass_counter = (long) cinfo->output_scanline;
cinfo->progress->pass_limit = (long) cinfo->output_height;
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
}
/* Process some data */
row_ctr = 0;
(*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines);
cinfo->output_scanline += row_ctr;
return row_ctr;
}
/*
* Alternate entry point to read raw data.
* Processes exactly one iMCU row per call, unless suspended.
*/
GLOBAL(JDIMENSION)
jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
JDIMENSION max_lines)
{
JDIMENSION lines_per_iMCU_row;
if (cinfo->global_state != DSTATE_RAW_OK)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (cinfo->output_scanline >= cinfo->output_height) {
WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
return 0;
}
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
cinfo->progress->pass_counter = (long) cinfo->output_scanline;
cinfo->progress->pass_limit = (long) cinfo->output_height;
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
}
/* Verify that at least one iMCU row can be returned. */
lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size;
if (max_lines < lines_per_iMCU_row)
ERREXIT(cinfo, JERR_BUFFER_SIZE);
/* Decompress directly into user's buffer. */
if (! (*cinfo->coef->decompress_data) (cinfo, data))
return 0; /* suspension forced, can do nothing more */
/* OK, we processed one iMCU row. */
cinfo->output_scanline += lines_per_iMCU_row;
return lines_per_iMCU_row;
}
/* Additional entry points for buffered-image mode. */
#ifdef D_MULTISCAN_FILES_SUPPORTED
/*
* Initialize for an output pass in buffered-image mode.
*/
GLOBAL(boolean)
jpeg_start_output (j_decompress_ptr cinfo, int scan_number)
{
if (cinfo->global_state != DSTATE_BUFIMAGE &&
cinfo->global_state != DSTATE_PRESCAN)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* Limit scan number to valid range */
if (scan_number <= 0)
scan_number = 1;
if (cinfo->inputctl->eoi_reached &&
scan_number > cinfo->input_scan_number)
scan_number = cinfo->input_scan_number;
cinfo->output_scan_number = scan_number;
/* Perform any dummy output passes, and set up for the real pass */
return output_pass_setup(cinfo);
}
/*
* Finish up after an output pass in buffered-image mode.
*
* Returns FALSE if suspended. The return value need be inspected only if
* a suspending data source is used.
*/
GLOBAL(boolean)
jpeg_finish_output (j_decompress_ptr cinfo)
{
if ((cinfo->global_state == DSTATE_SCANNING ||
cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) {
/* Terminate this pass. */
/* We do not require the whole pass to have been completed. */
(*cinfo->master->finish_output_pass) (cinfo);
cinfo->global_state = DSTATE_BUFPOST;
} else if (cinfo->global_state != DSTATE_BUFPOST) {
/* BUFPOST = repeat call after a suspension, anything else is error */
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
}
/* Read markers looking for SOS or EOI */
while (cinfo->input_scan_number <= cinfo->output_scan_number &&
! cinfo->inputctl->eoi_reached) {
if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
return FALSE; /* Suspend, come back later */
}
cinfo->global_state = DSTATE_BUFIMAGE;
return TRUE;
}
#endif /* D_MULTISCAN_FILES_SUPPORTED */

View File

@@ -1,42 +0,0 @@
/*
* jdarith.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains arithmetic entropy decoding routines.
* These routines are invoked via the methods entropy_decode
* and entropy_decode_init/term.
*/
#include "jinclude.h"
#ifdef D_ARITH_CODING_SUPPORTED
/*
* The arithmetic coding option of the JPEG standard specifies Q-coding,
* which is covered by patents held by IBM (and possibly AT&T and Mitsubishi).
* At this time it does not appear to be legal for the Independent JPEG
* Group to distribute software that implements arithmetic coding.
* We have therefore removed arithmetic coding support from the
* distributed source code.
*
* We're not happy about it either.
*/
/*
* The method selection routine for arithmetic entropy decoding.
*/
GLOBAL void
jseldarithmetic (decompress_info_ptr cinfo)
{
if (cinfo->arith_code) {
ERREXIT(cinfo->emethods, "Sorry, there are legal restrictions on arithmetic coding");
}
}
#endif /* D_ARITH_CODING_SUPPORTED */

151
jdatadst.c Normal file
View File

@@ -0,0 +1,151 @@
/*
* jdatadst.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains compression data destination routines for the case of
* emitting JPEG data to a file (or any stdio stream). While these routines
* are sufficient for most applications, some will want to use a different
* destination manager.
* IMPORTANT: we assume that fwrite() will correctly transcribe an array of
* JOCTETs into 8-bit-wide elements on external storage. If char is wider
* than 8 bits on your machine, you may need to do some tweaking.
*/
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
#include "jinclude.h"
#include "jpeglib.h"
#include "jerror.h"
/* Expanded data destination object for stdio output */
typedef struct {
struct jpeg_destination_mgr pub; /* public fields */
FILE * outfile; /* target stream */
JOCTET * buffer; /* start of buffer */
} my_destination_mgr;
typedef my_destination_mgr * my_dest_ptr;
#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
/*
* Initialize destination --- called by jpeg_start_compress
* before any data is actually written.
*/
METHODDEF(void)
init_destination (j_compress_ptr cinfo)
{
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
/* Allocate the output buffer --- it will be released when done with image */
dest->buffer = (JOCTET *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
}
/*
* Empty the output buffer --- called whenever buffer fills up.
*
* In typical applications, this should write the entire output buffer
* (ignoring the current state of next_output_byte & free_in_buffer),
* reset the pointer & count to the start of the buffer, and return TRUE
* indicating that the buffer has been dumped.
*
* In applications that need to be able to suspend compression due to output
* overrun, a FALSE return indicates that the buffer cannot be emptied now.
* In this situation, the compressor will return to its caller (possibly with
* an indication that it has not accepted all the supplied scanlines). The
* application should resume compression after it has made more room in the
* output buffer. Note that there are substantial restrictions on the use of
* suspension --- see the documentation.
*
* When suspending, the compressor will back up to a convenient restart point
* (typically the start of the current MCU). next_output_byte & free_in_buffer
* indicate where the restart point will be if the current call returns FALSE.
* Data beyond this point will be regenerated after resumption, so do not
* write it out when emptying the buffer externally.
*/
METHODDEF(boolean)
empty_output_buffer (j_compress_ptr cinfo)
{
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) !=
(size_t) OUTPUT_BUF_SIZE)
ERREXIT(cinfo, JERR_FILE_WRITE);
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
return TRUE;
}
/*
* Terminate destination --- called by jpeg_finish_compress
* after all data has been written. Usually needs to flush buffer.
*
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
* application must deal with any cleanup that should happen even
* for error exit.
*/
METHODDEF(void)
term_destination (j_compress_ptr cinfo)
{
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
/* Write any data remaining in the buffer */
if (datacount > 0) {
if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount)
ERREXIT(cinfo, JERR_FILE_WRITE);
}
fflush(dest->outfile);
/* Make sure we wrote the output file OK */
if (ferror(dest->outfile))
ERREXIT(cinfo, JERR_FILE_WRITE);
}
/*
* Prepare for output to a stdio stream.
* The caller must have already opened the stream, and is responsible
* for closing it after finishing compression.
*/
GLOBAL(void)
jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile)
{
my_dest_ptr dest;
/* The destination object is made permanent so that multiple JPEG images
* can be written to the same file without re-executing jpeg_stdio_dest.
* This makes it dangerous to use this manager and a different destination
* manager serially with the same JPEG object, because their private object
* sizes may be different. Caveat programmer.
*/
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
SIZEOF(my_destination_mgr));
}
dest = (my_dest_ptr) cinfo->dest;
dest->pub.init_destination = init_destination;
dest->pub.empty_output_buffer = empty_output_buffer;
dest->pub.term_destination = term_destination;
dest->outfile = outfile;
}

212
jdatasrc.c Normal file
View File

@@ -0,0 +1,212 @@
/*
* jdatasrc.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains decompression data source routines for the case of
* reading JPEG data from a file (or any stdio stream). While these routines
* are sufficient for most applications, some will want to use a different
* source manager.
* IMPORTANT: we assume that fread() will correctly transcribe an array of
* JOCTETs from 8-bit-wide elements on external storage. If char is wider
* than 8 bits on your machine, you may need to do some tweaking.
*/
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
#include "jinclude.h"
#include "jpeglib.h"
#include "jerror.h"
/* Expanded data source object for stdio input */
typedef struct {
struct jpeg_source_mgr pub; /* public fields */
FILE * infile; /* source stream */
JOCTET * buffer; /* start of buffer */
boolean start_of_file; /* have we gotten any data yet? */
} my_source_mgr;
typedef my_source_mgr * my_src_ptr;
#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
/*
* Initialize source --- called by jpeg_read_header
* before any data is actually read.
*/
METHODDEF(void)
init_source (j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
/* We reset the empty-input-file flag for each image,
* but we don't clear the input buffer.
* This is correct behavior for reading a series of images from one source.
*/
src->start_of_file = TRUE;
}
/*
* Fill the input buffer --- called whenever buffer is emptied.
*
* In typical applications, this should read fresh data into the buffer
* (ignoring the current state of next_input_byte & bytes_in_buffer),
* reset the pointer & count to the start of the buffer, and return TRUE
* indicating that the buffer has been reloaded. It is not necessary to
* fill the buffer entirely, only to obtain at least one more byte.
*
* There is no such thing as an EOF return. If the end of the file has been
* reached, the routine has a choice of ERREXIT() or inserting fake data into
* the buffer. In most cases, generating a warning message and inserting a
* fake EOI marker is the best course of action --- this will allow the
* decompressor to output however much of the image is there. However,
* the resulting error message is misleading if the real problem is an empty
* input file, so we handle that case specially.
*
* In applications that need to be able to suspend compression due to input
* not being available yet, a FALSE return indicates that no more data can be
* obtained right now, but more may be forthcoming later. In this situation,
* the decompressor will return to its caller (with an indication of the
* number of scanlines it has read, if any). The application should resume
* decompression after it has loaded more data into the input buffer. Note
* that there are substantial restrictions on the use of suspension --- see
* the documentation.
*
* When suspending, the decompressor will back up to a convenient restart point
* (typically the start of the current MCU). next_input_byte & bytes_in_buffer
* indicate where the restart point will be if the current call returns FALSE.
* Data beyond this point must be rescanned after resumption, so move it to
* the front of the buffer rather than discarding it.
*/
METHODDEF(boolean)
fill_input_buffer (j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
size_t nbytes;
nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);
if (nbytes <= 0) {
if (src->start_of_file) /* Treat empty input file as fatal error */
ERREXIT(cinfo, JERR_INPUT_EMPTY);
WARNMS(cinfo, JWRN_JPEG_EOF);
/* Insert a fake EOI marker */
src->buffer[0] = (JOCTET) 0xFF;
src->buffer[1] = (JOCTET) JPEG_EOI;
nbytes = 2;
}
src->pub.next_input_byte = src->buffer;
src->pub.bytes_in_buffer = nbytes;
src->start_of_file = FALSE;
return TRUE;
}
/*
* Skip data --- used to skip over a potentially large amount of
* uninteresting data (such as an APPn marker).
*
* Writers of suspendable-input applications must note that skip_input_data
* is not granted the right to give a suspension return. If the skip extends
* beyond the data currently in the buffer, the buffer can be marked empty so
* that the next read will cause a fill_input_buffer call that can suspend.
* Arranging for additional bytes to be discarded before reloading the input
* buffer is the application writer's problem.
*/
METHODDEF(void)
skip_input_data (j_decompress_ptr cinfo, long num_bytes)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
/* Just a dumb implementation for now. Could use fseek() except
* it doesn't work on pipes. Not clear that being smart is worth
* any trouble anyway --- large skips are infrequent.
*/
if (num_bytes > 0) {
while (num_bytes > (long) src->pub.bytes_in_buffer) {
num_bytes -= (long) src->pub.bytes_in_buffer;
(void) fill_input_buffer(cinfo);
/* note we assume that fill_input_buffer will never return FALSE,
* so suspension need not be handled.
*/
}
src->pub.next_input_byte += (size_t) num_bytes;
src->pub.bytes_in_buffer -= (size_t) num_bytes;
}
}
/*
* An additional method that can be provided by data source modules is the
* resync_to_restart method for error recovery in the presence of RST markers.
* For the moment, this source module just uses the default resync method
* provided by the JPEG library. That method assumes that no backtracking
* is possible.
*/
/*
* Terminate source --- called by jpeg_finish_decompress
* after all data has been read. Often a no-op.
*
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
* application must deal with any cleanup that should happen even
* for error exit.
*/
METHODDEF(void)
term_source (j_decompress_ptr cinfo)
{
/* no work necessary here */
}
/*
* Prepare for input from a stdio stream.
* The caller must have already opened the stream, and is responsible
* for closing it after finishing decompression.
*/
GLOBAL(void)
jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile)
{
my_src_ptr src;
/* The source object and input buffer are made permanent so that a series
* of JPEG images can be read from the same file by calling jpeg_stdio_src
* only before the first one. (If we discarded the buffer at the end of
* one image, we'd likely lose the start of the next one.)
* This makes it unsafe to use this manager and a different source
* manager serially with the same JPEG object. Caveat programmer.
*/
if (cinfo->src == NULL) { /* first time for this JPEG object? */
cinfo->src = (struct jpeg_source_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
SIZEOF(my_source_mgr));
src = (my_src_ptr) cinfo->src;
src->buffer = (JOCTET *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
INPUT_BUF_SIZE * SIZEOF(JOCTET));
}
src = (my_src_ptr) cinfo->src;
src->pub.init_source = init_source;
src->pub.fill_input_buffer = fill_input_buffer;
src->pub.skip_input_data = skip_input_data;
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
src->pub.term_source = term_source;
src->infile = infile;
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
src->pub.next_input_byte = NULL; /* until buffer loaded */
}

747
jdcoefct.c Normal file
View File

@@ -0,0 +1,747 @@
/*
* jdcoefct.c
*
* Copyright (C) 1994-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the coefficient buffer controller for decompression.
* This controller is the top level of the JPEG decompressor proper.
* The coefficient buffer lies between entropy decoding and inverse-DCT steps.
*
* In buffered-image mode, this controller is the interface between
* input-oriented processing and output-oriented processing.
* Also, the input side (only) is used when reading a file for transcoding.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Block smoothing is only applicable for progressive JPEG, so: */
#ifndef D_PROGRESSIVE_SUPPORTED
#undef BLOCK_SMOOTHING_SUPPORTED
#endif
/* Private buffer controller object */
typedef struct {
struct jpeg_d_coef_controller pub; /* public fields */
/* These variables keep track of the current location of the input side. */
/* cinfo->input_iMCU_row is also used for this. */
JDIMENSION MCU_ctr; /* counts MCUs processed in current row */
int MCU_vert_offset; /* counts MCU rows within iMCU row */
int MCU_rows_per_iMCU_row; /* number of such rows needed */
/* The output side's location is represented by cinfo->output_iMCU_row. */
/* In single-pass modes, it's sufficient to buffer just one MCU.
* We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks,
* and let the entropy decoder write into that workspace each time.
* (On 80x86, the workspace is FAR even though it's not really very big;
* this is to keep the module interfaces unchanged when a large coefficient
* buffer is necessary.)
* In multi-pass modes, this array points to the current MCU's blocks
* within the virtual arrays; it is used only by the input side.
*/
JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU];
/* Temporary workspace for one MCU */
JCOEF * workspace;
#ifdef D_MULTISCAN_FILES_SUPPORTED
/* In multi-pass modes, we need a virtual block array for each component. */
jvirt_barray_ptr whole_image[MAX_COMPONENTS];
#endif
#ifdef BLOCK_SMOOTHING_SUPPORTED
/* When doing block smoothing, we latch coefficient Al values here */
int * coef_bits_latch;
#define SAVED_COEFS 6 /* we save coef_bits[0..5] */
#endif
} my_coef_controller;
typedef my_coef_controller * my_coef_ptr;
/* Forward declarations */
METHODDEF(int) decompress_onepass
JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
#ifdef D_MULTISCAN_FILES_SUPPORTED
METHODDEF(int) decompress_data
JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
#endif
#ifdef BLOCK_SMOOTHING_SUPPORTED
LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo));
METHODDEF(int) decompress_smooth_data
JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
#endif
LOCAL(void)
start_iMCU_row (j_decompress_ptr cinfo)
/* Reset within-iMCU-row counters for a new row (input side) */
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
/* In an interleaved scan, an MCU row is the same as an iMCU row.
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
* But at the bottom of the image, process only what's left.
*/
if (cinfo->comps_in_scan > 1) {
coef->MCU_rows_per_iMCU_row = 1;
} else {
if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
else
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
}
coef->MCU_ctr = 0;
coef->MCU_vert_offset = 0;
}
/*
* Initialize for an input processing pass.
*/
METHODDEF(void)
start_input_pass (j_decompress_ptr cinfo)
{
cinfo->input_iMCU_row = 0;
start_iMCU_row(cinfo);
}
/*
* Initialize for an output processing pass.
*/
METHODDEF(void)
start_output_pass (j_decompress_ptr cinfo)
{
#ifdef BLOCK_SMOOTHING_SUPPORTED
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
/* If multipass, check to see whether to use block smoothing on this pass */
if (coef->pub.coef_arrays != NULL) {
if (cinfo->do_block_smoothing && smoothing_ok(cinfo))
coef->pub.decompress_data = decompress_smooth_data;
else
coef->pub.decompress_data = decompress_data;
}
#endif
cinfo->output_iMCU_row = 0;
}
/*
* Decompress and return some data in the single-pass case.
* Always attempts to emit one fully interleaved MCU row ("iMCU" row).
* Input and output must run in lockstep since we have only a one-MCU buffer.
* Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
*
* NB: output_buf contains a plane for each component in image,
* which we index according to the component's SOF position.
*/
METHODDEF(int)
decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
int blkn, ci, xindex, yindex, yoffset, useful_width;
JSAMPARRAY output_ptr;
JDIMENSION start_col, output_col;
jpeg_component_info *compptr;
inverse_DCT_method_ptr inverse_DCT;
/* Loop to process as much as one whole iMCU row */
for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
yoffset++) {
for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col;
MCU_col_num++) {
/* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */
jzero_far((void FAR *) coef->MCU_buffer[0],
(size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK)));
if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->MCU_ctr = MCU_col_num;
return JPEG_SUSPENDED;
}
/* Determine where data should go in output_buf and do the IDCT thing.
* We skip dummy blocks at the right and bottom edges (but blkn gets
* incremented past them!). Note the inner loop relies on having
* allocated the MCU_buffer[] blocks sequentially.
*/
blkn = 0; /* index of current DCT block within MCU */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* Don't bother to IDCT an uninteresting component. */
if (! compptr->component_needed) {
blkn += compptr->MCU_blocks;
continue;
}
inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index];
useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
: compptr->last_col_width;
output_ptr = output_buf[compptr->component_index] +
yoffset * compptr->DCT_scaled_size;
start_col = MCU_col_num * compptr->MCU_sample_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
if (cinfo->input_iMCU_row < last_iMCU_row ||
yoffset+yindex < compptr->last_row_height) {
output_col = start_col;
for (xindex = 0; xindex < useful_width; xindex++) {
(*inverse_DCT) (cinfo, compptr,
(JCOEFPTR) coef->MCU_buffer[blkn+xindex],
output_ptr, output_col);
output_col += compptr->DCT_scaled_size;
}
}
blkn += compptr->MCU_width;
output_ptr += compptr->DCT_scaled_size;
}
}
}
/* Completed an MCU row, but perhaps not an iMCU row */
coef->MCU_ctr = 0;
}
/* Completed the iMCU row, advance counters for next one */
cinfo->output_iMCU_row++;
if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
start_iMCU_row(cinfo);
return JPEG_ROW_COMPLETED;
}
/* Completed the scan */
(*cinfo->inputctl->finish_input_pass) (cinfo);
return JPEG_SCAN_COMPLETED;
}
/*
* Dummy consume-input routine for single-pass operation.
*/
METHODDEF(int)
dummy_consume_data (j_decompress_ptr cinfo)
{
return JPEG_SUSPENDED; /* Always indicate nothing was done */
}
#ifdef D_MULTISCAN_FILES_SUPPORTED
/*
* Consume input data and store it in the full-image coefficient buffer.
* We read as much as one fully interleaved MCU row ("iMCU" row) per call,
* ie, v_samp_factor block rows for each component in the scan.
* Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
*/
METHODDEF(int)
consume_data (j_decompress_ptr cinfo)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
int blkn, ci, xindex, yindex, yoffset;
JDIMENSION start_col;
JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
JBLOCKROW buffer_ptr;
jpeg_component_info *compptr;
/* Align the virtual buffers for the components used in this scan. */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
buffer[ci] = (*cinfo->mem->access_virt_barray)
((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
cinfo->input_iMCU_row * compptr->v_samp_factor,
(JDIMENSION) compptr->v_samp_factor, TRUE);
/* Note: entropy decoder expects buffer to be zeroed,
* but this is handled automatically by the memory manager
* because we requested a pre-zeroed array.
*/
}
/* Loop to process one whole iMCU row */
for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
yoffset++) {
for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row;
MCU_col_num++) {
/* Construct list of pointers to DCT blocks belonging to this MCU */
blkn = 0; /* index of current DCT block within MCU */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
start_col = MCU_col_num * compptr->MCU_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
coef->MCU_buffer[blkn++] = buffer_ptr++;
}
}
}
/* Try to fetch the MCU. */
if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->MCU_ctr = MCU_col_num;
return JPEG_SUSPENDED;
}
}
/* Completed an MCU row, but perhaps not an iMCU row */
coef->MCU_ctr = 0;
}
/* Completed the iMCU row, advance counters for next one */
if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
start_iMCU_row(cinfo);
return JPEG_ROW_COMPLETED;
}
/* Completed the scan */
(*cinfo->inputctl->finish_input_pass) (cinfo);
return JPEG_SCAN_COMPLETED;
}
/*
* Decompress and return some data in the multi-pass case.
* Always attempts to emit one fully interleaved MCU row ("iMCU" row).
* Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
*
* NB: output_buf contains a plane for each component in image.
*/
METHODDEF(int)
decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
JDIMENSION block_num;
int ci, block_row, block_rows;
JBLOCKARRAY buffer;
JBLOCKROW buffer_ptr;
JSAMPARRAY output_ptr;
JDIMENSION output_col;
jpeg_component_info *compptr;
inverse_DCT_method_ptr inverse_DCT;
/* Force some input to be done if we are getting ahead of the input. */
while (cinfo->input_scan_number < cinfo->output_scan_number ||
(cinfo->input_scan_number == cinfo->output_scan_number &&
cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) {
if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
return JPEG_SUSPENDED;
}
/* OK, output from the virtual arrays. */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Don't bother to IDCT an uninteresting component. */
if (! compptr->component_needed)
continue;
/* Align the virtual buffer for this component. */
buffer = (*cinfo->mem->access_virt_barray)
((j_common_ptr) cinfo, coef->whole_image[ci],
cinfo->output_iMCU_row * compptr->v_samp_factor,
(JDIMENSION) compptr->v_samp_factor, FALSE);
/* Count non-dummy DCT block rows in this iMCU row. */
if (cinfo->output_iMCU_row < last_iMCU_row)
block_rows = compptr->v_samp_factor;
else {
/* NB: can't use last_row_height here; it is input-side-dependent! */
block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
if (block_rows == 0) block_rows = compptr->v_samp_factor;
}
inverse_DCT = cinfo->idct->inverse_DCT[ci];
output_ptr = output_buf[ci];
/* Loop over all DCT blocks to be processed. */
for (block_row = 0; block_row < block_rows; block_row++) {
buffer_ptr = buffer[block_row];
output_col = 0;
for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) {
(*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr,
output_ptr, output_col);
buffer_ptr++;
output_col += compptr->DCT_scaled_size;
}
output_ptr += compptr->DCT_scaled_size;
}
}
if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
return JPEG_ROW_COMPLETED;
return JPEG_SCAN_COMPLETED;
}
#endif /* D_MULTISCAN_FILES_SUPPORTED */
#ifdef BLOCK_SMOOTHING_SUPPORTED
/*
* This code applies interblock smoothing as described by section K.8
* of the JPEG standard: the first 5 AC coefficients are estimated from
* the DC values of a DCT block and its 8 neighboring blocks.
* We apply smoothing only for progressive JPEG decoding, and only if
* the coefficients it can estimate are not yet known to full precision.
*/
/* Natural-order array positions of the first 5 zigzag-order coefficients */
#define Q01_POS 1
#define Q10_POS 8
#define Q20_POS 16
#define Q11_POS 9
#define Q02_POS 2
/*
* Determine whether block smoothing is applicable and safe.
* We also latch the current states of the coef_bits[] entries for the
* AC coefficients; otherwise, if the input side of the decompressor
* advances into a new scan, we might think the coefficients are known
* more accurately than they really are.
*/
LOCAL(boolean)
smoothing_ok (j_decompress_ptr cinfo)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
boolean smoothing_useful = FALSE;
int ci, coefi;
jpeg_component_info *compptr;
JQUANT_TBL * qtable;
int * coef_bits;
int * coef_bits_latch;
if (! cinfo->progressive_mode || cinfo->coef_bits == NULL)
return FALSE;
/* Allocate latch area if not already done */
if (coef->coef_bits_latch == NULL)
coef->coef_bits_latch = (int *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
cinfo->num_components *
(SAVED_COEFS * SIZEOF(int)));
coef_bits_latch = coef->coef_bits_latch;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* All components' quantization values must already be latched. */
if ((qtable = compptr->quant_table) == NULL)
return FALSE;
/* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */
if (qtable->quantval[0] == 0 ||
qtable->quantval[Q01_POS] == 0 ||
qtable->quantval[Q10_POS] == 0 ||
qtable->quantval[Q20_POS] == 0 ||
qtable->quantval[Q11_POS] == 0 ||
qtable->quantval[Q02_POS] == 0)
return FALSE;
/* DC values must be at least partly known for all components. */
coef_bits = cinfo->coef_bits[ci];
if (coef_bits[0] < 0)
return FALSE;
/* Block smoothing is helpful if some AC coefficients remain inaccurate. */
for (coefi = 1; coefi <= 5; coefi++) {
coef_bits_latch[coefi] = coef_bits[coefi];
if (coef_bits[coefi] != 0)
smoothing_useful = TRUE;
}
coef_bits_latch += SAVED_COEFS;
}
return smoothing_useful;
}
/*
* Variant of decompress_data for use when doing block smoothing.
*/
METHODDEF(int)
decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
JDIMENSION block_num, last_block_column;
int ci, block_row, block_rows, access_rows;
JBLOCKARRAY buffer;
JBLOCKROW buffer_ptr, prev_block_row, next_block_row;
JSAMPARRAY output_ptr;
JDIMENSION output_col;
jpeg_component_info *compptr;
inverse_DCT_method_ptr inverse_DCT;
boolean first_row, last_row;
JCOEF * workspace;
int *coef_bits;
JQUANT_TBL *quanttbl;
INT32 Q00,Q01,Q02,Q10,Q11,Q20, num;
int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9;
int Al, pred;
/* Keep a local variable to avoid looking it up more than once */
workspace = coef->workspace;
/* Force some input to be done if we are getting ahead of the input. */
while (cinfo->input_scan_number <= cinfo->output_scan_number &&
! cinfo->inputctl->eoi_reached) {
if (cinfo->input_scan_number == cinfo->output_scan_number) {
/* If input is working on current scan, we ordinarily want it to
* have completed the current row. But if input scan is DC,
* we want it to keep one row ahead so that next block row's DC
* values are up to date.
*/
JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0;
if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta)
break;
}
if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
return JPEG_SUSPENDED;
}
/* OK, output from the virtual arrays. */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Don't bother to IDCT an uninteresting component. */
if (! compptr->component_needed)
continue;
/* Count non-dummy DCT block rows in this iMCU row. */
if (cinfo->output_iMCU_row < last_iMCU_row) {
block_rows = compptr->v_samp_factor;
access_rows = block_rows * 2; /* this and next iMCU row */
last_row = FALSE;
} else {
/* NB: can't use last_row_height here; it is input-side-dependent! */
block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
if (block_rows == 0) block_rows = compptr->v_samp_factor;
access_rows = block_rows; /* this iMCU row only */
last_row = TRUE;
}
/* Align the virtual buffer for this component. */
if (cinfo->output_iMCU_row > 0) {
access_rows += compptr->v_samp_factor; /* prior iMCU row too */
buffer = (*cinfo->mem->access_virt_barray)
((j_common_ptr) cinfo, coef->whole_image[ci],
(cinfo->output_iMCU_row - 1) * compptr->v_samp_factor,
(JDIMENSION) access_rows, FALSE);
buffer += compptr->v_samp_factor; /* point to current iMCU row */
first_row = FALSE;
} else {
buffer = (*cinfo->mem->access_virt_barray)
((j_common_ptr) cinfo, coef->whole_image[ci],
(JDIMENSION) 0, (JDIMENSION) access_rows, FALSE);
first_row = TRUE;
}
/* Fetch component-dependent info */
coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS);
quanttbl = compptr->quant_table;
Q00 = quanttbl->quantval[0];
Q01 = quanttbl->quantval[Q01_POS];
Q10 = quanttbl->quantval[Q10_POS];
Q20 = quanttbl->quantval[Q20_POS];
Q11 = quanttbl->quantval[Q11_POS];
Q02 = quanttbl->quantval[Q02_POS];
inverse_DCT = cinfo->idct->inverse_DCT[ci];
output_ptr = output_buf[ci];
/* Loop over all DCT blocks to be processed. */
for (block_row = 0; block_row < block_rows; block_row++) {
buffer_ptr = buffer[block_row];
if (first_row && block_row == 0)
prev_block_row = buffer_ptr;
else
prev_block_row = buffer[block_row-1];
if (last_row && block_row == block_rows-1)
next_block_row = buffer_ptr;
else
next_block_row = buffer[block_row+1];
/* We fetch the surrounding DC values using a sliding-register approach.
* Initialize all nine here so as to do the right thing on narrow pics.
*/
DC1 = DC2 = DC3 = (int) prev_block_row[0][0];
DC4 = DC5 = DC6 = (int) buffer_ptr[0][0];
DC7 = DC8 = DC9 = (int) next_block_row[0][0];
output_col = 0;
last_block_column = compptr->width_in_blocks - 1;
for (block_num = 0; block_num <= last_block_column; block_num++) {
/* Fetch current DCT block into workspace so we can modify it. */
jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1);
/* Update DC values */
if (block_num < last_block_column) {
DC3 = (int) prev_block_row[1][0];
DC6 = (int) buffer_ptr[1][0];
DC9 = (int) next_block_row[1][0];
}
/* Compute coefficient estimates per K.8.
* An estimate is applied only if coefficient is still zero,
* and is not known to be fully accurate.
*/
/* AC01 */
if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) {
num = 36 * Q00 * (DC4 - DC6);
if (num >= 0) {
pred = (int) (((Q01<<7) + num) / (Q01<<8));
if (Al > 0 && pred >= (1<<Al))
pred = (1<<Al)-1;
} else {
pred = (int) (((Q01<<7) - num) / (Q01<<8));
if (Al > 0 && pred >= (1<<Al))
pred = (1<<Al)-1;
pred = -pred;
}
workspace[1] = (JCOEF) pred;
}
/* AC10 */
if ((Al=coef_bits[2]) != 0 && workspace[8] == 0) {
num = 36 * Q00 * (DC2 - DC8);
if (num >= 0) {
pred = (int) (((Q10<<7) + num) / (Q10<<8));
if (Al > 0 && pred >= (1<<Al))
pred = (1<<Al)-1;
} else {
pred = (int) (((Q10<<7) - num) / (Q10<<8));
if (Al > 0 && pred >= (1<<Al))
pred = (1<<Al)-1;
pred = -pred;
}
workspace[8] = (JCOEF) pred;
}
/* AC20 */
if ((Al=coef_bits[3]) != 0 && workspace[16] == 0) {
num = 9 * Q00 * (DC2 + DC8 - 2*DC5);
if (num >= 0) {
pred = (int) (((Q20<<7) + num) / (Q20<<8));
if (Al > 0 && pred >= (1<<Al))
pred = (1<<Al)-1;
} else {
pred = (int) (((Q20<<7) - num) / (Q20<<8));
if (Al > 0 && pred >= (1<<Al))
pred = (1<<Al)-1;
pred = -pred;
}
workspace[16] = (JCOEF) pred;
}
/* AC11 */
if ((Al=coef_bits[4]) != 0 && workspace[9] == 0) {
num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
if (num >= 0) {
pred = (int) (((Q11<<7) + num) / (Q11<<8));
if (Al > 0 && pred >= (1<<Al))
pred = (1<<Al)-1;
} else {
pred = (int) (((Q11<<7) - num) / (Q11<<8));
if (Al > 0 && pred >= (1<<Al))
pred = (1<<Al)-1;
pred = -pred;
}
workspace[9] = (JCOEF) pred;
}
/* AC02 */
if ((Al=coef_bits[5]) != 0 && workspace[2] == 0) {
num = 9 * Q00 * (DC4 + DC6 - 2*DC5);
if (num >= 0) {
pred = (int) (((Q02<<7) + num) / (Q02<<8));
if (Al > 0 && pred >= (1<<Al))
pred = (1<<Al)-1;
} else {
pred = (int) (((Q02<<7) - num) / (Q02<<8));
if (Al > 0 && pred >= (1<<Al))
pred = (1<<Al)-1;
pred = -pred;
}
workspace[2] = (JCOEF) pred;
}
/* OK, do the IDCT */
(*inverse_DCT) (cinfo, compptr, (JCOEFPTR) workspace,
output_ptr, output_col);
/* Advance for next column */
DC1 = DC2; DC2 = DC3;
DC4 = DC5; DC5 = DC6;
DC7 = DC8; DC8 = DC9;
buffer_ptr++, prev_block_row++, next_block_row++;
output_col += compptr->DCT_scaled_size;
}
output_ptr += compptr->DCT_scaled_size;
}
}
if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
return JPEG_ROW_COMPLETED;
return JPEG_SCAN_COMPLETED;
}
#endif /* BLOCK_SMOOTHING_SUPPORTED */
/*
* Initialize coefficient buffer controller.
*/
GLOBAL(void)
jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
{
my_coef_ptr coef;
coef = (my_coef_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_coef_controller));
cinfo->coef = (struct jpeg_d_coef_controller *) coef;
coef->pub.start_input_pass = start_input_pass;
coef->pub.start_output_pass = start_output_pass;
#ifdef BLOCK_SMOOTHING_SUPPORTED
coef->coef_bits_latch = NULL;
#endif
/* Create the coefficient buffer. */
if (need_full_buffer) {
#ifdef D_MULTISCAN_FILES_SUPPORTED
/* Allocate a full-image virtual array for each component, */
/* padded to a multiple of samp_factor DCT blocks in each direction. */
/* Note we ask for a pre-zeroed array. */
int ci, access_rows;
jpeg_component_info *compptr;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
access_rows = compptr->v_samp_factor;
#ifdef BLOCK_SMOOTHING_SUPPORTED
/* If block smoothing could be used, need a bigger window */
if (cinfo->progressive_mode)
access_rows *= 3;
#endif
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE,
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
(long) compptr->h_samp_factor),
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
(long) compptr->v_samp_factor),
(JDIMENSION) access_rows);
}
coef->pub.consume_data = consume_data;
coef->pub.decompress_data = decompress_data;
coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
} else {
/* We only need a single-MCU buffer. */
JBLOCKROW buffer;
int i;
buffer = (JBLOCKROW)
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) {
coef->MCU_buffer[i] = buffer + i;
}
coef->pub.consume_data = dummy_consume_data;
coef->pub.decompress_data = decompress_onepass;
coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */
}
/* Allocate the workspace buffer */
coef->workspace = (JCOEF *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(JCOEF) * DCTSIZE2);
}

415
jdcolor.c
View File

@@ -1,16 +1,34 @@
/*
* jdcolor.c
*
* Copyright (C) 1991, 1992, 1993, Thomas G. Lane.
* Copyright (C) 1991-1997, Thomas G. Lane.
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2009, D. R. Commander.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains output colorspace conversion routines.
* These routines are invoked via the methods color_convert
* and colorout_init/term.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jsimd.h"
/* Private subobject */
typedef struct {
struct jpeg_color_deconverter pub; /* public fields */
/* Private state for YCC->RGB conversion */
int * Cr_r_tab; /* => table for Cr to R conversion */
int * Cb_b_tab; /* => table for Cb to B conversion */
INT32 * Cr_g_tab; /* => table for Cr to G conversion */
INT32 * Cb_g_tab; /* => table for Cb to G conversion */
} my_color_deconverter;
typedef my_color_deconverter * my_cconvert_ptr;
/**************** YCbCr -> RGB conversion: most common case **************/
@@ -22,7 +40,7 @@
* R = Y + 1.40200 * Cr
* G = Y - 0.34414 * Cb - 0.71414 * Cr
* B = Y + 1.77200 * Cb
* where Cb and Cr represent the incoming values less MAXJSAMPLE/2.
* where Cb and Cr represent the incoming values less CENTERJSAMPLE.
* (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
*
* To avoid floating-point arithmetic, we represent the fractional constants
@@ -42,261 +60,356 @@
* together before rounding.
*/
#ifdef SIXTEEN_BIT_SAMPLES
#define SCALEBITS 14 /* avoid overflow */
#else
#define SCALEBITS 16 /* speedier right-shift on some machines */
#endif
#define SCALEBITS 16 /* speediest right-shift on some machines */
#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
static int * Cr_r_tab; /* => table for Cr to R conversion */
static int * Cb_b_tab; /* => table for Cb to B conversion */
static INT32 * Cr_g_tab; /* => table for Cr to G conversion */
static INT32 * Cb_g_tab; /* => table for Cb to G conversion */
/*
* Initialize for colorspace conversion.
* Initialize tables for YCC->RGB colorspace conversion.
*/
METHODDEF void
ycc_rgb_init (decompress_info_ptr cinfo)
LOCAL(void)
build_ycc_rgb_table (j_decompress_ptr cinfo)
{
INT32 i, x2;
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
int i;
INT32 x;
SHIFT_TEMPS
Cr_r_tab = (int *) (*cinfo->emethods->alloc_small)
((MAXJSAMPLE+1) * SIZEOF(int));
Cb_b_tab = (int *) (*cinfo->emethods->alloc_small)
((MAXJSAMPLE+1) * SIZEOF(int));
Cr_g_tab = (INT32 *) (*cinfo->emethods->alloc_small)
((MAXJSAMPLE+1) * SIZEOF(INT32));
Cb_g_tab = (INT32 *) (*cinfo->emethods->alloc_small)
((MAXJSAMPLE+1) * SIZEOF(INT32));
cconvert->Cr_r_tab = (int *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(MAXJSAMPLE+1) * SIZEOF(int));
cconvert->Cb_b_tab = (int *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(MAXJSAMPLE+1) * SIZEOF(int));
cconvert->Cr_g_tab = (INT32 *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(MAXJSAMPLE+1) * SIZEOF(INT32));
cconvert->Cb_g_tab = (INT32 *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(MAXJSAMPLE+1) * SIZEOF(INT32));
for (i = 0; i <= MAXJSAMPLE; i++) {
for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
/* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
/* The Cb or Cr value we are thinking of is x = i - MAXJSAMPLE/2 */
x2 = 2*i - MAXJSAMPLE; /* twice x */
/* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
/* Cr=>R value is nearest int to 1.40200 * x */
Cr_r_tab[i] = (int)
RIGHT_SHIFT(FIX(1.40200/2) * x2 + ONE_HALF, SCALEBITS);
cconvert->Cr_r_tab[i] = (int)
RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
/* Cb=>B value is nearest int to 1.77200 * x */
Cb_b_tab[i] = (int)
RIGHT_SHIFT(FIX(1.77200/2) * x2 + ONE_HALF, SCALEBITS);
cconvert->Cb_b_tab[i] = (int)
RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
/* Cr=>G value is scaled-up -0.71414 * x */
Cr_g_tab[i] = (- FIX(0.71414/2)) * x2;
cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
/* Cb=>G value is scaled-up -0.34414 * x */
/* We also add in ONE_HALF so that need not do it in inner loop */
Cb_g_tab[i] = (- FIX(0.34414/2)) * x2 + ONE_HALF;
cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
}
}
/*
* Convert some rows of samples to the output colorspace.
*
* Note that we change from noninterleaved, one-plane-per-component format
* to interleaved-pixel format. The output buffer is therefore three times
* as wide as the input buffer.
* A starting row offset is provided only for the input buffer. The caller
* can easily adjust the passed output_buf value to accommodate any row
* offset required on that side.
*/
METHODDEF void
ycc_rgb_convert (decompress_info_ptr cinfo, int num_rows, long num_cols,
JSAMPIMAGE input_data, JSAMPIMAGE output_data)
METHODDEF(void)
ycc_rgb_convert (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION input_row,
JSAMPARRAY output_buf, int num_rows)
{
#ifdef SIXTEEN_BIT_SAMPLES
register INT32 y;
register UINT16 cb, cr;
#else
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
register int y, cb, cr;
#endif
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2;
register JSAMPROW outptr0, outptr1, outptr2;
register long col;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->output_width;
/* copy these pointers into registers if possible */
register JSAMPLE * range_limit = cinfo->sample_range_limit;
register int * Crrtab = Cr_r_tab;
register int * Cbbtab = Cb_b_tab;
register INT32 * Crgtab = Cr_g_tab;
register INT32 * Cbgtab = Cb_g_tab;
int row;
register int * Crrtab = cconvert->Cr_r_tab;
register int * Cbbtab = cconvert->Cb_b_tab;
register INT32 * Crgtab = cconvert->Cr_g_tab;
register INT32 * Cbgtab = cconvert->Cb_g_tab;
SHIFT_TEMPS
for (row = 0; row < num_rows; row++) {
inptr0 = input_data[0][row];
inptr1 = input_data[1][row];
inptr2 = input_data[2][row];
outptr0 = output_data[0][row];
outptr1 = output_data[1][row];
outptr2 = output_data[2][row];
while (--num_rows >= 0) {
inptr0 = input_buf[0][input_row];
inptr1 = input_buf[1][input_row];
inptr2 = input_buf[2][input_row];
input_row++;
outptr = *output_buf++;
for (col = 0; col < num_cols; col++) {
y = GETJSAMPLE(inptr0[col]);
cb = GETJSAMPLE(inptr1[col]);
cr = GETJSAMPLE(inptr2[col]);
/* Note: if the inputs were computed directly from RGB values,
* range-limiting would be unnecessary here; but due to possible
* noise in the DCT/IDCT phase, we do need to apply range limits.
*/
outptr0[col] = range_limit[y + Crrtab[cr]]; /* red */
outptr1[col] = range_limit[y + /* green */
/* Range-limiting is essential due to noise introduced by DCT losses. */
outptr[rgb_red[cinfo->out_color_space]] = range_limit[y + Crrtab[cr]];
outptr[rgb_green[cinfo->out_color_space]] = range_limit[y +
((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
SCALEBITS))];
outptr2[col] = range_limit[y + Cbbtab[cb]]; /* blue */
outptr[rgb_blue[cinfo->out_color_space]] = range_limit[y + Cbbtab[cb]];
outptr += rgb_pixelsize[cinfo->out_color_space];
}
}
}
/*
* Finish up at the end of the file.
*/
METHODDEF void
ycc_rgb_term (decompress_info_ptr cinfo)
{
/* no work (we let free_all release the workspace) */
}
/**************** Cases other than YCbCr -> RGB **************/
/*
* Initialize for colorspace conversion.
* Color conversion for no colorspace change: just copy the data,
* converting from separate-planes to interleaved representation.
*/
METHODDEF void
null_init (decompress_info_ptr cinfo)
/* colorout_init for cases where no setup is needed */
METHODDEF(void)
null_convert (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION input_row,
JSAMPARRAY output_buf, int num_rows)
{
/* no work needed */
register JSAMPROW inptr, outptr;
register JDIMENSION count;
register int num_components = cinfo->num_components;
JDIMENSION num_cols = cinfo->output_width;
int ci;
while (--num_rows >= 0) {
for (ci = 0; ci < num_components; ci++) {
inptr = input_buf[ci][input_row];
outptr = output_buf[0] + ci;
for (count = num_cols; count > 0; count--) {
*outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */
outptr += num_components;
}
/*
* Color conversion for no colorspace change: just copy the data.
*/
METHODDEF void
null_convert (decompress_info_ptr cinfo, int num_rows, long num_cols,
JSAMPIMAGE input_data, JSAMPIMAGE output_data)
{
short ci;
for (ci = 0; ci < cinfo->num_components; ci++) {
jcopy_sample_rows(input_data[ci], 0, output_data[ci], 0,
num_rows, num_cols);
}
input_row++;
output_buf++;
}
}
/*
* Color conversion for grayscale: just copy the data.
* This also works for YCbCr/YIQ -> grayscale conversion, in which
* This also works for YCbCr -> grayscale conversion, in which
* we just copy the Y (luminance) component and ignore chrominance.
*/
METHODDEF void
grayscale_convert (decompress_info_ptr cinfo, int num_rows, long num_cols,
JSAMPIMAGE input_data, JSAMPIMAGE output_data)
METHODDEF(void)
grayscale_convert (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION input_row,
JSAMPARRAY output_buf, int num_rows)
{
jcopy_sample_rows(input_data[0], 0, output_data[0], 0,
num_rows, num_cols);
jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
num_rows, cinfo->output_width);
}
/*
* Finish up at the end of the file.
* Convert grayscale to RGB: just duplicate the graylevel three times.
* This is provided to support applications that don't want to cope
* with grayscale as a separate case.
*/
METHODDEF void
null_term (decompress_info_ptr cinfo)
/* colorout_term for cases where no teardown is needed */
METHODDEF(void)
gray_rgb_convert (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION input_row,
JSAMPARRAY output_buf, int num_rows)
{
register JSAMPROW inptr, outptr;
JSAMPLE *maxinptr;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->output_width;
int rindex = rgb_red[cinfo->out_color_space];
int gindex = rgb_green[cinfo->out_color_space];
int bindex = rgb_blue[cinfo->out_color_space];
int rgbstride = rgb_pixelsize[cinfo->out_color_space];
while (--num_rows >= 0) {
inptr = input_buf[0][input_row++];
maxinptr = &inptr[num_cols];
outptr = *output_buf++;
for (; inptr < maxinptr; inptr++, outptr += rgbstride) {
/* We can dispense with GETJSAMPLE() here */
outptr[rindex] = outptr[gindex] = outptr[bindex] = *inptr;
}
}
}
/*
* Adobe-style YCCK->CMYK conversion.
* We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
* conversion as above, while passing K (black) unchanged.
* We assume build_ycc_rgb_table has been called.
*/
METHODDEF(void)
ycck_cmyk_convert (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION input_row,
JSAMPARRAY output_buf, int num_rows)
{
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
register int y, cb, cr;
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2, inptr3;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->output_width;
/* copy these pointers into registers if possible */
register JSAMPLE * range_limit = cinfo->sample_range_limit;
register int * Crrtab = cconvert->Cr_r_tab;
register int * Cbbtab = cconvert->Cb_b_tab;
register INT32 * Crgtab = cconvert->Cr_g_tab;
register INT32 * Cbgtab = cconvert->Cb_g_tab;
SHIFT_TEMPS
while (--num_rows >= 0) {
inptr0 = input_buf[0][input_row];
inptr1 = input_buf[1][input_row];
inptr2 = input_buf[2][input_row];
inptr3 = input_buf[3][input_row];
input_row++;
outptr = *output_buf++;
for (col = 0; col < num_cols; col++) {
y = GETJSAMPLE(inptr0[col]);
cb = GETJSAMPLE(inptr1[col]);
cr = GETJSAMPLE(inptr2[col]);
/* Range-limiting is essential due to noise introduced by DCT losses. */
outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */
outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */
((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
SCALEBITS)))];
outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */
/* K passes through unchanged */
outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */
outptr += 4;
}
}
}
/*
* Empty method for start_pass.
*/
METHODDEF(void)
start_pass_dcolor (j_decompress_ptr cinfo)
{
/* no work needed */
}
/*
* The method selection routine for output colorspace conversion.
* Module initialization routine for output colorspace conversion.
*/
GLOBAL void
jseldcolor (decompress_info_ptr cinfo)
GLOBAL(void)
jinit_color_deconverter (j_decompress_ptr cinfo)
{
my_cconvert_ptr cconvert;
int ci;
cconvert = (my_cconvert_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_color_deconverter));
cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
cconvert->pub.start_pass = start_pass_dcolor;
/* Make sure num_components agrees with jpeg_color_space */
switch (cinfo->jpeg_color_space) {
case CS_GRAYSCALE:
case JCS_GRAYSCALE:
if (cinfo->num_components != 1)
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
break;
case CS_RGB:
case CS_YCbCr:
case CS_YIQ:
case JCS_RGB:
case JCS_YCbCr:
if (cinfo->num_components != 3)
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
break;
case CS_CMYK:
case JCS_CMYK:
case JCS_YCCK:
if (cinfo->num_components != 4)
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
break;
default:
ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace");
default: /* JCS_UNKNOWN can be anything */
if (cinfo->num_components < 1)
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
break;
}
/* Set color_out_comps and conversion method based on requested space. */
/* Also clear the component_needed flags for any unused components, */
/* so that earlier pipeline stages can avoid useless computation. */
/* Set out_color_components and conversion method based on requested space.
* Also clear the component_needed flags for any unused components,
* so that earlier pipeline stages can avoid useless computation.
*/
switch (cinfo->out_color_space) {
case CS_GRAYSCALE:
cinfo->color_out_comps = 1;
if (cinfo->jpeg_color_space == CS_GRAYSCALE ||
cinfo->jpeg_color_space == CS_YCbCr ||
cinfo->jpeg_color_space == CS_YIQ) {
cinfo->methods->color_convert = grayscale_convert;
cinfo->methods->colorout_init = null_init;
cinfo->methods->colorout_term = null_term;
case JCS_GRAYSCALE:
cinfo->out_color_components = 1;
if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
cinfo->jpeg_color_space == JCS_YCbCr) {
cconvert->pub.color_convert = grayscale_convert;
/* For color->grayscale conversion, only the Y (0) component is needed */
for (ci = 1; ci < cinfo->num_components; ci++)
cinfo->cur_comp_info[ci]->component_needed = FALSE;
cinfo->comp_info[ci].component_needed = FALSE;
} else
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
case CS_RGB:
cinfo->color_out_comps = 3;
if (cinfo->jpeg_color_space == CS_YCbCr) {
cinfo->methods->color_convert = ycc_rgb_convert;
cinfo->methods->colorout_init = ycc_rgb_init;
cinfo->methods->colorout_term = ycc_rgb_term;
} else if (cinfo->jpeg_color_space == CS_RGB) {
cinfo->methods->color_convert = null_convert;
cinfo->methods->colorout_init = null_init;
cinfo->methods->colorout_term = null_term;
case JCS_RGB:
case JCS_EXT_RGB:
case JCS_EXT_RGBX:
case JCS_EXT_BGR:
case JCS_EXT_BGRX:
case JCS_EXT_XBGR:
case JCS_EXT_XRGB:
cinfo->out_color_components = rgb_pixelsize[cinfo->out_color_space];
if (cinfo->jpeg_color_space == JCS_YCbCr) {
if (jsimd_can_ycc_rgb())
cconvert->pub.color_convert = jsimd_ycc_rgb_convert;
else {
cconvert->pub.color_convert = ycc_rgb_convert;
build_ycc_rgb_table(cinfo);
}
} else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
cconvert->pub.color_convert = gray_rgb_convert;
} else if (cinfo->jpeg_color_space == cinfo->out_color_space &&
rgb_pixelsize[cinfo->out_color_space] == 3) {
cconvert->pub.color_convert = null_convert;
} else
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
case JCS_CMYK:
cinfo->out_color_components = 4;
if (cinfo->jpeg_color_space == JCS_YCCK) {
cconvert->pub.color_convert = ycck_cmyk_convert;
build_ycc_rgb_table(cinfo);
} else if (cinfo->jpeg_color_space == JCS_CMYK) {
cconvert->pub.color_convert = null_convert;
} else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
default:
/* Permit null conversion from CMYK or YCbCr to same output space */
/* Permit null conversion to same output space */
if (cinfo->out_color_space == cinfo->jpeg_color_space) {
cinfo->color_out_comps = cinfo->num_components;
cinfo->methods->color_convert = null_convert;
cinfo->methods->colorout_init = null_init;
cinfo->methods->colorout_term = null_term;
cinfo->out_color_components = cinfo->num_components;
cconvert->pub.color_convert = null_convert;
} else /* unsupported non-null conversion */
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
}
if (cinfo->quantize_colors)
cinfo->final_out_comps = 1; /* single colormapped output component */
cinfo->output_components = 1; /* single colormapped output component */
else
cinfo->final_out_comps = cinfo->color_out_comps;
cinfo->output_components = cinfo->out_color_components;
}

184
jdct.h Normal file
View File

@@ -0,0 +1,184 @@
/*
* jdct.h
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This include file contains common declarations for the forward and
* inverse DCT modules. These declarations are private to the DCT managers
* (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms.
* The individual DCT algorithms are kept in separate files to ease
* machine-dependent tuning (e.g., assembly coding).
*/
/*
* A forward DCT routine is given a pointer to a work area of type DCTELEM[];
* the DCT is to be performed in-place in that buffer. Type DCTELEM is int
* for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT
* implementations use an array of type FAST_FLOAT, instead.)
* The DCT inputs are expected to be signed (range +-CENTERJSAMPLE).
* The DCT outputs are returned scaled up by a factor of 8; they therefore
* have a range of +-8K for 8-bit data, +-128K for 12-bit data. This
* convention improves accuracy in integer implementations and saves some
* work in floating-point ones.
* Quantization of the output coefficients is done by jcdctmgr.c. This
* step requires an unsigned type and also one with twice the bits.
*/
#if BITS_IN_JSAMPLE == 8
#ifndef WITH_SIMD
typedef int DCTELEM; /* 16 or 32 bits is fine */
typedef unsigned int UDCTELEM;
typedef unsigned long long UDCTELEM2;
#else
typedef short DCTELEM; /* prefer 16 bit with SIMD for parellelism */
typedef unsigned short UDCTELEM;
typedef unsigned int UDCTELEM2;
#endif
#else
typedef INT32 DCTELEM; /* must have 32 bits */
typedef UINT32 UDCTELEM;
typedef unsigned long long UDCTELEM2;
#endif
/*
* An inverse DCT routine is given a pointer to the input JBLOCK and a pointer
* to an output sample array. The routine must dequantize the input data as
* well as perform the IDCT; for dequantization, it uses the multiplier table
* pointed to by compptr->dct_table. The output data is to be placed into the
* sample array starting at a specified column. (Any row offset needed will
* be applied to the array pointer before it is passed to the IDCT code.)
* Note that the number of samples emitted by the IDCT routine is
* DCT_scaled_size * DCT_scaled_size.
*/
/* typedef inverse_DCT_method_ptr is declared in jpegint.h */
/*
* Each IDCT routine has its own ideas about the best dct_table element type.
*/
typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */
#if BITS_IN_JSAMPLE == 8
typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */
#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */
#else
typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */
#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */
#endif
typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
/*
* Each IDCT routine is responsible for range-limiting its results and
* converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could
* be quite far out of range if the input data is corrupt, so a bulletproof
* range-limiting step is required. We use a mask-and-table-lookup method
* to do the combined operations quickly. See the comments with
* prepare_range_limit_table (in jdmaster.c) for more info.
*/
#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE)
#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */
/* Short forms of external names for systems with brain-damaged linkers. */
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define jpeg_fdct_islow jFDislow
#define jpeg_fdct_ifast jFDifast
#define jpeg_fdct_float jFDfloat
#define jpeg_idct_islow jRDislow
#define jpeg_idct_ifast jRDifast
#define jpeg_idct_float jRDfloat
#define jpeg_idct_4x4 jRD4x4
#define jpeg_idct_2x2 jRD2x2
#define jpeg_idct_1x1 jRD1x1
#endif /* NEED_SHORT_EXTERNAL_NAMES */
/* Extern declarations for the forward and inverse DCT routines. */
EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data));
EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data));
EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data));
EXTERN(void) jpeg_idct_islow
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
EXTERN(void) jpeg_idct_ifast
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
EXTERN(void) jpeg_idct_float
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
EXTERN(void) jpeg_idct_4x4
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
EXTERN(void) jpeg_idct_2x2
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
EXTERN(void) jpeg_idct_1x1
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
/*
* Macros for handling fixed-point arithmetic; these are used by many
* but not all of the DCT/IDCT modules.
*
* All values are expected to be of type INT32.
* Fractional constants are scaled left by CONST_BITS bits.
* CONST_BITS is defined within each module using these macros,
* and may differ from one module to the next.
*/
#define ONE ((INT32) 1)
#define CONST_SCALE (ONE << CONST_BITS)
/* Convert a positive real constant to an integer scaled by CONST_SCALE.
* Caution: some C compilers fail to reduce "FIX(constant)" at compile time,
* thus causing a lot of useless floating-point operations at run time.
*/
#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
/* Descale and correctly round an INT32 value that's scaled by N bits.
* We assume RIGHT_SHIFT rounds towards minus infinity, so adding
* the fudge factor is correct for either sign of X.
*/
#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
* This macro is used only when the two inputs will actually be no more than
* 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a
* full 32x32 multiply. This provides a useful speedup on many machines.
* Unfortunately there is no way to specify a 16x16->32 multiply portably
* in C, but some C compilers will do the right thing if you provide the
* correct combination of casts.
*/
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const)))
#endif
#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const)))
#endif
#ifndef MULTIPLY16C16 /* default definition */
#define MULTIPLY16C16(var,const) ((var) * (const))
#endif
/* Same except both inputs are variables. */
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2)))
#endif
#ifndef MULTIPLY16V16 /* default definition */
#define MULTIPLY16V16(var1,var2) ((var1) * (var2))
#endif

286
jddctmgr.c Normal file
View File

@@ -0,0 +1,286 @@
/*
* jddctmgr.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the inverse-DCT management logic.
* This code selects a particular IDCT implementation to be used,
* and it performs related housekeeping chores. No code in this file
* is executed per IDCT step, only during output pass setup.
*
* Note that the IDCT routines are responsible for performing coefficient
* dequantization as well as the IDCT proper. This module sets up the
* dequantization multiplier table needed by the IDCT routine.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#include "jsimddct.h"
/*
* The decompressor input side (jdinput.c) saves away the appropriate
* quantization table for each component at the start of the first scan
* involving that component. (This is necessary in order to correctly
* decode files that reuse Q-table slots.)
* When we are ready to make an output pass, the saved Q-table is converted
* to a multiplier table that will actually be used by the IDCT routine.
* The multiplier table contents are IDCT-method-dependent. To support
* application changes in IDCT method between scans, we can remake the
* multiplier tables if necessary.
* In buffered-image mode, the first output pass may occur before any data
* has been seen for some components, and thus before their Q-tables have
* been saved away. To handle this case, multiplier tables are preset
* to zeroes; the result of the IDCT will be a neutral gray level.
*/
/* Private subobject for this module */
typedef struct {
struct jpeg_inverse_dct pub; /* public fields */
/* This array contains the IDCT method code that each multiplier table
* is currently set up for, or -1 if it's not yet set up.
* The actual multiplier tables are pointed to by dct_table in the
* per-component comp_info structures.
*/
int cur_method[MAX_COMPONENTS];
} my_idct_controller;
typedef my_idct_controller * my_idct_ptr;
/* Allocated multiplier tables: big enough for any supported variant */
typedef union {
ISLOW_MULT_TYPE islow_array[DCTSIZE2];
#ifdef DCT_IFAST_SUPPORTED
IFAST_MULT_TYPE ifast_array[DCTSIZE2];
#endif
#ifdef DCT_FLOAT_SUPPORTED
FLOAT_MULT_TYPE float_array[DCTSIZE2];
#endif
} multiplier_table;
/* The current scaled-IDCT routines require ISLOW-style multiplier tables,
* so be sure to compile that code if either ISLOW or SCALING is requested.
*/
#ifdef DCT_ISLOW_SUPPORTED
#define PROVIDE_ISLOW_TABLES
#else
#ifdef IDCT_SCALING_SUPPORTED
#define PROVIDE_ISLOW_TABLES
#endif
#endif
/*
* Prepare for an output pass.
* Here we select the proper IDCT routine for each component and build
* a matching multiplier table.
*/
METHODDEF(void)
start_pass (j_decompress_ptr cinfo)
{
my_idct_ptr idct = (my_idct_ptr) cinfo->idct;
int ci, i;
jpeg_component_info *compptr;
int method = 0;
inverse_DCT_method_ptr method_ptr = NULL;
JQUANT_TBL * qtbl;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Select the proper IDCT routine for this component's scaling */
switch (compptr->DCT_scaled_size) {
#ifdef IDCT_SCALING_SUPPORTED
case 1:
method_ptr = jpeg_idct_1x1;
method = JDCT_ISLOW; /* jidctred uses islow-style table */
break;
case 2:
if (jsimd_can_idct_2x2())
method_ptr = jsimd_idct_2x2;
else
method_ptr = jpeg_idct_2x2;
method = JDCT_ISLOW; /* jidctred uses islow-style table */
break;
case 4:
if (jsimd_can_idct_4x4())
method_ptr = jsimd_idct_4x4;
else
method_ptr = jpeg_idct_4x4;
method = JDCT_ISLOW; /* jidctred uses islow-style table */
break;
#endif
case DCTSIZE:
switch (cinfo->dct_method) {
#ifdef DCT_ISLOW_SUPPORTED
case JDCT_ISLOW:
if (jsimd_can_idct_islow())
method_ptr = jsimd_idct_islow;
else
method_ptr = jpeg_idct_islow;
method = JDCT_ISLOW;
break;
#endif
#ifdef DCT_IFAST_SUPPORTED
case JDCT_IFAST:
if (jsimd_can_idct_ifast())
method_ptr = jsimd_idct_ifast;
else
method_ptr = jpeg_idct_ifast;
method = JDCT_IFAST;
break;
#endif
#ifdef DCT_FLOAT_SUPPORTED
case JDCT_FLOAT:
if (jsimd_can_idct_float())
method_ptr = jsimd_idct_float;
else
method_ptr = jpeg_idct_float;
method = JDCT_FLOAT;
break;
#endif
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
break;
}
break;
default:
ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size);
break;
}
idct->pub.inverse_DCT[ci] = method_ptr;
/* Create multiplier table from quant table.
* However, we can skip this if the component is uninteresting
* or if we already built the table. Also, if no quant table
* has yet been saved for the component, we leave the
* multiplier table all-zero; we'll be reading zeroes from the
* coefficient controller's buffer anyway.
*/
if (! compptr->component_needed || idct->cur_method[ci] == method)
continue;
qtbl = compptr->quant_table;
if (qtbl == NULL) /* happens if no data yet for component */
continue;
idct->cur_method[ci] = method;
switch (method) {
#ifdef PROVIDE_ISLOW_TABLES
case JDCT_ISLOW:
{
/* For LL&M IDCT method, multipliers are equal to raw quantization
* coefficients, but are stored as ints to ensure access efficiency.
*/
ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table;
for (i = 0; i < DCTSIZE2; i++) {
ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i];
}
}
break;
#endif
#ifdef DCT_IFAST_SUPPORTED
case JDCT_IFAST:
{
/* For AA&N IDCT method, multipliers 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
* For integer operation, the multiplier table is to be scaled by
* IFAST_SCALE_BITS.
*/
IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table;
#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
for (i = 0; i < DCTSIZE2; i++) {
ifmtbl[i] = (IFAST_MULT_TYPE)
DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
(INT32) aanscales[i]),
CONST_BITS-IFAST_SCALE_BITS);
}
}
break;
#endif
#ifdef DCT_FLOAT_SUPPORTED
case JDCT_FLOAT:
{
/* For float AA&N IDCT method, multipliers 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
*/
FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table;
int row, col;
static const double aanscalefactor[DCTSIZE] = {
1.0, 1.387039845, 1.306562965, 1.175875602,
1.0, 0.785694958, 0.541196100, 0.275899379
};
i = 0;
for (row = 0; row < DCTSIZE; row++) {
for (col = 0; col < DCTSIZE; col++) {
fmtbl[i] = (FLOAT_MULT_TYPE)
((double) qtbl->quantval[i] *
aanscalefactor[row] * aanscalefactor[col]);
i++;
}
}
}
break;
#endif
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
break;
}
}
}
/*
* Initialize IDCT manager.
*/
GLOBAL(void)
jinit_inverse_dct (j_decompress_ptr cinfo)
{
my_idct_ptr idct;
int ci;
jpeg_component_info *compptr;
idct = (my_idct_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_idct_controller));
cinfo->idct = (struct jpeg_inverse_dct *) idct;
idct->pub.start_pass = start_pass;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Allocate and pre-zero a multiplier table for each component */
compptr->dct_table =
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(multiplier_table));
MEMZERO(compptr->dct_table, SIZEOF(multiplier_table));
/* Mark multiplier table not yet set up for any method */
idct->cur_method[ci] = -1;
}
}

View File

@@ -1,185 +0,0 @@
/*
* jddeflts.c
*
* Copyright (C) 1991, 1992, 1993, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains optional default-setting code for the JPEG decompressor.
* User interfaces do not have to use this file, but those that don't use it
* must know more about the innards of the JPEG code.
*/
#include "jinclude.h"
/* Default do-nothing progress monitoring routine.
* This can be overridden by a user interface that wishes to
* provide progress monitoring; just set methods->progress_monitor
* after j_d_defaults is done. The routine will be called periodically
* during the decompression process.
*
* During any one pass, loopcounter increases from 0 up to (not including)
* looplimit; the step size is not necessarily 1. Both the step size and
* the limit may differ between passes. The expected total number of passes
* is in cinfo->total_passes, and the number of passes already completed is
* in cinfo->completed_passes. Thus the fraction of work completed may be
* estimated as
* completed_passes + (loopcounter/looplimit)
* ------------------------------------------
* total_passes
* ignoring the fact that the passes may not be equal amounts of work.
*
* When decompressing, the total_passes figure is an estimate that may be
* on the high side; completed_passes will jump by more than one if some
* passes are skipped.
*/
METHODDEF void
progress_monitor (decompress_info_ptr cinfo, long loopcounter, long looplimit)
{
/* do nothing */
}
/* Default comment-block processing routine.
* This can be overridden by an application that wishes to examine
* COM blocks found in the JPEG file. The default routine does nothing.
* CAUTION: the comment processing routine MUST call JGETC() exactly
* comment_length times to read the comment data, whether it intends
* to do anything with the data or not!
* Keep in mind that (a) there may be more than one COM block in a file;
* (b) there's no guarantee that what's in the block is ASCII data.
*/
METHODDEF void
process_comment (decompress_info_ptr cinfo, long comment_length)
{
while (comment_length-- > 0) {
(void) JGETC(cinfo);
}
}
/*
* Reload the input buffer after it's been emptied, and return the next byte.
* See the JGETC macro for calling conditions. Note in particular that
* read_jpeg_data may NOT return EOF. If no more data is available, it must
* exit via ERREXIT, or perhaps synthesize fake data (such as an RST marker).
* In the present implementation, we insert an EOI marker; this might not be
* appropriate for non-JFIF file formats, but it usually allows us to handle
* a truncated JFIF file.
*
* This routine can be overridden by the system-dependent user interface,
* in case the data source is not a stdio stream or some other special
* condition applies. Note, however, that this capability only applies for
* JFIF or similar serial-access JPEG file formats. The input file control
* module for a random-access format such as TIFF/JPEG would most likely
* override the read_jpeg_data method with its own routine.
*/
METHODDEF int
read_jpeg_data (decompress_info_ptr cinfo)
{
cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET;
cinfo->bytes_in_buffer = (int) JFREAD(cinfo->input_file,
cinfo->next_input_byte,
JPEG_BUF_SIZE);
if (cinfo->bytes_in_buffer <= 0) {
WARNMS(cinfo->emethods, "Premature EOF in JPEG file");
cinfo->next_input_byte[0] = (char) 0xFF;
cinfo->next_input_byte[1] = (char) 0xD9; /* EOI marker */
cinfo->bytes_in_buffer = 2;
}
return JGETC(cinfo);
}
/* Default parameter setup for decompression.
*
* User interfaces that don't choose to use this routine must do their
* own setup of all these parameters. Alternately, you can call this
* to establish defaults and then alter parameters selectively. This
* is the recommended approach since, if we add any new parameters,
* your code will still work (they'll be set to reasonable defaults).
*
* standard_buffering should be TRUE to cause an input buffer to be allocated
* (the normal case); if FALSE, the user interface must provide a buffer.
* This option is most useful in the case that the buffer must not be freed
* at the end of an image. (For example, when reading a sequence of images
* from a single file, the remaining data in the buffer represents the
* start of the next image and mustn't be discarded.) To handle this,
* allocate the input buffer yourself at startup, WITHOUT using alloc_small
* (probably a direct call to malloc() instead). Then pass FALSE on each
* call to j_d_defaults to ensure the buffer state is not modified.
*
* If the source of the JPEG data is not a stdio stream, override the
* read_jpeg_data method with your own routine after calling j_d_defaults.
* You can still use the standard buffer if it's appropriate.
*
* CAUTION: if you want to decompress multiple images per run, it's necessary
* to call j_d_defaults before *each* call to jpeg_decompress, since subsidiary
* structures like the quantization tables are automatically freed during
* cleanup.
*/
GLOBAL void
j_d_defaults (decompress_info_ptr cinfo, boolean standard_buffering)
/* NB: the external methods must already be set up. */
{
short i;
/* Initialize pointers as needed to mark stuff unallocated. */
/* Outer application may fill in default tables for abbreviated files... */
cinfo->comp_info = NULL;
for (i = 0; i < NUM_QUANT_TBLS; i++)
cinfo->quant_tbl_ptrs[i] = NULL;
for (i = 0; i < NUM_HUFF_TBLS; i++) {
cinfo->dc_huff_tbl_ptrs[i] = NULL;
cinfo->ac_huff_tbl_ptrs[i] = NULL;
}
cinfo->colormap = NULL;
/* Default to RGB output */
/* UI can override by changing out_color_space */
cinfo->out_color_space = CS_RGB;
cinfo->jpeg_color_space = CS_UNKNOWN;
/* Setting any other value in jpeg_color_space overrides heuristics in */
/* jrdjfif.c. That might be useful when reading non-JFIF JPEG files, */
/* but ordinarily the UI shouldn't change it. */
/* Default to no gamma correction of output */
cinfo->output_gamma = 1.0;
/* Default to no color quantization */
cinfo->quantize_colors = FALSE;
/* but set reasonable default parameters for quantization, */
/* so that turning on quantize_colors is sufficient to do something useful */
cinfo->two_pass_quantize = TRUE;
cinfo->use_dithering = TRUE;
cinfo->desired_number_of_colors = 256;
/* Default to no smoothing */
cinfo->do_block_smoothing = FALSE;
cinfo->do_pixel_smoothing = FALSE;
/* Allocate memory for input buffer, unless outer application provides it. */
if (standard_buffering) {
cinfo->input_buffer = (char *) (*cinfo->emethods->alloc_small)
((size_t) (JPEG_BUF_SIZE + MIN_UNGET));
cinfo->bytes_in_buffer = 0; /* initialize buffer to empty */
}
/* Install standard buffer-reloading method (outer code may override). */
cinfo->methods->read_jpeg_data = read_jpeg_data;
/* Install default do-nothing progress monitoring method. */
cinfo->methods->progress_monitor = progress_monitor;
/* Install default comment-block processing method. */
cinfo->methods->process_comment = process_comment;
}

890
jdhuff.c

File diff suppressed because it is too large Load Diff

213
jdhuff.h Normal file
View File

@@ -0,0 +1,213 @@
/*
* jdhuff.h
*
* Copyright (C) 1991-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains declarations for Huffman entropy decoding routines
* that are shared between the sequential decoder (jdhuff.c) and the
* progressive decoder (jdphuff.c). No other modules need to see these.
*/
/* Short forms of external names for systems with brain-damaged linkers. */
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define jpeg_make_d_derived_tbl jMkDDerived
#define jpeg_fill_bit_buffer jFilBitBuf
#define jpeg_huff_decode jHufDecode
#endif /* NEED_SHORT_EXTERNAL_NAMES */
/* Derived data constructed for each Huffman table */
#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */
typedef struct {
/* Basic tables: (element [0] of each array is unused) */
INT32 maxcode[18]; /* largest code of length k (-1 if none) */
/* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */
INT32 valoffset[17]; /* huffval[] offset for codes of length k */
/* valoffset[k] = huffval[] index of 1st symbol of code length k, less
* the smallest code of length k; so given a code of length k, the
* corresponding symbol is huffval[code + valoffset[k]]
*/
/* Link to public Huffman table (needed only in jpeg_huff_decode) */
JHUFF_TBL *pub;
/* Lookahead table: indexed by the next HUFF_LOOKAHEAD bits of
* the input data stream. If the next Huffman code is no more
* than HUFF_LOOKAHEAD bits long, we can obtain its length and
* the corresponding symbol directly from this tables.
*
* The lower 8 bits of each table entry contain the number of
* bits in the corresponding Huffman code, or HUFF_LOOKAHEAD + 1
* if too long. The next 8 bits of each entry contain the
* symbol.
*/
int lookup[1<<HUFF_LOOKAHEAD];
} d_derived_tbl;
/* Expand a Huffman table definition into the derived format */
EXTERN(void) jpeg_make_d_derived_tbl
JPP((j_decompress_ptr cinfo, boolean isDC, int tblno,
d_derived_tbl ** pdtbl));
/*
* Fetching the next N bits from the input stream is a time-critical operation
* for the Huffman decoders. We implement it with a combination of inline
* macros and out-of-line subroutines. Note that N (the number of bits
* demanded at one time) never exceeds 15 for JPEG use.
*
* We read source bytes into get_buffer and dole out bits as needed.
* If get_buffer already contains enough bits, they are fetched in-line
* by the macros CHECK_BIT_BUFFER and GET_BITS. When there aren't enough
* bits, jpeg_fill_bit_buffer is called; it will attempt to fill get_buffer
* as full as possible (not just to the number of bits needed; this
* prefetching reduces the overhead cost of calling jpeg_fill_bit_buffer).
* Note that jpeg_fill_bit_buffer may return FALSE to indicate suspension.
* On TRUE return, jpeg_fill_bit_buffer guarantees that get_buffer contains
* at least the requested number of bits --- dummy zeroes are inserted if
* necessary.
*/
#if __WORDSIZE == 64 || defined(_WIN64)
typedef size_t bit_buf_type; /* type of bit-extraction buffer */
#define BIT_BUF_SIZE 64 /* size of buffer in bits */
#else
typedef INT32 bit_buf_type; /* type of bit-extraction buffer */
#define BIT_BUF_SIZE 32 /* size of buffer in bits */
#endif
/* If long is > 32 bits on your machine, and shifting/masking longs is
* reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE
* appropriately should be a win. Unfortunately we can't define the size
* with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8)
* because not all machines measure sizeof in 8-bit bytes.
*/
typedef struct { /* Bitreading state saved across MCUs */
bit_buf_type get_buffer; /* current bit-extraction buffer */
int bits_left; /* # of unused bits in it */
} bitread_perm_state;
typedef struct { /* Bitreading working state within an MCU */
/* Current data source location */
/* We need a copy, rather than munging the original, in case of suspension */
const JOCTET * next_input_byte; /* => next byte to read from source */
size_t bytes_in_buffer; /* # of bytes remaining in source buffer */
/* Bit input buffer --- note these values are kept in register variables,
* not in this struct, inside the inner loops.
*/
bit_buf_type get_buffer; /* current bit-extraction buffer */
int bits_left; /* # of unused bits in it */
/* Pointer needed by jpeg_fill_bit_buffer. */
j_decompress_ptr cinfo; /* back link to decompress master record */
} bitread_working_state;
/* Macros to declare and load/save bitread local variables. */
#define BITREAD_STATE_VARS \
register bit_buf_type get_buffer; \
register int bits_left; \
bitread_working_state br_state
#define BITREAD_LOAD_STATE(cinfop,permstate) \
br_state.cinfo = cinfop; \
br_state.next_input_byte = cinfop->src->next_input_byte; \
br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \
get_buffer = permstate.get_buffer; \
bits_left = permstate.bits_left;
#define BITREAD_SAVE_STATE(cinfop,permstate) \
cinfop->src->next_input_byte = br_state.next_input_byte; \
cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \
permstate.get_buffer = get_buffer; \
permstate.bits_left = bits_left
/*
* These macros provide the in-line portion of bit fetching.
* Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer
* before using GET_BITS, PEEK_BITS, or DROP_BITS.
* The variables get_buffer and bits_left are assumed to be locals,
* but the state struct might not be (jpeg_huff_decode needs this).
* CHECK_BIT_BUFFER(state,n,action);
* Ensure there are N bits in get_buffer; if suspend, take action.
* val = GET_BITS(n);
* Fetch next N bits.
* val = PEEK_BITS(n);
* Fetch next N bits without removing them from the buffer.
* DROP_BITS(n);
* Discard next N bits.
* The value N should be a simple variable, not an expression, because it
* is evaluated multiple times.
*/
#define CHECK_BIT_BUFFER(state,nbits,action) \
{ if (bits_left < (nbits)) { \
if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \
{ action; } \
get_buffer = (state).get_buffer; bits_left = (state).bits_left; } }
#define GET_BITS(nbits) \
(((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1))
#define PEEK_BITS(nbits) \
(((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1))
#define DROP_BITS(nbits) \
(bits_left -= (nbits))
/* Load up the bit buffer to a depth of at least nbits */
EXTERN(boolean) jpeg_fill_bit_buffer
JPP((bitread_working_state * state, register bit_buf_type get_buffer,
register int bits_left, int nbits));
/*
* Code for extracting next Huffman-coded symbol from input bit stream.
* Again, this is time-critical and we make the main paths be macros.
*
* We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits
* without looping. Usually, more than 95% of the Huffman codes will be 8
* or fewer bits long. The few overlength codes are handled with a loop,
* which need not be inline code.
*
* Notes about the HUFF_DECODE macro:
* 1. Near the end of the data segment, we may fail to get enough bits
* for a lookahead. In that case, we do it the hard way.
* 2. If the lookahead table contains no entry, the next code must be
* more than HUFF_LOOKAHEAD bits long.
* 3. jpeg_huff_decode returns -1 if forced to suspend.
*/
#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \
{ register int nb, look; \
if (bits_left < HUFF_LOOKAHEAD) { \
if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \
get_buffer = state.get_buffer; bits_left = state.bits_left; \
if (bits_left < HUFF_LOOKAHEAD) { \
nb = 1; goto slowlabel; \
} \
} \
look = PEEK_BITS(HUFF_LOOKAHEAD); \
if ((nb = (htbl->lookup[look] >> HUFF_LOOKAHEAD)) <= HUFF_LOOKAHEAD) { \
DROP_BITS(nb); \
result = htbl->lookup[look] & ((1 << HUFF_LOOKAHEAD) - 1); \
} else { \
slowlabel: \
if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \
{ failaction; } \
get_buffer = state.get_buffer; bits_left = state.bits_left; \
} \
}
/* Out-of-line case for Huffman code fetching */
EXTERN(int) jpeg_huff_decode
JPP((bitread_working_state * state, register bit_buf_type get_buffer,
register int bits_left, d_derived_tbl * htbl, int min_bits));

381
jdinput.c Normal file
View File

@@ -0,0 +1,381 @@
/*
* jdinput.c
*
* Copyright (C) 1991-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains input control logic for the JPEG decompressor.
* These routines are concerned with controlling the decompressor's input
* processing (marker reading and coefficient decoding). The actual input
* reading is done in jdmarker.c, jdhuff.c, and jdphuff.c.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Private state */
typedef struct {
struct jpeg_input_controller pub; /* public fields */
boolean inheaders; /* TRUE until first SOS is reached */
} my_input_controller;
typedef my_input_controller * my_inputctl_ptr;
/* Forward declarations */
METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo));
/*
* Routines to calculate various quantities related to the size of the image.
*/
LOCAL(void)
initial_setup (j_decompress_ptr cinfo)
/* Called once, when first SOS marker is reached */
{
int ci;
jpeg_component_info *compptr;
/* Make sure image isn't bigger than I can handle */
if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
(long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
/* For now, precision must match compiled-in value... */
if (cinfo->data_precision != BITS_IN_JSAMPLE)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
/* Check that number of components won't exceed internal array sizes */
if (cinfo->num_components > MAX_COMPONENTS)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
MAX_COMPONENTS);
/* Compute maximum sampling factors; check factor validity */
cinfo->max_h_samp_factor = 1;
cinfo->max_v_samp_factor = 1;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
ERREXIT(cinfo, JERR_BAD_SAMPLING);
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
compptr->h_samp_factor);
cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
compptr->v_samp_factor);
}
/* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE.
* In the full decompressor, this will be overridden by jdmaster.c;
* but in the transcoder, jdmaster.c is not used, so we must do it here.
*/
cinfo->min_DCT_scaled_size = DCTSIZE;
/* Compute dimensions of components */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
compptr->DCT_scaled_size = DCTSIZE;
/* Size in DCT blocks */
compptr->width_in_blocks = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
(long) (cinfo->max_h_samp_factor * DCTSIZE));
compptr->height_in_blocks = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
(long) (cinfo->max_v_samp_factor * DCTSIZE));
/* downsampled_width and downsampled_height will also be overridden by
* jdmaster.c if we are doing full decompression. The transcoder library
* doesn't use these values, but the calling application might.
*/
/* Size in samples */
compptr->downsampled_width = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
(long) cinfo->max_h_samp_factor);
compptr->downsampled_height = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
(long) cinfo->max_v_samp_factor);
/* Mark component needed, until color conversion says otherwise */
compptr->component_needed = TRUE;
/* Mark no quantization table yet saved for component */
compptr->quant_table = NULL;
}
/* Compute number of fully interleaved MCU rows. */
cinfo->total_iMCU_rows = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height,
(long) (cinfo->max_v_samp_factor*DCTSIZE));
/* Decide whether file contains multiple scans */
if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode)
cinfo->inputctl->has_multiple_scans = TRUE;
else
cinfo->inputctl->has_multiple_scans = FALSE;
}
LOCAL(void)
per_scan_setup (j_decompress_ptr cinfo)
/* Do computations that are needed before processing a JPEG scan */
/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */
{
int ci, mcublks, tmp;
jpeg_component_info *compptr;
if (cinfo->comps_in_scan == 1) {
/* Noninterleaved (single-component) scan */
compptr = cinfo->cur_comp_info[0];
/* Overall image size in MCUs */
cinfo->MCUs_per_row = compptr->width_in_blocks;
cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
/* For noninterleaved scan, always one block per MCU */
compptr->MCU_width = 1;
compptr->MCU_height = 1;
compptr->MCU_blocks = 1;
compptr->MCU_sample_width = compptr->DCT_scaled_size;
compptr->last_col_width = 1;
/* For noninterleaved scans, it is convenient to define last_row_height
* as the number of block rows present in the last iMCU row.
*/
tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
if (tmp == 0) tmp = compptr->v_samp_factor;
compptr->last_row_height = tmp;
/* Prepare array describing MCU composition */
cinfo->blocks_in_MCU = 1;
cinfo->MCU_membership[0] = 0;
} else {
/* Interleaved (multi-component) scan */
if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
MAX_COMPS_IN_SCAN);
/* Overall image size in MCUs */
cinfo->MCUs_per_row = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width,
(long) (cinfo->max_h_samp_factor*DCTSIZE));
cinfo->MCU_rows_in_scan = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height,
(long) (cinfo->max_v_samp_factor*DCTSIZE));
cinfo->blocks_in_MCU = 0;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* Sampling factors give # of blocks of component in each MCU */
compptr->MCU_width = compptr->h_samp_factor;
compptr->MCU_height = compptr->v_samp_factor;
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size;
/* Figure number of non-dummy blocks in last MCU column & row */
tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
if (tmp == 0) tmp = compptr->MCU_width;
compptr->last_col_width = tmp;
tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
if (tmp == 0) tmp = compptr->MCU_height;
compptr->last_row_height = tmp;
/* Prepare array describing MCU composition */
mcublks = compptr->MCU_blocks;
if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU)
ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
while (mcublks-- > 0) {
cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
}
}
}
}
/*
* Save away a copy of the Q-table referenced by each component present
* in the current scan, unless already saved during a prior scan.
*
* In a multiple-scan JPEG file, the encoder could assign different components
* the same Q-table slot number, but change table definitions between scans
* so that each component uses a different Q-table. (The IJG encoder is not
* currently capable of doing this, but other encoders might.) Since we want
* to be able to dequantize all the components at the end of the file, this
* means that we have to save away the table actually used for each component.
* We do this by copying the table at the start of the first scan containing
* the component.
* The JPEG spec prohibits the encoder from changing the contents of a Q-table
* slot between scans of a component using that slot. If the encoder does so
* anyway, this decoder will simply use the Q-table values that were current
* at the start of the first scan for the component.
*
* The decompressor output side looks only at the saved quant tables,
* not at the current Q-table slots.
*/
LOCAL(void)
latch_quant_tables (j_decompress_ptr cinfo)
{
int ci, qtblno;
jpeg_component_info *compptr;
JQUANT_TBL * qtbl;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* No work if we already saved Q-table for this component */
if (compptr->quant_table != NULL)
continue;
/* Make sure specified quantization table is present */
qtblno = compptr->quant_tbl_no;
if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
cinfo->quant_tbl_ptrs[qtblno] == NULL)
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
/* OK, save away the quantization table */
qtbl = (JQUANT_TBL *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(JQUANT_TBL));
MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL));
compptr->quant_table = qtbl;
}
}
/*
* Initialize the input modules to read a scan of compressed data.
* The first call to this is done by jdmaster.c after initializing
* the entire decompressor (during jpeg_start_decompress).
* Subsequent calls come from consume_markers, below.
*/
METHODDEF(void)
start_input_pass (j_decompress_ptr cinfo)
{
per_scan_setup(cinfo);
latch_quant_tables(cinfo);
(*cinfo->entropy->start_pass) (cinfo);
(*cinfo->coef->start_input_pass) (cinfo);
cinfo->inputctl->consume_input = cinfo->coef->consume_data;
}
/*
* Finish up after inputting a compressed-data scan.
* This is called by the coefficient controller after it's read all
* the expected data of the scan.
*/
METHODDEF(void)
finish_input_pass (j_decompress_ptr cinfo)
{
cinfo->inputctl->consume_input = consume_markers;
}
/*
* Read JPEG markers before, between, or after compressed-data scans.
* Change state as necessary when a new scan is reached.
* Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
*
* The consume_input method pointer points either here or to the
* coefficient controller's consume_data routine, depending on whether
* we are reading a compressed data segment or inter-segment markers.
*/
METHODDEF(int)
consume_markers (j_decompress_ptr cinfo)
{
my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
int val;
if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */
return JPEG_REACHED_EOI;
val = (*cinfo->marker->read_markers) (cinfo);
switch (val) {
case JPEG_REACHED_SOS: /* Found SOS */
if (inputctl->inheaders) { /* 1st SOS */
initial_setup(cinfo);
inputctl->inheaders = FALSE;
/* Note: start_input_pass must be called by jdmaster.c
* before any more input can be consumed. jdapimin.c is
* responsible for enforcing this sequencing.
*/
} else { /* 2nd or later SOS marker */
if (! inputctl->pub.has_multiple_scans)
ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */
start_input_pass(cinfo);
}
break;
case JPEG_REACHED_EOI: /* Found EOI */
inputctl->pub.eoi_reached = TRUE;
if (inputctl->inheaders) { /* Tables-only datastream, apparently */
if (cinfo->marker->saw_SOF)
ERREXIT(cinfo, JERR_SOF_NO_SOS);
} else {
/* Prevent infinite loop in coef ctlr's decompress_data routine
* if user set output_scan_number larger than number of scans.
*/
if (cinfo->output_scan_number > cinfo->input_scan_number)
cinfo->output_scan_number = cinfo->input_scan_number;
}
break;
case JPEG_SUSPENDED:
break;
}
return val;
}
/*
* Reset state to begin a fresh datastream.
*/
METHODDEF(void)
reset_input_controller (j_decompress_ptr cinfo)
{
my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
inputctl->pub.consume_input = consume_markers;
inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
inputctl->pub.eoi_reached = FALSE;
inputctl->inheaders = TRUE;
/* Reset other modules */
(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
(*cinfo->marker->reset_marker_reader) (cinfo);
/* Reset progression state -- would be cleaner if entropy decoder did this */
cinfo->coef_bits = NULL;
}
/*
* Initialize the input controller module.
* This is called only once, when the decompression object is created.
*/
GLOBAL(void)
jinit_input_controller (j_decompress_ptr cinfo)
{
my_inputctl_ptr inputctl;
/* Create subobject in permanent pool */
inputctl = (my_inputctl_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
SIZEOF(my_input_controller));
cinfo->inputctl = (struct jpeg_input_controller *) inputctl;
/* Initialize method pointers */
inputctl->pub.consume_input = consume_markers;
inputctl->pub.reset_input_controller = reset_input_controller;
inputctl->pub.start_input_pass = start_input_pass;
inputctl->pub.finish_input_pass = finish_input_pass;
/* Initialize state: can't use reset_input_controller since we don't
* want to try to reset other modules yet.
*/
inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
inputctl->pub.eoi_reached = FALSE;
inputctl->inheaders = TRUE;
}

514
jdmain.c
View File

@@ -1,514 +0,0 @@
/*
* jdmain.c
*
* Copyright (C) 1991, 1992, 1993, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains a command-line user interface for the JPEG decompressor.
* It should work on any system with Unix- or MS-DOS-style command lines.
*
* Two different command line styles are permitted, depending on the
* compile-time switch TWO_FILE_COMMANDLINE:
* djpeg [options] inputfile outputfile
* djpeg [options] [inputfile]
* In the second style, output is always to standard output, which you'd
* normally redirect to a file or pipe to some other program. Input is
* either from a named file or from standard input (typically redirected).
* The second style is convenient on Unix but is unhelpful on systems that
* don't support pipes. Also, you MUST use the first style if your system
* doesn't do binary I/O to stdin/stdout.
* To simplify script writing, the "-outfile" switch is provided. The syntax
* djpeg [options] -outfile outputfile inputfile
* works regardless of which command line style is used.
*/
#include "jinclude.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare exit() */
#endif
#include <ctype.h> /* to declare isupper(), tolower() */
#ifdef NEED_SIGNAL_CATCHER
#include <signal.h> /* to declare signal() */
#endif
#ifdef USE_SETMODE
#include <fcntl.h> /* to declare setmode() */
#endif
#ifdef THINK_C
#include <console.h> /* command-line reader for Macintosh */
#endif
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
#define READ_BINARY "r"
#define WRITE_BINARY "w"
#else
#define READ_BINARY "rb"
#define WRITE_BINARY "wb"
#endif
#ifndef EXIT_FAILURE /* define exit() codes if not provided */
#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
#ifdef VMS
#define EXIT_SUCCESS 1 /* VMS is very nonstandard */
#else
#define EXIT_SUCCESS 0
#endif
#endif
#include "jversion.h" /* for version message */
/*
* This list defines the known output image formats
* (not all of which need be supported by a given version).
* You can change the default output format by defining DEFAULT_FMT;
* indeed, you had better do so if you undefine PPM_SUPPORTED.
*/
typedef enum {
FMT_GIF, /* GIF format */
FMT_PPM, /* PPM/PGM (PBMPLUS formats) */
FMT_RLE, /* RLE format */
FMT_TARGA, /* Targa format */
FMT_TIFF /* TIFF format */
} IMAGE_FORMATS;
#ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */
#define DEFAULT_FMT FMT_PPM
#endif
static IMAGE_FORMATS requested_fmt;
/*
* This routine gets control after the input file header has been read.
* It must determine what output file format is to be written,
* and make any other decompression parameter changes that are desirable.
*/
METHODDEF void
d_ui_method_selection (decompress_info_ptr cinfo)
{
/* if grayscale or CMYK input, force similar output; */
/* else leave the output colorspace as set by options. */
if (cinfo->jpeg_color_space == CS_GRAYSCALE)
cinfo->out_color_space = CS_GRAYSCALE;
else if (cinfo->jpeg_color_space == CS_CMYK)
cinfo->out_color_space = CS_CMYK;
/* select output file format */
/* Note: jselwxxx routine may make additional parameter changes,
* such as forcing color quantization if it's a colormapped format.
*/
switch (requested_fmt) {
#ifdef GIF_SUPPORTED
case FMT_GIF:
jselwgif(cinfo);
break;
#endif
#ifdef PPM_SUPPORTED
case FMT_PPM:
jselwppm(cinfo);
break;
#endif
#ifdef RLE_SUPPORTED
case FMT_RLE:
jselwrle(cinfo);
break;
#endif
#ifdef TARGA_SUPPORTED
case FMT_TARGA:
jselwtarga(cinfo);
break;
#endif
default:
ERREXIT(cinfo->emethods, "Unsupported output file format");
break;
}
}
/*
* Signal catcher to ensure that temporary files are removed before aborting.
* NB: for Amiga Manx C this is actually a global routine named _abort();
* see -Dsignal_catcher=_abort in CFLAGS. Talk about bogus...
*/
#ifdef NEED_SIGNAL_CATCHER
static external_methods_ptr emethods; /* for access to free_all */
GLOBAL void
signal_catcher (int signum)
{
if (emethods != NULL) {
emethods->trace_level = 0; /* turn off trace output */
(*emethods->free_all) (); /* clean up memory allocation & temp files */
}
exit(EXIT_FAILURE);
}
#endif
/*
* Optional routine to display a percent-done figure on stderr.
* See jddeflts.c for explanation of the information used.
*/
#ifdef PROGRESS_REPORT
METHODDEF void
progress_monitor (decompress_info_ptr cinfo, long loopcounter, long looplimit)
{
if (cinfo->total_passes > 1) {
fprintf(stderr, "\rPass %d/%d: %3d%% ",
cinfo->completed_passes+1, cinfo->total_passes,
(int) (loopcounter*100L/looplimit));
} else {
fprintf(stderr, "\r %3d%% ",
(int) (loopcounter*100L/looplimit));
}
fflush(stderr);
}
#endif
/*
* Argument-parsing code.
* The switch parser is designed to be useful with DOS-style command line
* syntax, ie, intermixed switches and file names, where only the switches
* to the left of a given file name affect processing of that file.
* The main program in this file doesn't actually use this capability...
*/
static char * progname; /* program name for error messages */
static char * outfilename; /* for -outfile switch */
LOCAL void
usage (void)
/* complain about bad command line */
{
fprintf(stderr, "usage: %s [switches] ", progname);
#ifdef TWO_FILE_COMMANDLINE
fprintf(stderr, "inputfile outputfile\n");
#else
fprintf(stderr, "[inputfile]\n");
#endif
fprintf(stderr, "Switches (names may be abbreviated):\n");
fprintf(stderr, " -colors N Reduce image to no more than N colors\n");
#ifdef GIF_SUPPORTED
fprintf(stderr, " -gif Select GIF output format\n");
#endif
#ifdef PPM_SUPPORTED
fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format (default)\n");
#endif
fprintf(stderr, " -quantize N Same as -colors N\n");
#ifdef RLE_SUPPORTED
fprintf(stderr, " -rle Select Utah RLE output format\n");
#endif
#ifdef TARGA_SUPPORTED
fprintf(stderr, " -targa Select Targa output format\n");
#endif
fprintf(stderr, "Switches for advanced users:\n");
#ifdef BLOCK_SMOOTHING_SUPPORTED
fprintf(stderr, " -blocksmooth Apply cross-block smoothing\n");
#endif
fprintf(stderr, " -grayscale Force grayscale output\n");
fprintf(stderr, " -nodither Don't use dithering in quantization\n");
#ifdef QUANT_1PASS_SUPPORTED
fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n");
#endif
fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
fprintf(stderr, " -verbose or -debug Emit debug output\n");
exit(EXIT_FAILURE);
}
LOCAL boolean
keymatch (char * arg, const char * keyword, int minchars)
/* Case-insensitive matching of (possibly abbreviated) keyword switches. */
/* keyword is the constant keyword (must be lower case already), */
/* minchars is length of minimum legal abbreviation. */
{
register int ca, ck;
register int nmatched = 0;
while ((ca = *arg++) != '\0') {
if ((ck = *keyword++) == '\0')
return FALSE; /* arg longer than keyword, no good */
if (isupper(ca)) /* force arg to lcase (assume ck is already) */
ca = tolower(ca);
if (ca != ck)
return FALSE; /* no good */
nmatched++; /* count matched characters */
}
/* reached end of argument; fail if it's too short for unique abbrev */
if (nmatched < minchars)
return FALSE;
return TRUE; /* A-OK */
}
LOCAL int
parse_switches (decompress_info_ptr cinfo, int last_file_arg_seen,
int argc, char **argv)
/* Initialize cinfo with default switch settings, then parse option switches.
* Returns argv[] index of first file-name argument (== argc if none).
* Any file names with indexes <= last_file_arg_seen are ignored;
* they have presumably been processed in a previous iteration.
* (Pass 0 for last_file_arg_seen on the first or only iteration.)
*/
{
int argn;
char * arg;
/* (Re-)initialize the system-dependent error and memory managers. */
jselerror(cinfo->emethods); /* error/trace message routines */
jselmemmgr(cinfo->emethods); /* memory allocation routines */
cinfo->methods->d_ui_method_selection = d_ui_method_selection;
/* Now OK to enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
emethods = cinfo->emethods;
#endif
/* Set up default JPEG parameters. */
j_d_defaults(cinfo, TRUE);
requested_fmt = DEFAULT_FMT; /* set default output file format */
outfilename = NULL;
/* Scan command line options, adjust parameters */
for (argn = 1; argn < argc; argn++) {
arg = argv[argn];
if (*arg != '-') {
/* Not a switch, must be a file name argument */
if (argn <= last_file_arg_seen) {
outfilename = NULL; /* -outfile applies to just one input file */
continue; /* ignore this name if previously processed */
}
break; /* else done parsing switches */
}
arg++; /* advance past switch marker character */
if (keymatch(arg, "blocksmooth", 1)) {
/* Enable cross-block smoothing. */
cinfo->do_block_smoothing = TRUE;
} else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
/* Do color quantization. */
int val;
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%d", &val) != 1)
usage();
cinfo->desired_number_of_colors = val;
cinfo->quantize_colors = TRUE;
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
/* Enable debug printouts. */
/* On first -d, print version identification */
if (last_file_arg_seen == 0 && cinfo->emethods->trace_level == 0)
fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
JVERSION, JCOPYRIGHT);
cinfo->emethods->trace_level++;
} else if (keymatch(arg, "gif", 1)) {
/* GIF output format. */
requested_fmt = FMT_GIF;
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
/* Force monochrome output. */
cinfo->out_color_space = CS_GRAYSCALE;
} else if (keymatch(arg, "maxmemory", 1)) {
/* Maximum memory in Kb (or Mb with 'm'). */
long lval;
char ch = 'x';
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
usage();
if (ch == 'm' || ch == 'M')
lval *= 1000L;
cinfo->emethods->max_memory_to_use = lval * 1000L;
} else if (keymatch(arg, "nodither", 3)) {
/* Suppress dithering in color quantization. */
cinfo->use_dithering = FALSE;
} else if (keymatch(arg, "onepass", 1)) {
/* Use fast one-pass quantization. */
cinfo->two_pass_quantize = FALSE;
} else if (keymatch(arg, "outfile", 3)) {
/* Set output file name. */
if (++argn >= argc) /* advance to next argument */
usage();
outfilename = argv[argn]; /* save it away for later use */
} else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) {
/* PPM/PGM output format. */
requested_fmt = FMT_PPM;
} else if (keymatch(arg, "rle", 1)) {
/* RLE output format. */
requested_fmt = FMT_RLE;
} else if (keymatch(arg, "targa", 1)) {
/* Targa output format. */
requested_fmt = FMT_TARGA;
} else {
usage(); /* bogus switch */
}
}
return argn; /* return index of next arg (file name) */
}
/*
* The main program.
*/
GLOBAL int
main (int argc, char **argv)
{
struct Decompress_info_struct cinfo;
struct Decompress_methods_struct dc_methods;
struct External_methods_struct e_methods;
int file_index;
/* On Mac, fetch a command line. */
#ifdef THINK_C
argc = ccommand(&argv);
#endif
progname = argv[0];
/* Set up links to method structures. */
cinfo.methods = &dc_methods;
cinfo.emethods = &e_methods;
/* Install, but don't yet enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
emethods = NULL;
signal(SIGINT, signal_catcher);
#ifdef SIGTERM /* not all systems have SIGTERM */
signal(SIGTERM, signal_catcher);
#endif
#endif
/* Scan command line: set up compression parameters, find file names. */
file_index = parse_switches(&cinfo, 0, argc, argv);
#ifdef TWO_FILE_COMMANDLINE
/* Must have either -outfile switch or explicit output file name */
if (outfilename == NULL) {
if (file_index != argc-2) {
fprintf(stderr, "%s: must name one input and one output file\n",
progname);
usage();
}
outfilename = argv[file_index+1];
} else {
if (file_index != argc-1) {
fprintf(stderr, "%s: must name one input and one output file\n",
progname);
usage();
}
}
#else
/* Unix style: expect zero or one file name */
if (file_index < argc-1) {
fprintf(stderr, "%s: only one input file\n", progname);
usage();
}
#endif /* TWO_FILE_COMMANDLINE */
/* Open the input file. */
if (file_index < argc) {
if ((cinfo.input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
exit(EXIT_FAILURE);
}
} else {
/* default input file is stdin */
#ifdef USE_SETMODE /* need to hack file mode? */
setmode(fileno(stdin), O_BINARY);
#endif
#ifdef USE_FDOPEN /* need to re-open in binary mode? */
if ((cinfo.input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open stdin\n", progname);
exit(EXIT_FAILURE);
}
#else
cinfo.input_file = stdin;
#endif
}
/* Open the output file. */
if (outfilename != NULL) {
if ((cinfo.output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
exit(EXIT_FAILURE);
}
} else {
/* default output file is stdout */
#ifdef USE_SETMODE /* need to hack file mode? */
setmode(fileno(stdout), O_BINARY);
#endif
#ifdef USE_FDOPEN /* need to re-open in binary mode? */
if ((cinfo.output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open stdout\n", progname);
exit(EXIT_FAILURE);
}
#else
cinfo.output_file = stdout;
#endif
}
/* Set up to read a JFIF or baseline-JPEG file. */
/* A smarter UI would inspect the first few bytes of the input file */
/* to determine its type. */
#ifdef JFIF_SUPPORTED
jselrjfif(&cinfo);
#else
You shoulda defined JFIF_SUPPORTED. /* deliberate syntax error */
#endif
#ifdef PROGRESS_REPORT
/* Start up progress display, unless trace output is on */
if (e_methods.trace_level == 0)
dc_methods.progress_monitor = progress_monitor;
#endif
/* Do it to it! */
jpeg_decompress(&cinfo);
#ifdef PROGRESS_REPORT
/* Clear away progress display */
if (e_methods.trace_level == 0) {
fprintf(stderr, "\r \r");
fflush(stderr);
}
#endif
/* All done. */
exit(EXIT_SUCCESS);
return 0; /* suppress no-return-value warnings */
}

512
jdmainct.c Normal file
View File

@@ -0,0 +1,512 @@
/*
* jdmainct.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the main buffer controller for decompression.
* The main buffer lies between the JPEG decompressor proper and the
* post-processor; it holds downsampled data in the JPEG colorspace.
*
* Note that this code is bypassed in raw-data mode, since the application
* supplies the equivalent of the main buffer in that case.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* In the current system design, the main buffer need never be a full-image
* buffer; any full-height buffers will be found inside the coefficient or
* postprocessing controllers. Nonetheless, the main controller is not
* trivial. Its responsibility is to provide context rows for upsampling/
* rescaling, and doing this in an efficient fashion is a bit tricky.
*
* Postprocessor input data is counted in "row groups". A row group
* is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
* sample rows of each component. (We require DCT_scaled_size values to be
* chosen such that these numbers are integers. In practice DCT_scaled_size
* values will likely be powers of two, so we actually have the stronger
* condition that DCT_scaled_size / min_DCT_scaled_size is an integer.)
* Upsampling will typically produce max_v_samp_factor pixel rows from each
* row group (times any additional scale factor that the upsampler is
* applying).
*
* The coefficient controller will deliver data to us one iMCU row at a time;
* each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or
* exactly min_DCT_scaled_size row groups. (This amount of data corresponds
* to one row of MCUs when the image is fully interleaved.) Note that the
* number of sample rows varies across components, but the number of row
* groups does not. Some garbage sample rows may be included in the last iMCU
* row at the bottom of the image.
*
* Depending on the vertical scaling algorithm used, the upsampler may need
* access to the sample row(s) above and below its current input row group.
* The upsampler is required to set need_context_rows TRUE at global selection
* time if so. When need_context_rows is FALSE, this controller can simply
* obtain one iMCU row at a time from the coefficient controller and dole it
* out as row groups to the postprocessor.
*
* When need_context_rows is TRUE, this controller guarantees that the buffer
* passed to postprocessing contains at least one row group's worth of samples
* above and below the row group(s) being processed. Note that the context
* rows "above" the first passed row group appear at negative row offsets in
* the passed buffer. At the top and bottom of the image, the required
* context rows are manufactured by duplicating the first or last real sample
* row; this avoids having special cases in the upsampling inner loops.
*
* The amount of context is fixed at one row group just because that's a
* convenient number for this controller to work with. The existing
* upsamplers really only need one sample row of context. An upsampler
* supporting arbitrary output rescaling might wish for more than one row
* group of context when shrinking the image; tough, we don't handle that.
* (This is justified by the assumption that downsizing will be handled mostly
* by adjusting the DCT_scaled_size values, so that the actual scale factor at
* the upsample step needn't be much less than one.)
*
* To provide the desired context, we have to retain the last two row groups
* of one iMCU row while reading in the next iMCU row. (The last row group
* can't be processed until we have another row group for its below-context,
* and so we have to save the next-to-last group too for its above-context.)
* We could do this most simply by copying data around in our buffer, but
* that'd be very slow. We can avoid copying any data by creating a rather
* strange pointer structure. Here's how it works. We allocate a workspace
* consisting of M+2 row groups (where M = min_DCT_scaled_size is the number
* of row groups per iMCU row). We create two sets of redundant pointers to
* the workspace. Labeling the physical row groups 0 to M+1, the synthesized
* pointer lists look like this:
* M+1 M-1
* master pointer --> 0 master pointer --> 0
* 1 1
* ... ...
* M-3 M-3
* M-2 M
* M-1 M+1
* M M-2
* M+1 M-1
* 0 0
* We read alternate iMCU rows using each master pointer; thus the last two
* row groups of the previous iMCU row remain un-overwritten in the workspace.
* The pointer lists are set up so that the required context rows appear to
* be adjacent to the proper places when we pass the pointer lists to the
* upsampler.
*
* The above pictures describe the normal state of the pointer lists.
* At top and bottom of the image, we diddle the pointer lists to duplicate
* the first or last sample row as necessary (this is cheaper than copying
* sample rows around).
*
* This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that
* situation each iMCU row provides only one row group so the buffering logic
* must be different (eg, we must read two iMCU rows before we can emit the
* first row group). For now, we simply do not support providing context
* rows when min_DCT_scaled_size is 1. That combination seems unlikely to
* be worth providing --- if someone wants a 1/8th-size preview, they probably
* want it quick and dirty, so a context-free upsampler is sufficient.
*/
/* Private buffer controller object */
typedef struct {
struct jpeg_d_main_controller pub; /* public fields */
/* Pointer to allocated workspace (M or M+2 row groups). */
JSAMPARRAY buffer[MAX_COMPONENTS];
boolean buffer_full; /* Have we gotten an iMCU row from decoder? */
JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */
/* Remaining fields are only used in the context case. */
/* These are the master pointers to the funny-order pointer lists. */
JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */
int whichptr; /* indicates which pointer set is now in use */
int context_state; /* process_data state machine status */
JDIMENSION rowgroups_avail; /* row groups available to postprocessor */
JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */
} my_main_controller;
typedef my_main_controller * my_main_ptr;
/* context_state values: */
#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */
#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */
#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */
/* Forward declarations */
METHODDEF(void) process_data_simple_main
JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
METHODDEF(void) process_data_context_main
JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
#ifdef QUANT_2PASS_SUPPORTED
METHODDEF(void) process_data_crank_post
JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
#endif
LOCAL(void)
alloc_funny_pointers (j_decompress_ptr cinfo)
/* Allocate space for the funny pointer lists.
* This is done only once, not once per pass.
*/
{
my_main_ptr main = (my_main_ptr) cinfo->main;
int ci, rgroup;
int M = cinfo->min_DCT_scaled_size;
jpeg_component_info *compptr;
JSAMPARRAY xbuf;
/* Get top-level space for component array pointers.
* We alloc both arrays with one call to save a few cycles.
*/
main->xbuffer[0] = (JSAMPIMAGE)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
cinfo->num_components * 2 * SIZEOF(JSAMPARRAY));
main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
cinfo->min_DCT_scaled_size; /* height of a row group of component */
/* Get space for pointer lists --- M+4 row groups in each list.
* We alloc both pointer lists with one call to save a few cycles.
*/
xbuf = (JSAMPARRAY)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW));
xbuf += rgroup; /* want one row group at negative offsets */
main->xbuffer[0][ci] = xbuf;
xbuf += rgroup * (M + 4);
main->xbuffer[1][ci] = xbuf;
}
}
LOCAL(void)
make_funny_pointers (j_decompress_ptr cinfo)
/* Create the funny pointer lists discussed in the comments above.
* The actual workspace is already allocated (in main->buffer),
* and the space for the pointer lists is allocated too.
* This routine just fills in the curiously ordered lists.
* This will be repeated at the beginning of each pass.
*/
{
my_main_ptr main = (my_main_ptr) cinfo->main;
int ci, i, rgroup;
int M = cinfo->min_DCT_scaled_size;
jpeg_component_info *compptr;
JSAMPARRAY buf, xbuf0, xbuf1;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
cinfo->min_DCT_scaled_size; /* height of a row group of component */
xbuf0 = main->xbuffer[0][ci];
xbuf1 = main->xbuffer[1][ci];
/* First copy the workspace pointers as-is */
buf = main->buffer[ci];
for (i = 0; i < rgroup * (M + 2); i++) {
xbuf0[i] = xbuf1[i] = buf[i];
}
/* In the second list, put the last four row groups in swapped order */
for (i = 0; i < rgroup * 2; i++) {
xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i];
xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i];
}
/* The wraparound pointers at top and bottom will be filled later
* (see set_wraparound_pointers, below). Initially we want the "above"
* pointers to duplicate the first actual data line. This only needs
* to happen in xbuffer[0].
*/
for (i = 0; i < rgroup; i++) {
xbuf0[i - rgroup] = xbuf0[0];
}
}
}
LOCAL(void)
set_wraparound_pointers (j_decompress_ptr cinfo)
/* Set up the "wraparound" pointers at top and bottom of the pointer lists.
* This changes the pointer list state from top-of-image to the normal state.
*/
{
my_main_ptr main = (my_main_ptr) cinfo->main;
int ci, i, rgroup;
int M = cinfo->min_DCT_scaled_size;
jpeg_component_info *compptr;
JSAMPARRAY xbuf0, xbuf1;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
cinfo->min_DCT_scaled_size; /* height of a row group of component */
xbuf0 = main->xbuffer[0][ci];
xbuf1 = main->xbuffer[1][ci];
for (i = 0; i < rgroup; i++) {
xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i];
xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i];
xbuf0[rgroup*(M+2) + i] = xbuf0[i];
xbuf1[rgroup*(M+2) + i] = xbuf1[i];
}
}
}
LOCAL(void)
set_bottom_pointers (j_decompress_ptr cinfo)
/* Change the pointer lists to duplicate the last sample row at the bottom
* of the image. whichptr indicates which xbuffer holds the final iMCU row.
* Also sets rowgroups_avail to indicate number of nondummy row groups in row.
*/
{
my_main_ptr main = (my_main_ptr) cinfo->main;
int ci, i, rgroup, iMCUheight, rows_left;
jpeg_component_info *compptr;
JSAMPARRAY xbuf;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Count sample rows in one iMCU row and in one row group */
iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size;
rgroup = iMCUheight / cinfo->min_DCT_scaled_size;
/* Count nondummy sample rows remaining for this component */
rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight);
if (rows_left == 0) rows_left = iMCUheight;
/* Count nondummy row groups. Should get same answer for each component,
* so we need only do it once.
*/
if (ci == 0) {
main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1);
}
/* Duplicate the last real sample row rgroup*2 times; this pads out the
* last partial rowgroup and ensures at least one full rowgroup of context.
*/
xbuf = main->xbuffer[main->whichptr][ci];
for (i = 0; i < rgroup * 2; i++) {
xbuf[rows_left + i] = xbuf[rows_left-1];
}
}
}
/*
* Initialize for a processing pass.
*/
METHODDEF(void)
start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
{
my_main_ptr main = (my_main_ptr) cinfo->main;
switch (pass_mode) {
case JBUF_PASS_THRU:
if (cinfo->upsample->need_context_rows) {
main->pub.process_data = process_data_context_main;
make_funny_pointers(cinfo); /* Create the xbuffer[] lists */
main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */
main->context_state = CTX_PREPARE_FOR_IMCU;
main->iMCU_row_ctr = 0;
} else {
/* Simple case with no context needed */
main->pub.process_data = process_data_simple_main;
}
main->buffer_full = FALSE; /* Mark buffer empty */
main->rowgroup_ctr = 0;
break;
#ifdef QUANT_2PASS_SUPPORTED
case JBUF_CRANK_DEST:
/* For last pass of 2-pass quantization, just crank the postprocessor */
main->pub.process_data = process_data_crank_post;
break;
#endif
default:
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
break;
}
}
/*
* Process some data.
* This handles the simple case where no context is required.
*/
METHODDEF(void)
process_data_simple_main (j_decompress_ptr cinfo,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
{
my_main_ptr main = (my_main_ptr) cinfo->main;
JDIMENSION rowgroups_avail;
/* Read input data if we haven't filled the main buffer yet */
if (! main->buffer_full) {
if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer))
return; /* suspension forced, can do nothing more */
main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
}
/* There are always min_DCT_scaled_size row groups in an iMCU row. */
rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size;
/* Note: at the bottom of the image, we may pass extra garbage row groups
* to the postprocessor. The postprocessor has to check for bottom
* of image anyway (at row resolution), so no point in us doing it too.
*/
/* Feed the postprocessor */
(*cinfo->post->post_process_data) (cinfo, main->buffer,
&main->rowgroup_ctr, rowgroups_avail,
output_buf, out_row_ctr, out_rows_avail);
/* Has postprocessor consumed all the data yet? If so, mark buffer empty */
if (main->rowgroup_ctr >= rowgroups_avail) {
main->buffer_full = FALSE;
main->rowgroup_ctr = 0;
}
}
/*
* Process some data.
* This handles the case where context rows must be provided.
*/
METHODDEF(void)
process_data_context_main (j_decompress_ptr cinfo,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
{
my_main_ptr main = (my_main_ptr) cinfo->main;
/* Read input data if we haven't filled the main buffer yet */
if (! main->buffer_full) {
if (! (*cinfo->coef->decompress_data) (cinfo,
main->xbuffer[main->whichptr]))
return; /* suspension forced, can do nothing more */
main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
main->iMCU_row_ctr++; /* count rows received */
}
/* Postprocessor typically will not swallow all the input data it is handed
* in one call (due to filling the output buffer first). Must be prepared
* to exit and restart. This switch lets us keep track of how far we got.
* Note that each case falls through to the next on successful completion.
*/
switch (main->context_state) {
case CTX_POSTPONED_ROW:
/* Call postprocessor using previously set pointers for postponed row */
(*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
&main->rowgroup_ctr, main->rowgroups_avail,
output_buf, out_row_ctr, out_rows_avail);
if (main->rowgroup_ctr < main->rowgroups_avail)
return; /* Need to suspend */
main->context_state = CTX_PREPARE_FOR_IMCU;
if (*out_row_ctr >= out_rows_avail)
return; /* Postprocessor exactly filled output buf */
/*FALLTHROUGH*/
case CTX_PREPARE_FOR_IMCU:
/* Prepare to process first M-1 row groups of this iMCU row */
main->rowgroup_ctr = 0;
main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1);
/* Check for bottom of image: if so, tweak pointers to "duplicate"
* the last sample row, and adjust rowgroups_avail to ignore padding rows.
*/
if (main->iMCU_row_ctr == cinfo->total_iMCU_rows)
set_bottom_pointers(cinfo);
main->context_state = CTX_PROCESS_IMCU;
/*FALLTHROUGH*/
case CTX_PROCESS_IMCU:
/* Call postprocessor using previously set pointers */
(*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
&main->rowgroup_ctr, main->rowgroups_avail,
output_buf, out_row_ctr, out_rows_avail);
if (main->rowgroup_ctr < main->rowgroups_avail)
return; /* Need to suspend */
/* After the first iMCU, change wraparound pointers to normal state */
if (main->iMCU_row_ctr == 1)
set_wraparound_pointers(cinfo);
/* Prepare to load new iMCU row using other xbuffer list */
main->whichptr ^= 1; /* 0=>1 or 1=>0 */
main->buffer_full = FALSE;
/* Still need to process last row group of this iMCU row, */
/* which is saved at index M+1 of the other xbuffer */
main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1);
main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2);
main->context_state = CTX_POSTPONED_ROW;
}
}
/*
* Process some data.
* Final pass of two-pass quantization: just call the postprocessor.
* Source data will be the postprocessor controller's internal buffer.
*/
#ifdef QUANT_2PASS_SUPPORTED
METHODDEF(void)
process_data_crank_post (j_decompress_ptr cinfo,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
{
(*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL,
(JDIMENSION *) NULL, (JDIMENSION) 0,
output_buf, out_row_ctr, out_rows_avail);
}
#endif /* QUANT_2PASS_SUPPORTED */
/*
* Initialize main buffer controller.
*/
GLOBAL(void)
jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
{
my_main_ptr main;
int ci, rgroup, ngroups;
jpeg_component_info *compptr;
main = (my_main_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_main_controller));
cinfo->main = (struct jpeg_d_main_controller *) main;
main->pub.start_pass = start_pass_main;
if (need_full_buffer) /* shouldn't happen */
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
/* Allocate the workspace.
* ngroups is the number of row groups we need.
*/
if (cinfo->upsample->need_context_rows) {
if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */
ERREXIT(cinfo, JERR_NOTIMPL);
alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */
ngroups = cinfo->min_DCT_scaled_size + 2;
} else {
ngroups = cinfo->min_DCT_scaled_size;
}
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
cinfo->min_DCT_scaled_size; /* height of a row group of component */
main->buffer[ci] = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
compptr->width_in_blocks * compptr->DCT_scaled_size,
(JDIMENSION) (rgroup * ngroups));
}
}

1360
jdmarker.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,176 +1,568 @@
/*
* jdmaster.c
*
* Copyright (C) 1991, 1992, 1993, Thomas G. Lane.
* Copyright (C) 1991-1997, Thomas G. Lane.
* Copyright (C) 2009, D. R. Commander.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the main control for the JPEG decompressor.
* The system-dependent (user interface) code should call jpeg_decompress()
* after doing appropriate setup of the decompress_info_struct parameter.
* This file contains master control logic for the JPEG decompressor.
* These routines are concerned with selecting the modules to be executed
* and with determining the number of passes and the work to be done in each
* pass.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
METHODDEF void
d_per_scan_method_selection (decompress_info_ptr cinfo)
/* Central point for per-scan method selection */
/* Private state */
typedef struct {
struct jpeg_decomp_master pub; /* public fields */
int pass_number; /* # of passes completed */
boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */
/* Saved references to initialized quantizer modules,
* in case we need to switch modes.
*/
struct jpeg_color_quantizer * quantizer_1pass;
struct jpeg_color_quantizer * quantizer_2pass;
} my_decomp_master;
typedef my_decomp_master * my_master_ptr;
/*
* Determine whether merged upsample/color conversion should be used.
* CRUCIAL: this must match the actual capabilities of jdmerge.c!
*/
LOCAL(boolean)
use_merged_upsample (j_decompress_ptr cinfo)
{
/* MCU disassembly */
jseldmcu(cinfo);
/* Upsampling of pixels */
jselupsample(cinfo);
}
LOCAL void
d_initial_method_selection (decompress_info_ptr cinfo)
/* Central point for initial method selection (after reading file header) */
{
/* JPEG file scanning method selection is already done. */
/* So is output file format selection (both are done by user interface). */
/* Gamma and color space conversion */
/* NB: this may change the component_needed flags */
jseldcolor(cinfo);
/* Color quantization selection rules */
#ifdef QUANT_1PASS_SUPPORTED
#ifdef QUANT_2PASS_SUPPORTED
/* We have both, check for conditions in which 1-pass should be used */
if (cinfo->num_components != 3 || cinfo->jpeg_color_space != CS_YCbCr)
cinfo->two_pass_quantize = FALSE; /* 2-pass only handles YCbCr input */
if (cinfo->out_color_space == CS_GRAYSCALE)
cinfo->two_pass_quantize = FALSE; /* Should use 1-pass for grayscale out */
#else /* not QUANT_2PASS_SUPPORTED */
cinfo->two_pass_quantize = FALSE; /* only have 1-pass */
#endif
#else /* not QUANT_1PASS_SUPPORTED */
#ifdef QUANT_2PASS_SUPPORTED
cinfo->two_pass_quantize = TRUE; /* only have 2-pass */
#else /* not QUANT_2PASS_SUPPORTED */
if (cinfo->quantize_colors) {
ERREXIT(cinfo->emethods, "Color quantization was not compiled");
}
#endif
#endif
#ifdef QUANT_1PASS_SUPPORTED
jsel1quantize(cinfo);
#endif
#ifdef QUANT_2PASS_SUPPORTED
jsel2quantize(cinfo);
#endif
/* Cross-block smoothing */
#ifdef BLOCK_SMOOTHING_SUPPORTED
jselbsmooth(cinfo);
#ifdef UPSAMPLE_MERGING_SUPPORTED
/* Merging is the equivalent of plain box-filter upsampling */
if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling)
return FALSE;
/* jdmerge.c only supports YCC=>RGB color conversion */
if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 ||
(cinfo->out_color_space != JCS_RGB &&
cinfo->out_color_space != JCS_EXT_RGB &&
cinfo->out_color_space != JCS_EXT_RGBX &&
cinfo->out_color_space != JCS_EXT_BGR &&
cinfo->out_color_space != JCS_EXT_BGRX &&
cinfo->out_color_space != JCS_EXT_XBGR &&
cinfo->out_color_space != JCS_EXT_XRGB) ||
cinfo->out_color_components != rgb_pixelsize[cinfo->out_color_space])
return FALSE;
/* and it only handles 2h1v or 2h2v sampling ratios */
if (cinfo->comp_info[0].h_samp_factor != 2 ||
cinfo->comp_info[1].h_samp_factor != 1 ||
cinfo->comp_info[2].h_samp_factor != 1 ||
cinfo->comp_info[0].v_samp_factor > 2 ||
cinfo->comp_info[1].v_samp_factor != 1 ||
cinfo->comp_info[2].v_samp_factor != 1)
return FALSE;
/* furthermore, it doesn't work if we've scaled the IDCTs differently */
if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size)
return FALSE;
/* ??? also need to test for upsample-time rescaling, when & if supported */
return TRUE; /* by golly, it'll work... */
#else
cinfo->do_block_smoothing = FALSE;
return FALSE;
#endif
/* Entropy decoding: either Huffman or arithmetic coding. */
#ifdef D_ARITH_CODING_SUPPORTED
jseldarithmetic(cinfo);
#else
if (cinfo->arith_code) {
ERREXIT(cinfo->emethods, "Arithmetic coding not supported");
}
#endif
jseldhuffman(cinfo);
/* Pipeline control */
jseldpipeline(cinfo);
/* Overall control (that's me!) */
cinfo->methods->d_per_scan_method_selection = d_per_scan_method_selection;
}
LOCAL void
initial_setup (decompress_info_ptr cinfo)
/* Do computations that are needed before initial method selection */
/*
* Compute output image dimensions and related values.
* NOTE: this is exported for possible use by application.
* Hence it mustn't do anything that can't be done twice.
* Also note that it may be called before the master module is initialized!
*/
GLOBAL(void)
jpeg_calc_output_dimensions (j_decompress_ptr cinfo)
/* Do computations that are needed before master selection phase */
{
short ci;
#ifdef IDCT_SCALING_SUPPORTED
int ci;
jpeg_component_info *compptr;
#endif
/* Compute maximum sampling factors; check factor validity */
cinfo->max_h_samp_factor = 1;
cinfo->max_v_samp_factor = 1;
for (ci = 0; ci < cinfo->num_components; ci++) {
compptr = &cinfo->comp_info[ci];
if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
ERREXIT(cinfo->emethods, "Bogus sampling factors");
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
compptr->h_samp_factor);
cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
compptr->v_samp_factor);
/* Prevent application from calling me at wrong times */
if (cinfo->global_state != DSTATE_READY)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
#ifdef IDCT_SCALING_SUPPORTED
/* Compute actual output image dimensions and DCT scaling choices. */
if (cinfo->scale_num * 8 <= cinfo->scale_denom) {
/* Provide 1/8 scaling */
cinfo->output_width = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width, 8L);
cinfo->output_height = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height, 8L);
cinfo->min_DCT_scaled_size = 1;
} else if (cinfo->scale_num * 4 <= cinfo->scale_denom) {
/* Provide 1/4 scaling */
cinfo->output_width = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width, 4L);
cinfo->output_height = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height, 4L);
cinfo->min_DCT_scaled_size = 2;
} else if (cinfo->scale_num * 2 <= cinfo->scale_denom) {
/* Provide 1/2 scaling */
cinfo->output_width = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width, 2L);
cinfo->output_height = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height, 2L);
cinfo->min_DCT_scaled_size = 4;
} else {
/* Provide 1/1 scaling */
cinfo->output_width = cinfo->image_width;
cinfo->output_height = cinfo->image_height;
cinfo->min_DCT_scaled_size = DCTSIZE;
}
/* In selecting the actual DCT scaling for each component, we try to
* scale up the chroma components via IDCT scaling rather than upsampling.
* This saves time if the upsampler gets to use 1:1 scaling.
* Note this code assumes that the supported DCT scalings are powers of 2.
*/
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
int ssize = cinfo->min_DCT_scaled_size;
while (ssize < DCTSIZE &&
(compptr->h_samp_factor * ssize * 2 <=
cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) &&
(compptr->v_samp_factor * ssize * 2 <=
cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) {
ssize = ssize * 2;
}
compptr->DCT_scaled_size = ssize;
}
/* Compute logical downsampled dimensions of components */
for (ci = 0; ci < cinfo->num_components; ci++) {
compptr = &cinfo->comp_info[ci];
compptr->true_comp_width = (cinfo->image_width * compptr->h_samp_factor
+ cinfo->max_h_samp_factor - 1)
/ cinfo->max_h_samp_factor;
compptr->true_comp_height = (cinfo->image_height * compptr->v_samp_factor
+ cinfo->max_v_samp_factor - 1)
/ cinfo->max_v_samp_factor;
/* Recompute downsampled dimensions of components;
* application needs to know these if using raw downsampled data.
*/
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Size in samples, after IDCT scaling */
compptr->downsampled_width = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width *
(long) (compptr->h_samp_factor * compptr->DCT_scaled_size),
(long) (cinfo->max_h_samp_factor * DCTSIZE));
compptr->downsampled_height = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height *
(long) (compptr->v_samp_factor * compptr->DCT_scaled_size),
(long) (cinfo->max_v_samp_factor * DCTSIZE));
}
#else /* !IDCT_SCALING_SUPPORTED */
/* Hardwire it to "no scaling" */
cinfo->output_width = cinfo->image_width;
cinfo->output_height = cinfo->image_height;
/* jdinput.c has already initialized DCT_scaled_size to DCTSIZE,
* and has computed unscaled downsampled_width and downsampled_height.
*/
#endif /* IDCT_SCALING_SUPPORTED */
/* Report number of components in selected colorspace. */
/* Probably this should be in the color conversion module... */
switch (cinfo->out_color_space) {
case JCS_GRAYSCALE:
cinfo->out_color_components = 1;
break;
case JCS_RGB:
case JCS_EXT_RGB:
case JCS_EXT_RGBX:
case JCS_EXT_BGR:
case JCS_EXT_BGRX:
case JCS_EXT_XBGR:
case JCS_EXT_XRGB:
cinfo->out_color_components = rgb_pixelsize[cinfo->out_color_space];
break;
case JCS_YCbCr:
cinfo->out_color_components = 3;
break;
case JCS_CMYK:
case JCS_YCCK:
cinfo->out_color_components = 4;
break;
default: /* else must be same colorspace as in file */
cinfo->out_color_components = cinfo->num_components;
break;
}
cinfo->output_components = (cinfo->quantize_colors ? 1 :
cinfo->out_color_components);
/* See if upsampler will want to emit more than one row at a time */
if (use_merged_upsample(cinfo))
cinfo->rec_outbuf_height = cinfo->max_v_samp_factor;
else
cinfo->rec_outbuf_height = 1;
}
/*
* Several decompression processes need to range-limit values to the range
* 0..MAXJSAMPLE; the input value may fall somewhat outside this range
* due to noise introduced by quantization, roundoff error, etc. These
* processes are inner loops and need to be as fast as possible. On most
* machines, particularly CPUs with pipelines or instruction prefetch,
* a (subscript-check-less) C table lookup
* x = sample_range_limit[x];
* is faster than explicit tests
* if (x < 0) x = 0;
* else if (x > MAXJSAMPLE) x = MAXJSAMPLE;
* These processes all use a common table prepared by the routine below.
*
* For most steps we can mathematically guarantee that the initial value
* of x is within MAXJSAMPLE+1 of the legal range, so a table running from
* -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial
* limiting step (just after the IDCT), a wildly out-of-range value is
* possible if the input data is corrupt. To avoid any chance of indexing
* off the end of memory and getting a bad-pointer trap, we perform the
* post-IDCT limiting thus:
* x = range_limit[x & MASK];
* where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit
* samples. Under normal circumstances this is more than enough range and
* a correct output will be generated; with bogus input data the mask will
* cause wraparound, and we will safely generate a bogus-but-in-range output.
* For the post-IDCT step, we want to convert the data from signed to unsigned
* representation by adding CENTERJSAMPLE at the same time that we limit it.
* So the post-IDCT limiting table ends up looking like this:
* CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE,
* MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
* 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
* 0,1,...,CENTERJSAMPLE-1
* Negative inputs select values from the upper half of the table after
* masking.
*
* We can save some space by overlapping the start of the post-IDCT table
* with the simpler range limiting table. The post-IDCT table begins at
* sample_range_limit + CENTERJSAMPLE.
*
* Note that the table is allocated in near data space on PCs; it's small
* enough and used often enough to justify this.
*/
LOCAL(void)
prepare_range_limit_table (j_decompress_ptr cinfo)
/* Allocate and fill in the sample_range_limit table */
{
JSAMPLE * table;
int i;
table = (JSAMPLE *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE));
table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */
cinfo->sample_range_limit = table;
/* First segment of "simple" table: limit[x] = 0 for x < 0 */
MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE));
/* Main part of "simple" table: limit[x] = x */
for (i = 0; i <= MAXJSAMPLE; i++)
table[i] = (JSAMPLE) i;
table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */
/* End of simple table, rest of first half of post-IDCT table */
for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++)
table[i] = MAXJSAMPLE;
/* Second half of post-IDCT table */
MEMZERO(table + (2 * (MAXJSAMPLE+1)),
(2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE));
MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE),
cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE));
}
/*
* Master selection of decompression modules.
* This is done once at jpeg_start_decompress time. We determine
* which modules will be used and give them appropriate initialization calls.
* We also initialize the decompressor input side to begin consuming data.
*
* Since jpeg_read_header has finished, we know what is in the SOF
* and (first) SOS markers. We also have all the application parameter
* settings.
*/
LOCAL(void)
master_selection (j_decompress_ptr cinfo)
{
my_master_ptr master = (my_master_ptr) cinfo->master;
boolean use_c_buffer;
long samplesperrow;
JDIMENSION jd_samplesperrow;
/* Initialize dimensions and other stuff */
jpeg_calc_output_dimensions(cinfo);
prepare_range_limit_table(cinfo);
/* Width of an output scanline must be representable as JDIMENSION. */
samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components;
jd_samplesperrow = (JDIMENSION) samplesperrow;
if ((long) jd_samplesperrow != samplesperrow)
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
/* Initialize my private state */
master->pass_number = 0;
master->using_merged_upsample = use_merged_upsample(cinfo);
/* Color quantizer selection */
master->quantizer_1pass = NULL;
master->quantizer_2pass = NULL;
/* No mode changes if not using buffered-image mode. */
if (! cinfo->quantize_colors || ! cinfo->buffered_image) {
cinfo->enable_1pass_quant = FALSE;
cinfo->enable_external_quant = FALSE;
cinfo->enable_2pass_quant = FALSE;
}
if (cinfo->quantize_colors) {
if (cinfo->raw_data_out)
ERREXIT(cinfo, JERR_NOTIMPL);
/* 2-pass quantizer only works in 3-component color space. */
if (cinfo->out_color_components != 3) {
cinfo->enable_1pass_quant = TRUE;
cinfo->enable_external_quant = FALSE;
cinfo->enable_2pass_quant = FALSE;
cinfo->colormap = NULL;
} else if (cinfo->colormap != NULL) {
cinfo->enable_external_quant = TRUE;
} else if (cinfo->two_pass_quantize) {
cinfo->enable_2pass_quant = TRUE;
} else {
cinfo->enable_1pass_quant = TRUE;
}
if (cinfo->enable_1pass_quant) {
#ifdef QUANT_1PASS_SUPPORTED
jinit_1pass_quantizer(cinfo);
master->quantizer_1pass = cinfo->cquantize;
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
}
/* We use the 2-pass code to map to external colormaps. */
if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) {
#ifdef QUANT_2PASS_SUPPORTED
jinit_2pass_quantizer(cinfo);
master->quantizer_2pass = cinfo->cquantize;
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
}
/* If both quantizers are initialized, the 2-pass one is left active;
* this is necessary for starting with quantization to an external map.
*/
}
/* Post-processing: in particular, color conversion first */
if (! cinfo->raw_data_out) {
if (master->using_merged_upsample) {
#ifdef UPSAMPLE_MERGING_SUPPORTED
jinit_merged_upsampler(cinfo); /* does color conversion too */
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
} else {
jinit_color_deconverter(cinfo);
jinit_upsampler(cinfo);
}
jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant);
}
/* Inverse DCT */
jinit_inverse_dct(cinfo);
/* Entropy decoding: either Huffman or arithmetic coding. */
if (cinfo->arith_code) {
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
} else {
if (cinfo->progressive_mode) {
#ifdef D_PROGRESSIVE_SUPPORTED
jinit_phuff_decoder(cinfo);
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
} else
jinit_huff_decoder(cinfo);
}
/* Initialize principal buffer controllers. */
use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
jinit_d_coef_controller(cinfo, use_c_buffer);
if (! cinfo->raw_data_out)
jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */);
/* We can now tell the memory manager to allocate virtual arrays. */
(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
/* Initialize input side of decompressor to consume first scan. */
(*cinfo->inputctl->start_input_pass) (cinfo);
#ifdef D_MULTISCAN_FILES_SUPPORTED
/* If jpeg_start_decompress will read the whole file, initialize
* progress monitoring appropriately. The input step is counted
* as one pass.
*/
if (cinfo->progress != NULL && ! cinfo->buffered_image &&
cinfo->inputctl->has_multiple_scans) {
int nscans;
/* Estimate number of scans to set pass_limit. */
if (cinfo->progressive_mode) {
/* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
nscans = 2 + 3 * cinfo->num_components;
} else {
/* For a nonprogressive multiscan file, estimate 1 scan per component. */
nscans = cinfo->num_components;
}
cinfo->progress->pass_counter = 0L;
cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
cinfo->progress->completed_passes = 0;
cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2);
/* Count the input pass as done */
master->pass_number++;
}
#endif /* D_MULTISCAN_FILES_SUPPORTED */
}
/*
* Per-pass setup.
* This is called at the beginning of each output pass. We determine which
* modules will be active during this pass and give them appropriate
* start_pass calls. We also set is_dummy_pass to indicate whether this
* is a "real" output pass or a dummy pass for color quantization.
* (In the latter case, jdapistd.c will crank the pass to completion.)
*/
METHODDEF(void)
prepare_for_output_pass (j_decompress_ptr cinfo)
{
my_master_ptr master = (my_master_ptr) cinfo->master;
if (master->pub.is_dummy_pass) {
#ifdef QUANT_2PASS_SUPPORTED
/* Final pass of 2-pass quantization */
master->pub.is_dummy_pass = FALSE;
(*cinfo->cquantize->start_pass) (cinfo, FALSE);
(*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST);
(*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST);
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif /* QUANT_2PASS_SUPPORTED */
} else {
if (cinfo->quantize_colors && cinfo->colormap == NULL) {
/* Select new quantization method */
if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) {
cinfo->cquantize = master->quantizer_2pass;
master->pub.is_dummy_pass = TRUE;
} else if (cinfo->enable_1pass_quant) {
cinfo->cquantize = master->quantizer_1pass;
} else {
ERREXIT(cinfo, JERR_MODE_CHANGE);
}
}
(*cinfo->idct->start_pass) (cinfo);
(*cinfo->coef->start_output_pass) (cinfo);
if (! cinfo->raw_data_out) {
if (! master->using_merged_upsample)
(*cinfo->cconvert->start_pass) (cinfo);
(*cinfo->upsample->start_pass) (cinfo);
if (cinfo->quantize_colors)
(*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass);
(*cinfo->post->start_pass) (cinfo,
(master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
(*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
}
}
/* Set up progress monitor's pass info if present */
if (cinfo->progress != NULL) {
cinfo->progress->completed_passes = master->pass_number;
cinfo->progress->total_passes = master->pass_number +
(master->pub.is_dummy_pass ? 2 : 1);
/* In buffered-image mode, we assume one more output pass if EOI not
* yet reached, but no more passes if EOI has been reached.
*/
if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) {
cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1);
}
}
}
/*
* This is the main entry point to the JPEG decompressor.
* Finish up at end of an output pass.
*/
GLOBAL void
jpeg_decompress (decompress_info_ptr cinfo)
METHODDEF(void)
finish_output_pass (j_decompress_ptr cinfo)
{
/* Init pass counts to 0 --- total_passes is adjusted in method selection */
cinfo->total_passes = 0;
cinfo->completed_passes = 0;
my_master_ptr master = (my_master_ptr) cinfo->master;
/* Read the JPEG file header markers; everything up through the first SOS
* marker is read now. NOTE: the user interface must have initialized the
* read_file_header method pointer (eg, by calling jselrjfif or jselrtiff).
* The other file reading methods (read_scan_header etc.) were probably
* set at the same time, but could be set up by read_file_header itself.
*/
(*cinfo->methods->read_file_header) (cinfo);
if (! ((*cinfo->methods->read_scan_header) (cinfo)))
ERREXIT(cinfo->emethods, "Empty JPEG file");
/* Give UI a chance to adjust decompression parameters and select */
/* output file format based on info from file header. */
(*cinfo->methods->d_ui_method_selection) (cinfo);
/* Now select methods for decompression steps. */
initial_setup(cinfo);
d_initial_method_selection(cinfo);
/* Initialize the output file & other modules as needed */
/* (modules needing per-scan init are called by pipeline controller) */
(*cinfo->methods->output_init) (cinfo);
(*cinfo->methods->colorout_init) (cinfo);
if (cinfo->quantize_colors)
(*cinfo->methods->color_quant_init) (cinfo);
/* And let the pipeline controller do the rest. */
(*cinfo->methods->d_pipeline_controller) (cinfo);
/* Finish output file, release working storage, etc */
if (cinfo->quantize_colors)
(*cinfo->methods->color_quant_term) (cinfo);
(*cinfo->methods->colorout_term) (cinfo);
(*cinfo->methods->output_term) (cinfo);
(*cinfo->methods->read_file_trailer) (cinfo);
(*cinfo->emethods->free_all) ();
/* My, that was easy, wasn't it? */
(*cinfo->cquantize->finish_pass) (cinfo);
master->pass_number++;
}
#ifdef D_MULTISCAN_FILES_SUPPORTED
/*
* Switch to a new external colormap between output passes.
*/
GLOBAL(void)
jpeg_new_colormap (j_decompress_ptr cinfo)
{
my_master_ptr master = (my_master_ptr) cinfo->master;
/* Prevent application from calling me at wrong times */
if (cinfo->global_state != DSTATE_BUFIMAGE)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (cinfo->quantize_colors && cinfo->enable_external_quant &&
cinfo->colormap != NULL) {
/* Select 2-pass quantizer for external colormap use */
cinfo->cquantize = master->quantizer_2pass;
/* Notify quantizer of colormap change */
(*cinfo->cquantize->new_color_map) (cinfo);
master->pub.is_dummy_pass = FALSE; /* just in case */
} else
ERREXIT(cinfo, JERR_MODE_CHANGE);
}
#endif /* D_MULTISCAN_FILES_SUPPORTED */
/*
* Initialize master decompression control and select active modules.
* This is performed at the start of jpeg_start_decompress.
*/
GLOBAL(void)
jinit_master_decompress (j_decompress_ptr cinfo)
{
my_master_ptr master;
master = (my_master_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_decomp_master));
cinfo->master = (struct jpeg_decomp_master *) master;
master->pub.prepare_for_output_pass = prepare_for_output_pass;
master->pub.finish_output_pass = finish_output_pass;
master->pub.is_dummy_pass = FALSE;
master_selection(cinfo);
}

215
jdmcu.c
View File

@@ -1,215 +0,0 @@
/*
* jdmcu.c
*
* Copyright (C) 1991, 1992, 1993, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains MCU disassembly and IDCT control routines.
* These routines are invoked via the disassemble_MCU, reverse_DCT, and
* disassemble_init/term methods.
*/
#include "jinclude.h"
/*
* Fetch one MCU row from entropy_decode, build coefficient array.
* This version is used for noninterleaved (single-component) scans.
*/
METHODDEF void
disassemble_noninterleaved_MCU (decompress_info_ptr cinfo,
JBLOCKIMAGE image_data)
{
JBLOCKROW MCU_data[1];
long mcuindex;
/* this is pretty easy since there is one component and one block per MCU */
/* Pre-zero the target area to speed up entropy decoder */
/* (we assume wholesale zeroing is faster than retail) */
jzero_far((void FAR *) image_data[0][0],
(size_t) (cinfo->MCUs_per_row * SIZEOF(JBLOCK)));
for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
/* Point to the proper spot in the image array for this MCU */
MCU_data[0] = image_data[0][0] + mcuindex;
/* Fetch the coefficient data */
(*cinfo->methods->entropy_decode) (cinfo, MCU_data);
}
}
/*
* Fetch one MCU row from entropy_decode, build coefficient array.
* This version is used for interleaved (multi-component) scans.
*/
METHODDEF void
disassemble_interleaved_MCU (decompress_info_ptr cinfo,
JBLOCKIMAGE image_data)
{
JBLOCKROW MCU_data[MAX_BLOCKS_IN_MCU];
long mcuindex;
short blkn, ci, xpos, ypos;
jpeg_component_info * compptr;
JBLOCKROW image_ptr;
/* Pre-zero the target area to speed up entropy decoder */
/* (we assume wholesale zeroing is faster than retail) */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
for (ypos = 0; ypos < compptr->MCU_height; ypos++) {
jzero_far((void FAR *) image_data[ci][ypos],
(size_t) (cinfo->MCUs_per_row * compptr->MCU_width * SIZEOF(JBLOCK)));
}
}
for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
/* Point to the proper spots in the image array for this MCU */
blkn = 0;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
for (ypos = 0; ypos < compptr->MCU_height; ypos++) {
image_ptr = image_data[ci][ypos] + (mcuindex * compptr->MCU_width);
for (xpos = 0; xpos < compptr->MCU_width; xpos++) {
MCU_data[blkn] = image_ptr;
image_ptr++;
blkn++;
}
}
}
/* Fetch the coefficient data */
(*cinfo->methods->entropy_decode) (cinfo, MCU_data);
}
}
/*
* Perform inverse DCT on each block in an MCU row's worth of data;
* output the results into a sample array starting at row start_row.
* NB: start_row can only be nonzero when dealing with a single-component
* scan; otherwise we'd have to pass different offsets for different
* components, since the heights of interleaved MCU rows can vary.
* But the pipeline controller logic is such that this is not necessary.
*/
METHODDEF void
reverse_DCT (decompress_info_ptr cinfo,
JBLOCKIMAGE coeff_data, JSAMPIMAGE output_data, int start_row)
{
DCTBLOCK block;
JBLOCKROW browptr;
JSAMPARRAY srowptr;
jpeg_component_info * compptr;
long blocksperrow, bi;
short numrows, ri;
short ci;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* don't bother to IDCT an uninteresting component */
if (! compptr->component_needed)
continue;
/* calculate size of an MCU row in this component */
blocksperrow = compptr->downsampled_width / DCTSIZE;
numrows = compptr->MCU_height;
/* iterate through all blocks in MCU row */
for (ri = 0; ri < numrows; ri++) {
browptr = coeff_data[ci][ri];
srowptr = output_data[ci] + (ri * DCTSIZE + start_row);
for (bi = 0; bi < blocksperrow; bi++) {
/* copy the data into a local DCTBLOCK. This allows for change of
* representation (if DCTELEM != JCOEF). On 80x86 machines it also
* brings the data back from FAR storage to NEAR storage.
*/
{ register JCOEFPTR elemptr = browptr[bi];
register DCTELEM *localblkptr = block;
register int elem = DCTSIZE2;
while (--elem >= 0)
*localblkptr++ = (DCTELEM) *elemptr++;
}
j_rev_dct(block); /* perform inverse DCT */
/* Output the data into the sample array.
* Note change from signed to unsigned representation:
* DCT calculation works with values +-CENTERJSAMPLE,
* but sample arrays always hold 0..MAXJSAMPLE.
* We have to do range-limiting because of quantization errors in the
* DCT/IDCT phase. We use the sample_range_limit[] table to do this
* quickly; the CENTERJSAMPLE offset is folded into table indexing.
*/
{ register JSAMPROW elemptr;
register DCTELEM *localblkptr = block;
register JSAMPLE *range_limit = cinfo->sample_range_limit +
CENTERJSAMPLE;
#if DCTSIZE != 8
register int elemc;
#endif
register int elemr;
for (elemr = 0; elemr < DCTSIZE; elemr++) {
elemptr = srowptr[elemr] + (bi * DCTSIZE);
#if DCTSIZE == 8 /* unroll the inner loop */
*elemptr++ = range_limit[*localblkptr++];
*elemptr++ = range_limit[*localblkptr++];
*elemptr++ = range_limit[*localblkptr++];
*elemptr++ = range_limit[*localblkptr++];
*elemptr++ = range_limit[*localblkptr++];
*elemptr++ = range_limit[*localblkptr++];
*elemptr++ = range_limit[*localblkptr++];
*elemptr++ = range_limit[*localblkptr++];
#else
for (elemc = DCTSIZE; elemc > 0; elemc--) {
*elemptr++ = range_limit[*localblkptr++];
}
#endif
}
}
}
}
}
}
/*
* Initialize for processing a scan.
*/
METHODDEF void
disassemble_init (decompress_info_ptr cinfo)
{
/* no work for now */
}
/*
* Clean up after a scan.
*/
METHODDEF void
disassemble_term (decompress_info_ptr cinfo)
{
/* no work for now */
}
/*
* The method selection routine for MCU disassembly.
*/
GLOBAL void
jseldmcu (decompress_info_ptr cinfo)
{
if (cinfo->comps_in_scan == 1)
cinfo->methods->disassemble_MCU = disassemble_noninterleaved_MCU;
else
cinfo->methods->disassemble_MCU = disassemble_interleaved_MCU;
cinfo->methods->reverse_DCT = reverse_DCT;
cinfo->methods->disassemble_init = disassemble_init;
cinfo->methods->disassemble_term = disassemble_term;
}

409
jdmerge.c Normal file
View File

@@ -0,0 +1,409 @@
/*
* jdmerge.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2009, D. R. Commander.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains code for merged upsampling/color conversion.
*
* This file combines functions from jdsample.c and jdcolor.c;
* read those files first to understand what's going on.
*
* When the chroma components are to be upsampled by simple replication
* (ie, box filtering), we can save some work in color conversion by
* calculating all the output pixels corresponding to a pair of chroma
* samples at one time. In the conversion equations
* R = Y + K1 * Cr
* G = Y + K2 * Cb + K3 * Cr
* B = Y + K4 * Cb
* only the Y term varies among the group of pixels corresponding to a pair
* of chroma samples, so the rest of the terms can be calculated just once.
* At typical sampling ratios, this eliminates half or three-quarters of the
* multiplications needed for color conversion.
*
* This file currently provides implementations for the following cases:
* YCbCr => RGB color conversion only.
* Sampling ratios of 2h1v or 2h2v.
* No scaling needed at upsample time.
* Corner-aligned (non-CCIR601) sampling alignment.
* Other special cases could be added, but in most applications these are
* the only common cases. (For uncommon cases we fall back on the more
* general code in jdsample.c and jdcolor.c.)
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jsimd.h"
#ifdef UPSAMPLE_MERGING_SUPPORTED
/* Private subobject */
typedef struct {
struct jpeg_upsampler pub; /* public fields */
/* Pointer to routine to do actual upsampling/conversion of one row group */
JMETHOD(void, upmethod, (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
JSAMPARRAY output_buf));
/* Private state for YCC->RGB conversion */
int * Cr_r_tab; /* => table for Cr to R conversion */
int * Cb_b_tab; /* => table for Cb to B conversion */
INT32 * Cr_g_tab; /* => table for Cr to G conversion */
INT32 * Cb_g_tab; /* => table for Cb to G conversion */
/* For 2:1 vertical sampling, we produce two output rows at a time.
* We need a "spare" row buffer to hold the second output row if the
* application provides just a one-row buffer; we also use the spare
* to discard the dummy last row if the image height is odd.
*/
JSAMPROW spare_row;
boolean spare_full; /* T if spare buffer is occupied */
JDIMENSION out_row_width; /* samples per output row */
JDIMENSION rows_to_go; /* counts rows remaining in image */
} my_upsampler;
typedef my_upsampler * my_upsample_ptr;
#define SCALEBITS 16 /* speediest right-shift on some machines */
#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
/*
* Initialize tables for YCC->RGB colorspace conversion.
* This is taken directly from jdcolor.c; see that file for more info.
*/
LOCAL(void)
build_ycc_rgb_table (j_decompress_ptr cinfo)
{
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
int i;
INT32 x;
SHIFT_TEMPS
upsample->Cr_r_tab = (int *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(MAXJSAMPLE+1) * SIZEOF(int));
upsample->Cb_b_tab = (int *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(MAXJSAMPLE+1) * SIZEOF(int));
upsample->Cr_g_tab = (INT32 *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(MAXJSAMPLE+1) * SIZEOF(INT32));
upsample->Cb_g_tab = (INT32 *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(MAXJSAMPLE+1) * SIZEOF(INT32));
for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
/* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
/* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
/* Cr=>R value is nearest int to 1.40200 * x */
upsample->Cr_r_tab[i] = (int)
RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
/* Cb=>B value is nearest int to 1.77200 * x */
upsample->Cb_b_tab[i] = (int)
RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
/* Cr=>G value is scaled-up -0.71414 * x */
upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x;
/* Cb=>G value is scaled-up -0.34414 * x */
/* We also add in ONE_HALF so that need not do it in inner loop */
upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
}
}
/*
* Initialize for an upsampling pass.
*/
METHODDEF(void)
start_pass_merged_upsample (j_decompress_ptr cinfo)
{
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
/* Mark the spare buffer empty */
upsample->spare_full = FALSE;
/* Initialize total-height counter for detecting bottom of image */
upsample->rows_to_go = cinfo->output_height;
}
/*
* Control routine to do upsampling (and color conversion).
*
* The control routine just handles the row buffering considerations.
*/
METHODDEF(void)
merged_2v_upsample (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
/* 2:1 vertical sampling case: may need a spare row. */
{
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
JSAMPROW work_ptrs[2];
JDIMENSION num_rows; /* number of rows returned to caller */
if (upsample->spare_full) {
/* If we have a spare row saved from a previous cycle, just return it. */
jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
1, upsample->out_row_width);
num_rows = 1;
upsample->spare_full = FALSE;
} else {
/* Figure number of rows to return to caller. */
num_rows = 2;
/* Not more than the distance to the end of the image. */
if (num_rows > upsample->rows_to_go)
num_rows = upsample->rows_to_go;
/* And not more than what the client can accept: */
out_rows_avail -= *out_row_ctr;
if (num_rows > out_rows_avail)
num_rows = out_rows_avail;
/* Create output pointer array for upsampler. */
work_ptrs[0] = output_buf[*out_row_ctr];
if (num_rows > 1) {
work_ptrs[1] = output_buf[*out_row_ctr + 1];
} else {
work_ptrs[1] = upsample->spare_row;
upsample->spare_full = TRUE;
}
/* Now do the upsampling. */
(*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs);
}
/* Adjust counts */
*out_row_ctr += num_rows;
upsample->rows_to_go -= num_rows;
/* When the buffer is emptied, declare this input row group consumed */
if (! upsample->spare_full)
(*in_row_group_ctr)++;
}
METHODDEF(void)
merged_1v_upsample (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
/* 1:1 vertical sampling case: much easier, never need a spare row. */
{
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
/* Just do the upsampling. */
(*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr,
output_buf + *out_row_ctr);
/* Adjust counts */
(*out_row_ctr)++;
(*in_row_group_ctr)++;
}
/*
* These are the routines invoked by the control routines to do
* the actual upsampling/conversion. One row group is processed per call.
*
* Note: since we may be writing directly into application-supplied buffers,
* we have to be honest about the output width; we can't assume the buffer
* has been rounded up to an even width.
*/
/*
* Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical.
*/
METHODDEF(void)
h2v1_merged_upsample (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
JSAMPARRAY output_buf)
{
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr;
JSAMPROW inptr0, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
register JSAMPLE * range_limit = cinfo->sample_range_limit;
int * Crrtab = upsample->Cr_r_tab;
int * Cbbtab = upsample->Cb_b_tab;
INT32 * Crgtab = upsample->Cr_g_tab;
INT32 * Cbgtab = upsample->Cb_g_tab;
SHIFT_TEMPS
inptr0 = input_buf[0][in_row_group_ctr];
inptr1 = input_buf[1][in_row_group_ctr];
inptr2 = input_buf[2][in_row_group_ctr];
outptr = output_buf[0];
/* Loop for each pair of output pixels */
for (col = cinfo->output_width >> 1; col > 0; col--) {
/* Do the chroma part of the calculation */
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 2 Y values and emit 2 pixels */
y = GETJSAMPLE(*inptr0++);
outptr[rgb_red[cinfo->out_color_space]] = range_limit[y + cred];
outptr[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen];
outptr[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue];
outptr += rgb_pixelsize[cinfo->out_color_space];
y = GETJSAMPLE(*inptr0++);
outptr[rgb_red[cinfo->out_color_space]] = range_limit[y + cred];
outptr[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen];
outptr[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue];
outptr += rgb_pixelsize[cinfo->out_color_space];
}
/* If image width is odd, do the last output column separately */
if (cinfo->output_width & 1) {
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr0);
outptr[rgb_red[cinfo->out_color_space]] = range_limit[y + cred];
outptr[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen];
outptr[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue];
}
}
/*
* Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical.
*/
METHODDEF(void)
h2v2_merged_upsample (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
JSAMPARRAY output_buf)
{
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr0, outptr1;
JSAMPROW inptr00, inptr01, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
register JSAMPLE * range_limit = cinfo->sample_range_limit;
int * Crrtab = upsample->Cr_r_tab;
int * Cbbtab = upsample->Cb_b_tab;
INT32 * Crgtab = upsample->Cr_g_tab;
INT32 * Cbgtab = upsample->Cb_g_tab;
SHIFT_TEMPS
inptr00 = input_buf[0][in_row_group_ctr*2];
inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
inptr1 = input_buf[1][in_row_group_ctr];
inptr2 = input_buf[2][in_row_group_ctr];
outptr0 = output_buf[0];
outptr1 = output_buf[1];
/* Loop for each group of output pixels */
for (col = cinfo->output_width >> 1; col > 0; col--) {
/* Do the chroma part of the calculation */
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 4 Y values and emit 4 pixels */
y = GETJSAMPLE(*inptr00++);
outptr0[rgb_red[cinfo->out_color_space]] = range_limit[y + cred];
outptr0[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen];
outptr0[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue];
outptr0 += RGB_PIXELSIZE;
y = GETJSAMPLE(*inptr00++);
outptr0[rgb_red[cinfo->out_color_space]] = range_limit[y + cred];
outptr0[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen];
outptr0[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue];
outptr0 += RGB_PIXELSIZE;
y = GETJSAMPLE(*inptr01++);
outptr1[rgb_red[cinfo->out_color_space]] = range_limit[y + cred];
outptr1[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen];
outptr1[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue];
outptr1 += RGB_PIXELSIZE;
y = GETJSAMPLE(*inptr01++);
outptr1[rgb_red[cinfo->out_color_space]] = range_limit[y + cred];
outptr1[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen];
outptr1[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue];
outptr1 += RGB_PIXELSIZE;
}
/* If image width is odd, do the last output column separately */
if (cinfo->output_width & 1) {
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr00);
outptr0[rgb_red[cinfo->out_color_space]] = range_limit[y + cred];
outptr0[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen];
outptr0[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue];
y = GETJSAMPLE(*inptr01);
outptr1[rgb_red[cinfo->out_color_space]] = range_limit[y + cred];
outptr1[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen];
outptr1[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue];
}
}
/*
* Module initialization routine for merged upsampling/color conversion.
*
* NB: this is called under the conditions determined by use_merged_upsample()
* in jdmaster.c. That routine MUST correspond to the actual capabilities
* of this module; no safety checks are made here.
*/
GLOBAL(void)
jinit_merged_upsampler (j_decompress_ptr cinfo)
{
my_upsample_ptr upsample;
upsample = (my_upsample_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_upsampler));
cinfo->upsample = (struct jpeg_upsampler *) upsample;
upsample->pub.start_pass = start_pass_merged_upsample;
upsample->pub.need_context_rows = FALSE;
upsample->out_row_width = cinfo->output_width * cinfo->out_color_components;
if (cinfo->max_v_samp_factor == 2) {
upsample->pub.upsample = merged_2v_upsample;
if (jsimd_can_h2v2_merged_upsample())
upsample->upmethod = jsimd_h2v2_merged_upsample;
else
upsample->upmethod = h2v2_merged_upsample;
/* Allocate a spare row buffer */
upsample->spare_row = (JSAMPROW)
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(size_t) (upsample->out_row_width * SIZEOF(JSAMPLE)));
} else {
upsample->pub.upsample = merged_1v_upsample;
if (jsimd_can_h2v1_merged_upsample())
upsample->upmethod = jsimd_h2v1_merged_upsample;
else
upsample->upmethod = h2v1_merged_upsample;
/* No spare row needed */
upsample->spare_row = NULL;
}
build_ycc_rgb_table(cinfo);
}
#endif /* UPSAMPLE_MERGING_SUPPORTED */

668
jdphuff.c Normal file
View File

@@ -0,0 +1,668 @@
/*
* jdphuff.c
*
* Copyright (C) 1995-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains Huffman entropy decoding routines for progressive JPEG.
*
* Much of the complexity here has to do with supporting input suspension.
* If the data source module demands suspension, we want to be able to back
* up to the start of the current MCU. To do this, we copy state variables
* into local working storage, and update them back to the permanent
* storage only upon successful completion of an MCU.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdhuff.h" /* Declarations shared with jdhuff.c */
#ifdef D_PROGRESSIVE_SUPPORTED
/*
* Expanded entropy decoder object for progressive Huffman decoding.
*
* The savable_state subrecord contains fields that change within an MCU,
* but must not be updated permanently until we complete the MCU.
*/
typedef struct {
unsigned int EOBRUN; /* remaining EOBs in EOBRUN */
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
} savable_state;
/* This macro is to work around compilers with missing or broken
* structure assignment. You'll need to fix this code if you have
* such a compiler and you change MAX_COMPS_IN_SCAN.
*/
#ifndef NO_STRUCT_ASSIGN
#define ASSIGN_STATE(dest,src) ((dest) = (src))
#else
#if MAX_COMPS_IN_SCAN == 4
#define ASSIGN_STATE(dest,src) \
((dest).EOBRUN = (src).EOBRUN, \
(dest).last_dc_val[0] = (src).last_dc_val[0], \
(dest).last_dc_val[1] = (src).last_dc_val[1], \
(dest).last_dc_val[2] = (src).last_dc_val[2], \
(dest).last_dc_val[3] = (src).last_dc_val[3])
#endif
#endif
typedef struct {
struct jpeg_entropy_decoder pub; /* public fields */
/* These fields are loaded into local variables at start of each MCU.
* In case of suspension, we exit WITHOUT updating them.
*/
bitread_perm_state bitstate; /* Bit buffer at start of MCU */
savable_state saved; /* Other state at start of MCU */
/* These fields are NOT loaded into local working state. */
unsigned int restarts_to_go; /* MCUs left in this restart interval */
/* Pointers to derived tables (these workspaces have image lifespan) */
d_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */
} phuff_entropy_decoder;
typedef phuff_entropy_decoder * phuff_entropy_ptr;
/* Forward declarations */
METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo,
JBLOCKROW *MCU_data));
METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo,
JBLOCKROW *MCU_data));
METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo,
JBLOCKROW *MCU_data));
METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo,
JBLOCKROW *MCU_data));
/*
* Initialize for a Huffman-compressed scan.
*/
METHODDEF(void)
start_pass_phuff_decoder (j_decompress_ptr cinfo)
{
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
boolean is_DC_band, bad;
int ci, coefi, tbl;
int *coef_bit_ptr;
jpeg_component_info * compptr;
is_DC_band = (cinfo->Ss == 0);
/* Validate scan parameters */
bad = FALSE;
if (is_DC_band) {
if (cinfo->Se != 0)
bad = TRUE;
} else {
/* need not check Ss/Se < 0 since they came from unsigned bytes */
if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2)
bad = TRUE;
/* AC scans may have only one component */
if (cinfo->comps_in_scan != 1)
bad = TRUE;
}
if (cinfo->Ah != 0) {
/* Successive approximation refinement scan: must have Al = Ah-1. */
if (cinfo->Al != cinfo->Ah-1)
bad = TRUE;
}
if (cinfo->Al > 13) /* need not check for < 0 */
bad = TRUE;
/* Arguably the maximum Al value should be less than 13 for 8-bit precision,
* but the spec doesn't say so, and we try to be liberal about what we
* accept. Note: large Al values could result in out-of-range DC
* coefficients during early scans, leading to bizarre displays due to
* overflows in the IDCT math. But we won't crash.
*/
if (bad)
ERREXIT4(cinfo, JERR_BAD_PROGRESSION,
cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al);
/* Update progression status, and verify that scan order is legal.
* Note that inter-scan inconsistencies are treated as warnings
* not fatal errors ... not clear if this is right way to behave.
*/
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
int cindex = cinfo->cur_comp_info[ci]->component_index;
coef_bit_ptr = & cinfo->coef_bits[cindex][0];
if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */
WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) {
int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi];
if (cinfo->Ah != expected)
WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi);
coef_bit_ptr[coefi] = cinfo->Al;
}
}
/* Select MCU decoding routine */
if (cinfo->Ah == 0) {
if (is_DC_band)
entropy->pub.decode_mcu = decode_mcu_DC_first;
else
entropy->pub.decode_mcu = decode_mcu_AC_first;
} else {
if (is_DC_band)
entropy->pub.decode_mcu = decode_mcu_DC_refine;
else
entropy->pub.decode_mcu = decode_mcu_AC_refine;
}
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* Make sure requested tables are present, and compute derived tables.
* We may build same derived table more than once, but it's not expensive.
*/
if (is_DC_band) {
if (cinfo->Ah == 0) { /* DC refinement needs no table */
tbl = compptr->dc_tbl_no;
jpeg_make_d_derived_tbl(cinfo, TRUE, tbl,
& entropy->derived_tbls[tbl]);
}
} else {
tbl = compptr->ac_tbl_no;
jpeg_make_d_derived_tbl(cinfo, FALSE, tbl,
& entropy->derived_tbls[tbl]);
/* remember the single active table */
entropy->ac_derived_tbl = entropy->derived_tbls[tbl];
}
/* Initialize DC predictions to 0 */
entropy->saved.last_dc_val[ci] = 0;
}
/* Initialize bitread state variables */
entropy->bitstate.bits_left = 0;
entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
entropy->pub.insufficient_data = FALSE;
/* Initialize private state variables */
entropy->saved.EOBRUN = 0;
/* Initialize restart counter */
entropy->restarts_to_go = cinfo->restart_interval;
}
/*
* Figure F.12: extend sign bit.
* On some machines, a shift and add will be faster than a table lookup.
*/
#ifdef AVOID_TABLES
#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
#else
#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
static const int extend_test[16] = /* entry n is 2**(n-1) */
{ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
{ 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
#endif /* AVOID_TABLES */
/*
* Check for a restart marker & resynchronize decoder.
* Returns FALSE if must suspend.
*/
LOCAL(boolean)
process_restart (j_decompress_ptr cinfo)
{
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
int ci;
/* Throw away any unused bits remaining in bit buffer; */
/* include any full bytes in next_marker's count of discarded bytes */
cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
entropy->bitstate.bits_left = 0;
/* Advance past the RSTn marker */
if (! (*cinfo->marker->read_restart_marker) (cinfo))
return FALSE;
/* Re-initialize DC predictions to 0 */
for (ci = 0; ci < cinfo->comps_in_scan; ci++)
entropy->saved.last_dc_val[ci] = 0;
/* Re-init EOB run count, too */
entropy->saved.EOBRUN = 0;
/* Reset restart counter */
entropy->restarts_to_go = cinfo->restart_interval;
/* Reset out-of-data flag, unless read_restart_marker left us smack up
* against a marker. In that case we will end up treating the next data
* segment as empty, and we can avoid producing bogus output pixels by
* leaving the flag set.
*/
if (cinfo->unread_marker == 0)
entropy->pub.insufficient_data = FALSE;
return TRUE;
}
/*
* Huffman MCU decoding.
* Each of these routines decodes and returns one MCU's worth of
* Huffman-compressed coefficients.
* The coefficients are reordered from zigzag order into natural array order,
* but are not dequantized.
*
* The i'th block of the MCU is stored into the block pointed to by
* MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER.
*
* We return FALSE if data source requested suspension. In that case no
* changes have been made to permanent state. (Exception: some output
* coefficients may already have been assigned. This is harmless for
* spectral selection, since we'll just re-assign them on the next call.
* Successive approximation AC refinement has to be more careful, however.)
*/
/*
* MCU decoding for DC initial scan (either spectral selection,
* or first pass of successive approximation).
*/
METHODDEF(boolean)
decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
int Al = cinfo->Al;
register int s, r;
int blkn, ci;
JBLOCKROW block;
BITREAD_STATE_VARS;
savable_state state;
d_derived_tbl * tbl;
jpeg_component_info * compptr;
/* Process restart marker if needed; may have to suspend */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
if (! process_restart(cinfo))
return FALSE;
}
/* If we've run out of data, just leave the MCU set to zeroes.
* This way, we return uniform gray for the remainder of the segment.
*/
if (! entropy->pub.insufficient_data) {
/* Load up working state */
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
ASSIGN_STATE(state, entropy->saved);
/* Outer loop handles each block in the MCU */
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
block = MCU_data[blkn];
ci = cinfo->MCU_membership[blkn];
compptr = cinfo->cur_comp_info[ci];
tbl = entropy->derived_tbls[compptr->dc_tbl_no];
/* Decode a single block's worth of coefficients */
/* Section F.2.2.1: decode the DC coefficient difference */
HUFF_DECODE(s, br_state, tbl, return FALSE, label1);
if (s) {
CHECK_BIT_BUFFER(br_state, s, return FALSE);
r = GET_BITS(s);
s = HUFF_EXTEND(r, s);
}
/* Convert DC difference to actual value, update last_dc_val */
s += state.last_dc_val[ci];
state.last_dc_val[ci] = s;
/* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */
(*block)[0] = (JCOEF) (s << Al);
}
/* Completed MCU, so update state */
BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
ASSIGN_STATE(entropy->saved, state);
}
/* Account for restart interval (no-op if not using restarts) */
entropy->restarts_to_go--;
return TRUE;
}
/*
* MCU decoding for AC initial scan (either spectral selection,
* or first pass of successive approximation).
*/
METHODDEF(boolean)
decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
int Se = cinfo->Se;
int Al = cinfo->Al;
register int s, k, r;
unsigned int EOBRUN;
JBLOCKROW block;
BITREAD_STATE_VARS;
d_derived_tbl * tbl;
/* Process restart marker if needed; may have to suspend */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
if (! process_restart(cinfo))
return FALSE;
}
/* If we've run out of data, just leave the MCU set to zeroes.
* This way, we return uniform gray for the remainder of the segment.
*/
if (! entropy->pub.insufficient_data) {
/* Load up working state.
* We can avoid loading/saving bitread state if in an EOB run.
*/
EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */
/* There is always only one block per MCU */
if (EOBRUN > 0) /* if it's a band of zeroes... */
EOBRUN--; /* ...process it now (we do nothing) */
else {
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
block = MCU_data[0];
tbl = entropy->ac_derived_tbl;
for (k = cinfo->Ss; k <= Se; k++) {
HUFF_DECODE(s, br_state, tbl, return FALSE, label2);
r = s >> 4;
s &= 15;
if (s) {
k += r;
CHECK_BIT_BUFFER(br_state, s, return FALSE);
r = GET_BITS(s);
s = HUFF_EXTEND(r, s);
/* Scale and output coefficient in natural (dezigzagged) order */
(*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al);
} else {
if (r == 15) { /* ZRL */
k += 15; /* skip 15 zeroes in band */
} else { /* EOBr, run length is 2^r + appended bits */
EOBRUN = 1 << r;
if (r) { /* EOBr, r > 0 */
CHECK_BIT_BUFFER(br_state, r, return FALSE);
r = GET_BITS(r);
EOBRUN += r;
}
EOBRUN--; /* this band is processed at this moment */
break; /* force end-of-band */
}
}
}
BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
}
/* Completed MCU, so update state */
entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */
}
/* Account for restart interval (no-op if not using restarts) */
entropy->restarts_to_go--;
return TRUE;
}
/*
* MCU decoding for DC successive approximation refinement scan.
* Note: we assume such scans can be multi-component, although the spec
* is not very clear on the point.
*/
METHODDEF(boolean)
decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
int blkn;
JBLOCKROW block;
BITREAD_STATE_VARS;
/* Process restart marker if needed; may have to suspend */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
if (! process_restart(cinfo))
return FALSE;
}
/* Not worth the cycles to check insufficient_data here,
* since we will not change the data anyway if we read zeroes.
*/
/* Load up working state */
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
/* Outer loop handles each block in the MCU */
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
block = MCU_data[blkn];
/* Encoded data is simply the next bit of the two's-complement DC value */
CHECK_BIT_BUFFER(br_state, 1, return FALSE);
if (GET_BITS(1))
(*block)[0] |= p1;
/* Note: since we use |=, repeating the assignment later is safe */
}
/* Completed MCU, so update state */
BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
/* Account for restart interval (no-op if not using restarts) */
entropy->restarts_to_go--;
return TRUE;
}
/*
* MCU decoding for AC successive approximation refinement scan.
*/
METHODDEF(boolean)
decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
int Se = cinfo->Se;
int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */
register int s, k, r;
unsigned int EOBRUN;
JBLOCKROW block;
JCOEFPTR thiscoef;
BITREAD_STATE_VARS;
d_derived_tbl * tbl;
int num_newnz;
int newnz_pos[DCTSIZE2];
/* Process restart marker if needed; may have to suspend */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
if (! process_restart(cinfo))
return FALSE;
}
/* If we've run out of data, don't modify the MCU.
*/
if (! entropy->pub.insufficient_data) {
/* Load up working state */
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */
/* There is always only one block per MCU */
block = MCU_data[0];
tbl = entropy->ac_derived_tbl;
/* If we are forced to suspend, we must undo the assignments to any newly
* nonzero coefficients in the block, because otherwise we'd get confused
* next time about which coefficients were already nonzero.
* But we need not undo addition of bits to already-nonzero coefficients;
* instead, we can test the current bit to see if we already did it.
*/
num_newnz = 0;
/* initialize coefficient loop counter to start of band */
k = cinfo->Ss;
if (EOBRUN == 0) {
for (; k <= Se; k++) {
HUFF_DECODE(s, br_state, tbl, goto undoit, label3);
r = s >> 4;
s &= 15;
if (s) {
if (s != 1) /* size of new coef should always be 1 */
WARNMS(cinfo, JWRN_HUFF_BAD_CODE);
CHECK_BIT_BUFFER(br_state, 1, goto undoit);
if (GET_BITS(1))
s = p1; /* newly nonzero coef is positive */
else
s = m1; /* newly nonzero coef is negative */
} else {
if (r != 15) {
EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */
if (r) {
CHECK_BIT_BUFFER(br_state, r, goto undoit);
r = GET_BITS(r);
EOBRUN += r;
}
break; /* rest of block is handled by EOB logic */
}
/* note s = 0 for processing ZRL */
}
/* Advance over already-nonzero coefs and r still-zero coefs,
* appending correction bits to the nonzeroes. A correction bit is 1
* if the absolute value of the coefficient must be increased.
*/
do {
thiscoef = *block + jpeg_natural_order[k];
if (*thiscoef != 0) {
CHECK_BIT_BUFFER(br_state, 1, goto undoit);
if (GET_BITS(1)) {
if ((*thiscoef & p1) == 0) { /* do nothing if already set it */
if (*thiscoef >= 0)
*thiscoef += p1;
else
*thiscoef += m1;
}
}
} else {
if (--r < 0)
break; /* reached target zero coefficient */
}
k++;
} while (k <= Se);
if (s) {
int pos = jpeg_natural_order[k];
/* Output newly nonzero coefficient */
(*block)[pos] = (JCOEF) s;
/* Remember its position in case we have to suspend */
newnz_pos[num_newnz++] = pos;
}
}
}
if (EOBRUN > 0) {
/* Scan any remaining coefficient positions after the end-of-band
* (the last newly nonzero coefficient, if any). Append a correction
* bit to each already-nonzero coefficient. A correction bit is 1
* if the absolute value of the coefficient must be increased.
*/
for (; k <= Se; k++) {
thiscoef = *block + jpeg_natural_order[k];
if (*thiscoef != 0) {
CHECK_BIT_BUFFER(br_state, 1, goto undoit);
if (GET_BITS(1)) {
if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */
if (*thiscoef >= 0)
*thiscoef += p1;
else
*thiscoef += m1;
}
}
}
}
/* Count one block completed in EOB run */
EOBRUN--;
}
/* Completed MCU, so update state */
BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */
}
/* Account for restart interval (no-op if not using restarts) */
entropy->restarts_to_go--;
return TRUE;
undoit:
/* Re-zero any output coefficients that we made newly nonzero */
while (num_newnz > 0)
(*block)[newnz_pos[--num_newnz]] = 0;
return FALSE;
}
/*
* Module initialization routine for progressive Huffman entropy decoding.
*/
GLOBAL(void)
jinit_phuff_decoder (j_decompress_ptr cinfo)
{
phuff_entropy_ptr entropy;
int *coef_bit_ptr;
int ci, i;
entropy = (phuff_entropy_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(phuff_entropy_decoder));
cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
entropy->pub.start_pass = start_pass_phuff_decoder;
/* Mark derived tables unallocated */
for (i = 0; i < NUM_HUFF_TBLS; i++) {
entropy->derived_tbls[i] = NULL;
}
/* Create progression status table */
cinfo->coef_bits = (int (*)[DCTSIZE2])
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
cinfo->num_components*DCTSIZE2*SIZEOF(int));
coef_bit_ptr = & cinfo->coef_bits[0][0];
for (ci = 0; ci < cinfo->num_components; ci++)
for (i = 0; i < DCTSIZE2; i++)
*coef_bit_ptr++ = -1;
}
#endif /* D_PROGRESSIVE_SUPPORTED */

1056
jdpipe.c

File diff suppressed because it is too large Load Diff

290
jdpostct.c Normal file
View File

@@ -0,0 +1,290 @@
/*
* jdpostct.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the decompression postprocessing controller.
* This controller manages the upsampling, color conversion, and color
* quantization/reduction steps; specifically, it controls the buffering
* between upsample/color conversion and color quantization/reduction.
*
* If no color quantization/reduction is required, then this module has no
* work to do, and it just hands off to the upsample/color conversion code.
* An integrated upsample/convert/quantize process would replace this module
* entirely.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Private buffer controller object */
typedef struct {
struct jpeg_d_post_controller pub; /* public fields */
/* Color quantization source buffer: this holds output data from
* the upsample/color conversion step to be passed to the quantizer.
* For two-pass color quantization, we need a full-image buffer;
* for one-pass operation, a strip buffer is sufficient.
*/
jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */
JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */
JDIMENSION strip_height; /* buffer size in rows */
/* for two-pass mode only: */
JDIMENSION starting_row; /* row # of first row in current strip */
JDIMENSION next_row; /* index of next row to fill/empty in strip */
} my_post_controller;
typedef my_post_controller * my_post_ptr;
/* Forward declarations */
METHODDEF(void) post_process_1pass
JPP((j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail));
#ifdef QUANT_2PASS_SUPPORTED
METHODDEF(void) post_process_prepass
JPP((j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail));
METHODDEF(void) post_process_2pass
JPP((j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail));
#endif
/*
* Initialize for a processing pass.
*/
METHODDEF(void)
start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
{
my_post_ptr post = (my_post_ptr) cinfo->post;
switch (pass_mode) {
case JBUF_PASS_THRU:
if (cinfo->quantize_colors) {
/* Single-pass processing with color quantization. */
post->pub.post_process_data = post_process_1pass;
/* We could be doing buffered-image output before starting a 2-pass
* color quantization; in that case, jinit_d_post_controller did not
* allocate a strip buffer. Use the virtual-array buffer as workspace.
*/
if (post->buffer == NULL) {
post->buffer = (*cinfo->mem->access_virt_sarray)
((j_common_ptr) cinfo, post->whole_image,
(JDIMENSION) 0, post->strip_height, TRUE);
}
} else {
/* For single-pass processing without color quantization,
* I have no work to do; just call the upsampler directly.
*/
post->pub.post_process_data = cinfo->upsample->upsample;
}
break;
#ifdef QUANT_2PASS_SUPPORTED
case JBUF_SAVE_AND_PASS:
/* First pass of 2-pass quantization */
if (post->whole_image == NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
post->pub.post_process_data = post_process_prepass;
break;
case JBUF_CRANK_DEST:
/* Second pass of 2-pass quantization */
if (post->whole_image == NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
post->pub.post_process_data = post_process_2pass;
break;
#endif /* QUANT_2PASS_SUPPORTED */
default:
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
break;
}
post->starting_row = post->next_row = 0;
}
/*
* Process some data in the one-pass (strip buffer) case.
* This is used for color precision reduction as well as one-pass quantization.
*/
METHODDEF(void)
post_process_1pass (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
{
my_post_ptr post = (my_post_ptr) cinfo->post;
JDIMENSION num_rows, max_rows;
/* Fill the buffer, but not more than what we can dump out in one go. */
/* Note we rely on the upsampler to detect bottom of image. */
max_rows = out_rows_avail - *out_row_ctr;
if (max_rows > post->strip_height)
max_rows = post->strip_height;
num_rows = 0;
(*cinfo->upsample->upsample) (cinfo,
input_buf, in_row_group_ctr, in_row_groups_avail,
post->buffer, &num_rows, max_rows);
/* Quantize and emit data. */
(*cinfo->cquantize->color_quantize) (cinfo,
post->buffer, output_buf + *out_row_ctr, (int) num_rows);
*out_row_ctr += num_rows;
}
#ifdef QUANT_2PASS_SUPPORTED
/*
* Process some data in the first pass of 2-pass quantization.
*/
METHODDEF(void)
post_process_prepass (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
{
my_post_ptr post = (my_post_ptr) cinfo->post;
JDIMENSION old_next_row, num_rows;
/* Reposition virtual buffer if at start of strip. */
if (post->next_row == 0) {
post->buffer = (*cinfo->mem->access_virt_sarray)
((j_common_ptr) cinfo, post->whole_image,
post->starting_row, post->strip_height, TRUE);
}
/* Upsample some data (up to a strip height's worth). */
old_next_row = post->next_row;
(*cinfo->upsample->upsample) (cinfo,
input_buf, in_row_group_ctr, in_row_groups_avail,
post->buffer, &post->next_row, post->strip_height);
/* Allow quantizer to scan new data. No data is emitted, */
/* but we advance out_row_ctr so outer loop can tell when we're done. */
if (post->next_row > old_next_row) {
num_rows = post->next_row - old_next_row;
(*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row,
(JSAMPARRAY) NULL, (int) num_rows);
*out_row_ctr += num_rows;
}
/* Advance if we filled the strip. */
if (post->next_row >= post->strip_height) {
post->starting_row += post->strip_height;
post->next_row = 0;
}
}
/*
* Process some data in the second pass of 2-pass quantization.
*/
METHODDEF(void)
post_process_2pass (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
{
my_post_ptr post = (my_post_ptr) cinfo->post;
JDIMENSION num_rows, max_rows;
/* Reposition virtual buffer if at start of strip. */
if (post->next_row == 0) {
post->buffer = (*cinfo->mem->access_virt_sarray)
((j_common_ptr) cinfo, post->whole_image,
post->starting_row, post->strip_height, FALSE);
}
/* Determine number of rows to emit. */
num_rows = post->strip_height - post->next_row; /* available in strip */
max_rows = out_rows_avail - *out_row_ctr; /* available in output area */
if (num_rows > max_rows)
num_rows = max_rows;
/* We have to check bottom of image here, can't depend on upsampler. */
max_rows = cinfo->output_height - post->starting_row;
if (num_rows > max_rows)
num_rows = max_rows;
/* Quantize and emit data. */
(*cinfo->cquantize->color_quantize) (cinfo,
post->buffer + post->next_row, output_buf + *out_row_ctr,
(int) num_rows);
*out_row_ctr += num_rows;
/* Advance if we filled the strip. */
post->next_row += num_rows;
if (post->next_row >= post->strip_height) {
post->starting_row += post->strip_height;
post->next_row = 0;
}
}
#endif /* QUANT_2PASS_SUPPORTED */
/*
* Initialize postprocessing controller.
*/
GLOBAL(void)
jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
{
my_post_ptr post;
post = (my_post_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_post_controller));
cinfo->post = (struct jpeg_d_post_controller *) post;
post->pub.start_pass = start_pass_dpost;
post->whole_image = NULL; /* flag for no virtual arrays */
post->buffer = NULL; /* flag for no strip buffer */
/* Create the quantization buffer, if needed */
if (cinfo->quantize_colors) {
/* The buffer strip height is max_v_samp_factor, which is typically
* an efficient number of rows for upsampling to return.
* (In the presence of output rescaling, we might want to be smarter?)
*/
post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor;
if (need_full_buffer) {
/* Two-pass color quantization: need full-image storage. */
/* We round up the number of rows to a multiple of the strip height. */
#ifdef QUANT_2PASS_SUPPORTED
post->whole_image = (*cinfo->mem->request_virt_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
cinfo->output_width * cinfo->out_color_components,
(JDIMENSION) jround_up((long) cinfo->output_height,
(long) post->strip_height),
post->strip_height);
#else
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
#endif /* QUANT_2PASS_SUPPORTED */
} else {
/* One-pass color quantization: just make a strip buffer. */
post->buffer = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
cinfo->output_width * cinfo->out_color_components,
post->strip_height);
}
}
}

View File

@@ -1,37 +1,183 @@
/*
* jdsample.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1996, Thomas G. Lane.
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains upsampling routines.
* These routines are invoked via the upsample and
* upsample_init/term methods.
*
* Upsampling input data is counted in "row groups". A row group
* is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
* sample rows of each component. Upsampling will normally produce
* max_v_samp_factor pixel rows from each row group (but this could vary
* if the upsampler is applying a scale factor of its own).
*
* An excellent reference for image resampling is
* Digital Image Warping, George Wolberg, 1990.
* Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jsimd.h"
/* Pointer to routine to upsample a single component */
typedef JMETHOD(void, upsample1_ptr,
(j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
/* Private subobject */
typedef struct {
struct jpeg_upsampler pub; /* public fields */
/* Color conversion buffer. When using separate upsampling and color
* conversion steps, this buffer holds one upsampled row group until it
* has been color converted and output.
* Note: we do not allocate any storage for component(s) which are full-size,
* ie do not need rescaling. The corresponding entry of color_buf[] is
* simply set to point to the input data array, thereby avoiding copying.
*/
JSAMPARRAY color_buf[MAX_COMPONENTS];
/* Per-component upsampling method pointers */
upsample1_ptr methods[MAX_COMPONENTS];
int next_row_out; /* counts rows emitted from color_buf */
JDIMENSION rows_to_go; /* counts rows remaining in image */
/* Height of an input row group for each component. */
int rowgroup_height[MAX_COMPONENTS];
/* These arrays save pixel expansion factors so that int_expand need not
* recompute them each time. They are unused for other upsampling methods.
*/
UINT8 h_expand[MAX_COMPONENTS];
UINT8 v_expand[MAX_COMPONENTS];
} my_upsampler;
typedef my_upsampler * my_upsample_ptr;
/*
* Initialize for upsampling a scan.
* Initialize for an upsampling pass.
*/
METHODDEF void
upsample_init (decompress_info_ptr cinfo)
METHODDEF(void)
start_pass_upsample (j_decompress_ptr cinfo)
{
/* no work for now */
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
/* Mark the conversion buffer empty */
upsample->next_row_out = cinfo->max_v_samp_factor;
/* Initialize total-height counter for detecting bottom of image */
upsample->rows_to_go = cinfo->output_height;
}
/*
* Upsample pixel values of a single component.
* This version handles any integral sampling ratios.
* Control routine to do upsampling (and color conversion).
*
* In this version we upsample each component independently.
* We upsample one row group into the conversion buffer, then apply
* color conversion a row at a time.
*/
METHODDEF(void)
sep_upsample (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
{
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
int ci;
jpeg_component_info * compptr;
JDIMENSION num_rows;
/* Fill the conversion buffer, if it's empty */
if (upsample->next_row_out >= cinfo->max_v_samp_factor) {
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Invoke per-component upsample method. Notice we pass a POINTER
* to color_buf[ci], so that fullsize_upsample can change it.
*/
(*upsample->methods[ci]) (cinfo, compptr,
input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]),
upsample->color_buf + ci);
}
upsample->next_row_out = 0;
}
/* Color-convert and emit rows */
/* How many we have in the buffer: */
num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out);
/* Not more than the distance to the end of the image. Need this test
* in case the image height is not a multiple of max_v_samp_factor:
*/
if (num_rows > upsample->rows_to_go)
num_rows = upsample->rows_to_go;
/* And not more than what the client can accept: */
out_rows_avail -= *out_row_ctr;
if (num_rows > out_rows_avail)
num_rows = out_rows_avail;
(*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf,
(JDIMENSION) upsample->next_row_out,
output_buf + *out_row_ctr,
(int) num_rows);
/* Adjust counts */
*out_row_ctr += num_rows;
upsample->rows_to_go -= num_rows;
upsample->next_row_out += num_rows;
/* When the buffer is emptied, declare this input row group consumed */
if (upsample->next_row_out >= cinfo->max_v_samp_factor)
(*in_row_group_ctr)++;
}
/*
* These are the routines invoked by sep_upsample to upsample pixel values
* of a single component. One row group is processed per call.
*/
/*
* For full-size components, we just make color_buf[ci] point at the
* input buffer, and thus avoid copying any data. Note that this is
* safe only because sep_upsample doesn't declare the input row group
* "consumed" until we are done color converting and emitting it.
*/
METHODDEF(void)
fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
{
*output_data_ptr = input_data;
}
/*
* This is a no-op version used for "uninteresting" components.
* These components will not be referenced by color conversion.
*/
METHODDEF(void)
noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
{
*output_data_ptr = NULL; /* safety check */
}
/*
* This version handles any integral sampling ratios.
* This is not used for typical JPEG files, so it need not be fast.
* Nor, for that matter, is it particularly accurate: the algorithm is
* simple replication of the input pixel onto the corresponding output
@@ -41,82 +187,132 @@ upsample_init (decompress_info_ptr cinfo)
* you would be well advised to improve this code.
*/
METHODDEF void
int_upsample (decompress_info_ptr cinfo, int which_component,
long input_cols, int input_rows,
long output_cols, int output_rows,
JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
JSAMPARRAY output_data)
METHODDEF(void)
int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
{
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
register JSAMPLE invalue;
register short h_expand, h;
short v_expand, v;
register int h;
JSAMPROW outend;
int h_expand, v_expand;
int inrow, outrow;
register long incol;
#ifdef DEBUG /* for debugging pipeline controller */
if (input_rows != compptr->v_samp_factor ||
output_rows != cinfo->max_v_samp_factor ||
(input_cols % compptr->h_samp_factor) != 0 ||
(output_cols % cinfo->max_h_samp_factor) != 0 ||
output_cols*compptr->h_samp_factor != input_cols*cinfo->max_h_samp_factor)
ERREXIT(cinfo->emethods, "Bogus upsample parameters");
#endif
h_expand = upsample->h_expand[compptr->component_index];
v_expand = upsample->v_expand[compptr->component_index];
h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
outrow = 0;
for (inrow = 0; inrow < input_rows; inrow++) {
for (v = 0; v < v_expand; v++) {
inrow = outrow = 0;
while (outrow < cinfo->max_v_samp_factor) {
/* Generate one output row with proper horizontal expansion */
inptr = input_data[inrow];
outptr = output_data[outrow++];
for (incol = 0; incol < input_cols; incol++) {
invalue = GETJSAMPLE(*inptr++);
for (h = 0; h < h_expand; h++) {
outptr = output_data[outrow];
outend = outptr + cinfo->output_width;
while (outptr < outend) {
invalue = *inptr++; /* don't need GETJSAMPLE() here */
for (h = h_expand; h > 0; h--) {
*outptr++ = invalue;
}
}
/* Generate any additional output rows by duplicating the first one */
if (v_expand > 1) {
jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
v_expand-1, cinfo->output_width);
}
inrow++;
outrow += v_expand;
}
}
/*
* Fast processing for the common case of 2:1 horizontal and 1:1 vertical.
* It's still a box filter.
*/
METHODDEF(void)
h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
register JSAMPLE invalue;
JSAMPROW outend;
int inrow;
for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
inptr = input_data[inrow];
outptr = output_data[inrow];
outend = outptr + cinfo->output_width;
while (outptr < outend) {
invalue = *inptr++; /* don't need GETJSAMPLE() here */
*outptr++ = invalue;
*outptr++ = invalue;
}
}
}
/*
* Upsample pixel values of a single component.
* This version handles the common case of 2:1 horizontal and 1:1 vertical.
* Fast processing for the common case of 2:1 horizontal and 2:1 vertical.
* It's still a box filter.
*/
METHODDEF(void)
h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
register JSAMPLE invalue;
JSAMPROW outend;
int inrow, outrow;
inrow = outrow = 0;
while (outrow < cinfo->max_v_samp_factor) {
inptr = input_data[inrow];
outptr = output_data[outrow];
outend = outptr + cinfo->output_width;
while (outptr < outend) {
invalue = *inptr++; /* don't need GETJSAMPLE() here */
*outptr++ = invalue;
*outptr++ = invalue;
}
jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
1, cinfo->output_width);
inrow++;
outrow += 2;
}
}
/*
* Fancy processing for the common case of 2:1 horizontal and 1:1 vertical.
*
* The upsampling algorithm is linear interpolation between pixel centers,
* also known as a "triangle filter". This is a good compromise between
* speed and visual quality. The centers of the output pixels are 1/4 and 3/4
* of the way between input pixel centers.
*
* A note about the "bias" calculations: when rounding fractional values to
* integer, we do not want to always round 0.5 up to the next integer.
* If we did that, we'd introduce a noticeable bias towards larger values.
* Instead, this code is arranged so that 0.5 will be rounded up or down at
* alternate pixel locations (a simple ordered dither pattern).
*/
METHODDEF void
h2v1_upsample (decompress_info_ptr cinfo, int which_component,
long input_cols, int input_rows,
long output_cols, int output_rows,
JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
JSAMPARRAY output_data)
METHODDEF(void)
h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
register int invalue;
register JDIMENSION colctr;
int inrow;
register long colctr;
#ifdef DEBUG /* for debugging pipeline controller */
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
if (input_rows != compptr->v_samp_factor ||
output_rows != cinfo->max_v_samp_factor ||
(input_cols % compptr->h_samp_factor) != 0 ||
(output_cols % cinfo->max_h_samp_factor) != 0 ||
output_cols*compptr->h_samp_factor != input_cols*cinfo->max_h_samp_factor)
ERREXIT(cinfo->emethods, "Bogus upsample parameters");
#endif
for (inrow = 0; inrow < input_rows; inrow++) {
for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
inptr = input_data[inrow];
outptr = output_data[inrow];
/* Special case for first column */
@@ -124,165 +320,175 @@ h2v1_upsample (decompress_info_ptr cinfo, int which_component,
*outptr++ = (JSAMPLE) invalue;
*outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2);
for (colctr = input_cols - 2; colctr > 0; colctr--) {
for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
/* General case: 3/4 * nearer pixel + 1/4 * further pixel */
invalue = GETJSAMPLE(*inptr++) * 3;
*outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 2) >> 2);
*outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2);
*outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
}
/* Special case for last column */
invalue = GETJSAMPLE(*inptr);
*outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 2) >> 2);
*outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
*outptr++ = (JSAMPLE) invalue;
}
}
/*
* Upsample pixel values of a single component.
* This version handles the common case of 2:1 horizontal and 2:1 vertical.
* Fancy processing for the common case of 2:1 horizontal and 2:1 vertical.
* Again a triangle filter; see comments for h2v1 case, above.
*
* The upsampling algorithm is linear interpolation between pixel centers,
* also known as a "triangle filter". This is a good compromise between
* speed and visual quality. The centers of the output pixels are 1/4 and 3/4
* of the way between input pixel centers.
* It is OK for us to reference the adjacent input rows because we demanded
* context from the main buffer controller (see initialization code).
*/
METHODDEF void
h2v2_upsample (decompress_info_ptr cinfo, int which_component,
long input_cols, int input_rows,
long output_cols, int output_rows,
JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
JSAMPARRAY output_data)
METHODDEF(void)
h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr0, inptr1, outptr;
#ifdef EIGHT_BIT_SAMPLES
#if BITS_IN_JSAMPLE == 8
register int thiscolsum, lastcolsum, nextcolsum;
#else
register INT32 thiscolsum, lastcolsum, nextcolsum;
#endif
register JDIMENSION colctr;
int inrow, outrow, v;
register long colctr;
#ifdef DEBUG /* for debugging pipeline controller */
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
if (input_rows != compptr->v_samp_factor ||
output_rows != cinfo->max_v_samp_factor ||
(input_cols % compptr->h_samp_factor) != 0 ||
(output_cols % cinfo->max_h_samp_factor) != 0 ||
output_cols*compptr->h_samp_factor != input_cols*cinfo->max_h_samp_factor)
ERREXIT(cinfo->emethods, "Bogus upsample parameters");
#endif
outrow = 0;
for (inrow = 0; inrow < input_rows; inrow++) {
inrow = outrow = 0;
while (outrow < cinfo->max_v_samp_factor) {
for (v = 0; v < 2; v++) {
/* inptr0 points to nearest input row, inptr1 points to next nearest */
inptr0 = input_data[inrow];
if (v == 0) { /* next nearest is row above */
if (inrow == 0)
inptr1 = above[input_rows-1];
else
if (v == 0) /* next nearest is row above */
inptr1 = input_data[inrow-1];
} else { /* next nearest is row below */
if (inrow == input_rows-1)
inptr1 = below[0];
else
else /* next nearest is row below */
inptr1 = input_data[inrow+1];
}
outptr = output_data[outrow++];
/* Special case for first column */
thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
*outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4);
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 8) >> 4);
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
lastcolsum = thiscolsum; thiscolsum = nextcolsum;
for (colctr = input_cols - 2; colctr > 0; colctr--) {
for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
/* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */
/* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 8) >> 4);
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
lastcolsum = thiscolsum; thiscolsum = nextcolsum;
}
/* Special case for last column */
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
*outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4);
*outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4);
}
inrow++;
}
}
/*
* Upsample pixel values of a single component.
* This version handles the special case of a full-size component.
* Module initialization routine for upsampling.
*/
METHODDEF void
fullsize_upsample (decompress_info_ptr cinfo, int which_component,
long input_cols, int input_rows,
long output_cols, int output_rows,
JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
JSAMPARRAY output_data)
GLOBAL(void)
jinit_upsampler (j_decompress_ptr cinfo)
{
#ifdef DEBUG /* for debugging pipeline controller */
if (input_cols != output_cols || input_rows != output_rows)
ERREXIT(cinfo->emethods, "Pipeline controller messed up");
#endif
jcopy_sample_rows(input_data, 0, output_data, 0, output_rows, output_cols);
}
/*
* Clean up after a scan.
*/
METHODDEF void
upsample_term (decompress_info_ptr cinfo)
{
/* no work for now */
}
/*
* The method selection routine for upsampling.
* Note that we must select a routine for each component.
*/
GLOBAL void
jselupsample (decompress_info_ptr cinfo)
{
short ci;
my_upsample_ptr upsample;
int ci;
jpeg_component_info * compptr;
boolean need_buffer, do_fancy;
int h_in_group, v_in_group, h_out_group, v_out_group;
if (cinfo->CCIR601_sampling)
ERREXIT(cinfo->emethods, "CCIR601 upsampling not implemented yet");
upsample = (my_upsample_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_upsampler));
cinfo->upsample = (struct jpeg_upsampler *) upsample;
upsample->pub.start_pass = start_pass_upsample;
upsample->pub.upsample = sep_upsample;
upsample->pub.need_context_rows = FALSE; /* until we find out differently */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
compptr->v_samp_factor == cinfo->max_v_samp_factor)
cinfo->methods->upsample[ci] = fullsize_upsample;
else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
compptr->v_samp_factor == cinfo->max_v_samp_factor)
cinfo->methods->upsample[ci] = h2v1_upsample;
else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor)
cinfo->methods->upsample[ci] = h2v2_upsample;
else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
(cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0)
cinfo->methods->upsample[ci] = int_upsample;
if (cinfo->CCIR601_sampling) /* this isn't supported */
ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
/* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1,
* so don't ask for it.
*/
do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1;
/* Verify we can handle the sampling factors, select per-component methods,
* and create storage as needed.
*/
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Compute size of an "input group" after IDCT scaling. This many samples
* are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
*/
h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) /
cinfo->min_DCT_scaled_size;
v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
cinfo->min_DCT_scaled_size;
h_out_group = cinfo->max_h_samp_factor;
v_out_group = cinfo->max_v_samp_factor;
upsample->rowgroup_height[ci] = v_in_group; /* save for use later */
need_buffer = TRUE;
if (! compptr->component_needed) {
/* Don't bother to upsample an uninteresting component. */
upsample->methods[ci] = noop_upsample;
need_buffer = FALSE;
} else if (h_in_group == h_out_group && v_in_group == v_out_group) {
/* Fullsize components can be processed without any work. */
upsample->methods[ci] = fullsize_upsample;
need_buffer = FALSE;
} else if (h_in_group * 2 == h_out_group &&
v_in_group == v_out_group) {
/* Special cases for 2h1v upsampling */
if (do_fancy && compptr->downsampled_width > 2) {
if (jsimd_can_h2v1_fancy_upsample())
upsample->methods[ci] = jsimd_h2v1_fancy_upsample;
else
ERREXIT(cinfo->emethods, "Fractional upsampling not implemented yet");
upsample->methods[ci] = h2v1_fancy_upsample;
} else {
if (jsimd_can_h2v1_upsample())
upsample->methods[ci] = jsimd_h2v1_upsample;
else
upsample->methods[ci] = h2v1_upsample;
}
} else if (h_in_group * 2 == h_out_group &&
v_in_group * 2 == v_out_group) {
/* Special cases for 2h2v upsampling */
if (do_fancy && compptr->downsampled_width > 2) {
if (jsimd_can_h2v2_fancy_upsample())
upsample->methods[ci] = jsimd_h2v2_fancy_upsample;
else
upsample->methods[ci] = h2v2_fancy_upsample;
upsample->pub.need_context_rows = TRUE;
} else {
if (jsimd_can_h2v2_upsample())
upsample->methods[ci] = jsimd_h2v2_upsample;
else
upsample->methods[ci] = h2v2_upsample;
}
} else if ((h_out_group % h_in_group) == 0 &&
(v_out_group % v_in_group) == 0) {
/* Generic integral-factors upsampling method */
upsample->methods[ci] = int_upsample;
upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group);
upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group);
} else
ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
if (need_buffer) {
upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) jround_up((long) cinfo->output_width,
(long) cinfo->max_h_samp_factor),
(JDIMENSION) cinfo->max_v_samp_factor);
}
}
cinfo->methods->upsample_init = upsample_init;
cinfo->methods->upsample_term = upsample_term;
}

143
jdtrans.c Normal file
View File

@@ -0,0 +1,143 @@
/*
* jdtrans.c
*
* Copyright (C) 1995-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains library routines for transcoding decompression,
* that is, reading raw DCT coefficient arrays from an input JPEG file.
* The routines in jdapimin.c will also be needed by a transcoder.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Forward declarations */
LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo));
/*
* Read the coefficient arrays from a JPEG file.
* jpeg_read_header must be completed before calling this.
*
* The entire image is read into a set of virtual coefficient-block arrays,
* one per component. The return value is a pointer to the array of
* virtual-array descriptors. These can be manipulated directly via the
* JPEG memory manager, or handed off to jpeg_write_coefficients().
* To release the memory occupied by the virtual arrays, call
* jpeg_finish_decompress() when done with the data.
*
* An alternative usage is to simply obtain access to the coefficient arrays
* during a buffered-image-mode decompression operation. This is allowed
* after any jpeg_finish_output() call. The arrays can be accessed until
* jpeg_finish_decompress() is called. (Note that any call to the library
* may reposition the arrays, so don't rely on access_virt_barray() results
* to stay valid across library calls.)
*
* Returns NULL if suspended. This case need be checked only if
* a suspending data source is used.
*/
GLOBAL(jvirt_barray_ptr *)
jpeg_read_coefficients (j_decompress_ptr cinfo)
{
if (cinfo->global_state == DSTATE_READY) {
/* First call: initialize active modules */
transdecode_master_selection(cinfo);
cinfo->global_state = DSTATE_RDCOEFS;
}
if (cinfo->global_state == DSTATE_RDCOEFS) {
/* Absorb whole file into the coef buffer */
for (;;) {
int retcode;
/* Call progress monitor hook if present */
if (cinfo->progress != NULL)
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
/* Absorb some more input */
retcode = (*cinfo->inputctl->consume_input) (cinfo);
if (retcode == JPEG_SUSPENDED)
return NULL;
if (retcode == JPEG_REACHED_EOI)
break;
/* Advance progress counter if appropriate */
if (cinfo->progress != NULL &&
(retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
/* startup underestimated number of scans; ratchet up one scan */
cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
}
}
}
/* Set state so that jpeg_finish_decompress does the right thing */
cinfo->global_state = DSTATE_STOPPING;
}
/* At this point we should be in state DSTATE_STOPPING if being used
* standalone, or in state DSTATE_BUFIMAGE if being invoked to get access
* to the coefficients during a full buffered-image-mode decompression.
*/
if ((cinfo->global_state == DSTATE_STOPPING ||
cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) {
return cinfo->coef->coef_arrays;
}
/* Oops, improper usage */
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
return NULL; /* keep compiler happy */
}
/*
* Master selection of decompression modules for transcoding.
* This substitutes for jdmaster.c's initialization of the full decompressor.
*/
LOCAL(void)
transdecode_master_selection (j_decompress_ptr cinfo)
{
/* This is effectively a buffered-image operation. */
cinfo->buffered_image = TRUE;
/* Entropy decoding: either Huffman or arithmetic coding. */
if (cinfo->arith_code) {
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
} else {
if (cinfo->progressive_mode) {
#ifdef D_PROGRESSIVE_SUPPORTED
jinit_phuff_decoder(cinfo);
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
} else
jinit_huff_decoder(cinfo);
}
/* Always get a full-image coefficient buffer. */
jinit_d_coef_controller(cinfo, TRUE);
/* We can now tell the memory manager to allocate virtual arrays. */
(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
/* Initialize input side of decompressor to consume first scan. */
(*cinfo->inputctl->start_input_pass) (cinfo);
/* Initialize progress monitoring. */
if (cinfo->progress != NULL) {
int nscans;
/* Estimate number of scans to set pass_limit. */
if (cinfo->progressive_mode) {
/* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
nscans = 2 + 3 * cinfo->num_components;
} else if (cinfo->inputctl->has_multiple_scans) {
/* For a nonprogressive multiscan file, estimate 1 scan per component. */
nscans = cinfo->num_components;
} else {
nscans = 1;
}
cinfo->progress->pass_counter = 0L;
cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
cinfo->progress->completed_passes = 0;
cinfo->progress->total_passes = 1;
}
}

259
jerror.c
View File

@@ -1,28 +1,31 @@
/*
* jerror.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1998, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains simple error-reporting and trace-message routines.
* These are suitable for Unix-like systems and others where writing to
* stderr is the right thing to do. If the JPEG software is integrated
* into a larger application, you may well need to replace these.
* stderr is the right thing to do. Many applications will want to replace
* some or all of these routines.
*
* The error_exit() routine should not return to its caller. Within a
* larger application, you might want to have it do a longjmp() to return
* control to the outer user interface routine. This should work since
* the portable JPEG code doesn't use setjmp/longjmp. You should make sure
* that free_all is called either within error_exit or after the return to
* the outer-level routine.
* If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile,
* you get a Windows-specific hack to display error messages in a dialog box.
* It ain't much, but it beats dropping error messages into the bit bucket,
* which is what happens to output to stderr under most Windows C compilers.
*
* These routines are used by both the compression and decompression code.
*/
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
#include "jinclude.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare exit() */
#include "jpeglib.h"
#include "jversion.h"
#include "jerror.h"
#ifdef USE_WINDOWS_MESSAGEBOX
#include <windows.h>
#endif
#ifndef EXIT_FAILURE /* define exit() codes if not provided */
@@ -30,52 +33,220 @@
#endif
static external_methods_ptr methods; /* saved for access to message_parm, free_all */
/*
* Create the message string table.
* We do this from the master message list in jerror.h by re-reading
* jerror.h with a suitable definition for macro JMESSAGE.
* The message table is made an external symbol just in case any applications
* want to refer to it directly.
*/
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define jpeg_std_message_table jMsgTable
#endif
#define JMESSAGE(code,string) string ,
const char * const jpeg_std_message_table[] = {
#include "jerror.h"
NULL
};
METHODDEF void
trace_message (const char *msgtext)
/*
* Error exit handler: must not return to caller.
*
* Applications may override this if they want to get control back after
* an error. Typically one would longjmp somewhere instead of exiting.
* The setjmp buffer can be made a private field within an expanded error
* handler object. Note that the info needed to generate an error message
* is stored in the error object, so you can generate the message now or
* later, at your convenience.
* You should make sure that the JPEG object is cleaned up (with jpeg_abort
* or jpeg_destroy) at some point.
*/
METHODDEF(void)
error_exit (j_common_ptr cinfo)
{
fprintf(stderr, msgtext,
methods->message_parm[0], methods->message_parm[1],
methods->message_parm[2], methods->message_parm[3],
methods->message_parm[4], methods->message_parm[5],
methods->message_parm[6], methods->message_parm[7]);
fprintf(stderr, "\n");
}
/* Always display the message */
(*cinfo->err->output_message) (cinfo);
/* Let the memory manager delete any temp files before we die */
jpeg_destroy(cinfo);
METHODDEF void
error_exit (const char *msgtext)
{
(*methods->trace_message) (msgtext);
(*methods->free_all) (); /* clean up memory allocation */
exit(EXIT_FAILURE);
}
/*
* The method selection routine for simple error handling.
* The system-dependent setup routine should call this routine
* to install the necessary method pointers in the supplied struct.
* Actual output of an error or trace message.
* Applications may override this method to send JPEG messages somewhere
* other than stderr.
*
* On Windows, printing to stderr is generally completely useless,
* so we provide optional code to produce an error-dialog popup.
* Most Windows applications will still prefer to override this routine,
* but if they don't, it'll do something at least marginally useful.
*
* NOTE: to use the library in an environment that doesn't support the
* C stdio library, you may have to delete the call to fprintf() entirely,
* not just not use this routine.
*/
GLOBAL void
jselerror (external_methods_ptr emethods)
METHODDEF(void)
output_message (j_common_ptr cinfo)
{
methods = emethods; /* save struct addr for later access */
char buffer[JMSG_LENGTH_MAX];
emethods->error_exit = error_exit;
emethods->trace_message = trace_message;
/* Create the message */
(*cinfo->err->format_message) (cinfo, buffer);
emethods->trace_level = 0; /* default = no tracing */
emethods->num_warnings = 0; /* no warnings emitted yet */
/* By default, the first corrupt-data warning will be displayed,
* but additional ones will appear only if trace level is at least 3.
* A corrupt data file could generate many warnings, so it's a good idea
* to suppress additional messages except at high tracing levels.
*/
emethods->first_warning_level = 0;
emethods->more_warning_level = 3;
#ifdef USE_WINDOWS_MESSAGEBOX
/* Display it in a message dialog box */
MessageBox(GetActiveWindow(), buffer, "JPEG Library Error",
MB_OK | MB_ICONERROR);
#else
/* Send it to stderr, adding a newline */
fprintf(stderr, "%s\n", buffer);
#endif
}
/*
* Decide whether to emit a trace or warning message.
* msg_level is one of:
* -1: recoverable corrupt-data warning, may want to abort.
* 0: important advisory messages (always display to user).
* 1: first level of tracing detail.
* 2,3,...: successively more detailed tracing messages.
* An application might override this method if it wanted to abort on warnings
* or change the policy about which messages to display.
*/
METHODDEF(void)
emit_message (j_common_ptr cinfo, int msg_level)
{
struct jpeg_error_mgr * err = cinfo->err;
if (msg_level < 0) {
/* It's a warning message. Since corrupt files may generate many warnings,
* the policy implemented here is to show only the first warning,
* unless trace_level >= 3.
*/
if (err->num_warnings == 0 || err->trace_level >= 3)
(*err->output_message) (cinfo);
/* Always count warnings in num_warnings. */
err->num_warnings++;
} else {
/* It's a trace message. Show it if trace_level >= msg_level. */
if (err->trace_level >= msg_level)
(*err->output_message) (cinfo);
}
}
/*
* Format a message string for the most recent JPEG error or message.
* The message is stored into buffer, which should be at least JMSG_LENGTH_MAX
* characters. Note that no '\n' character is added to the string.
* Few applications should need to override this method.
*/
METHODDEF(void)
format_message (j_common_ptr cinfo, char * buffer)
{
struct jpeg_error_mgr * err = cinfo->err;
int msg_code = err->msg_code;
const char * msgtext = NULL;
const char * msgptr;
char ch;
boolean isstring;
/* Look up message string in proper table */
if (msg_code > 0 && msg_code <= err->last_jpeg_message) {
msgtext = err->jpeg_message_table[msg_code];
} else if (err->addon_message_table != NULL &&
msg_code >= err->first_addon_message &&
msg_code <= err->last_addon_message) {
msgtext = err->addon_message_table[msg_code - err->first_addon_message];
}
/* Defend against bogus message number */
if (msgtext == NULL) {
err->msg_parm.i[0] = msg_code;
msgtext = err->jpeg_message_table[0];
}
/* Check for string parameter, as indicated by %s in the message text */
isstring = FALSE;
msgptr = msgtext;
while ((ch = *msgptr++) != '\0') {
if (ch == '%') {
if (*msgptr == 's') isstring = TRUE;
break;
}
}
/* Format the message into the passed buffer */
if (isstring)
sprintf(buffer, msgtext, err->msg_parm.s);
else
sprintf(buffer, msgtext,
err->msg_parm.i[0], err->msg_parm.i[1],
err->msg_parm.i[2], err->msg_parm.i[3],
err->msg_parm.i[4], err->msg_parm.i[5],
err->msg_parm.i[6], err->msg_parm.i[7]);
}
/*
* Reset error state variables at start of a new image.
* This is called during compression startup to reset trace/error
* processing to default state, without losing any application-specific
* method pointers. An application might possibly want to override
* this method if it has additional error processing state.
*/
METHODDEF(void)
reset_error_mgr (j_common_ptr cinfo)
{
cinfo->err->num_warnings = 0;
/* trace_level is not reset since it is an application-supplied parameter */
cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */
}
/*
* Fill in the standard error-handling methods in a jpeg_error_mgr object.
* Typical call is:
* struct jpeg_compress_struct cinfo;
* struct jpeg_error_mgr err;
*
* cinfo.err = jpeg_std_error(&err);
* after which the application may override some of the methods.
*/
GLOBAL(struct jpeg_error_mgr *)
jpeg_std_error (struct jpeg_error_mgr * err)
{
err->error_exit = error_exit;
err->emit_message = emit_message;
err->output_message = output_message;
err->format_message = format_message;
err->reset_error_mgr = reset_error_mgr;
err->trace_level = 0; /* default = no tracing */
err->num_warnings = 0; /* no warnings emitted yet */
err->msg_code = 0; /* may be useful as a flag for "no error" */
/* Initialize message table pointers */
err->jpeg_message_table = jpeg_std_message_table;
err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1;
err->addon_message_table = NULL;
err->first_addon_message = 0; /* for safety */
err->last_addon_message = 0;
return err;
}

291
jerror.h Normal file
View File

@@ -0,0 +1,291 @@
/*
* jerror.h
*
* Copyright (C) 1994-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file defines the error and message codes for the JPEG library.
* Edit this file to add new codes, or to translate the message strings to
* some other language.
* A set of error-reporting macros are defined too. Some applications using
* the JPEG library may wish to include this file to get the error codes
* and/or the macros.
*/
/*
* To define the enum list of message codes, include this file without
* defining macro JMESSAGE. To create a message string table, include it
* again with a suitable JMESSAGE definition (see jerror.c for an example).
*/
#ifndef JMESSAGE
#ifndef JERROR_H
/* First time through, define the enum list */
#define JMAKE_ENUM_LIST
#else
/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
#define JMESSAGE(code,string)
#endif /* JERROR_H */
#endif /* JMESSAGE */
#ifdef JMAKE_ENUM_LIST
typedef enum {
#define JMESSAGE(code,string) code ,
#endif /* JMAKE_ENUM_LIST */
JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
/* For maintenance convenience, list is alphabetical by message code name */
JMESSAGE(JERR_ARITH_NOTIMPL,
"Sorry, there are legal restrictions on arithmetic coding")
JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range")
JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition")
JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
JMESSAGE(JERR_BAD_LIB_VERSION,
"Wrong JPEG library version: library is %d, caller expects %d")
JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
JMESSAGE(JERR_BAD_PROGRESSION,
"Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d")
JMESSAGE(JERR_BAD_PROG_SCRIPT,
"Invalid progressive parameters at scan script entry %d")
JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
JMESSAGE(JERR_BAD_STRUCT_SIZE,
"JPEG parameter struct mismatch: library thinks size is %u, caller expects %u")
JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d")
JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x")
JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d")
JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d")
JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)")
JMESSAGE(JERR_EMS_READ, "Read from EMS failed")
JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed")
JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan")
JMESSAGE(JERR_FILE_READ, "Input file read error")
JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")
JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet")
JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow")
JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry")
JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels")
JMESSAGE(JERR_INPUT_EMPTY, "Empty input file")
JMESSAGE(JERR_INPUT_EOF, "Premature end of input file")
JMESSAGE(JERR_MISMATCHED_QUANT_TABLE,
"Cannot transcode due to multiple use of quantization table %d")
JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data")
JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change")
JMESSAGE(JERR_NOTIMPL, "Not implemented yet")
JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported")
JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
JMESSAGE(JERR_QUANT_COMPONENTS,
"Cannot quantize more than %d color components")
JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors")
JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors")
JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers")
JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker")
JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x")
JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers")
JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF")
JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s")
JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file")
JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file")
JMESSAGE(JERR_TFILE_WRITE,
"Write failed on temporary file --- out of disk space?")
JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines")
JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x")
JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up")
JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation")
JMESSAGE(JERR_XMS_READ, "Read from XMS failed")
JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed")
JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT)
JMESSAGE(JMSG_VERSION, JVERSION)
JMESSAGE(JTRC_16BIT_TABLES,
"Caution: quantization tables are too coarse for baseline JPEG")
JMESSAGE(JTRC_ADOBE,
"Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d")
JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u")
JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u")
JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x")
JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x")
JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d")
JMESSAGE(JTRC_DRI, "Define Restart Interval %u")
JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u")
JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u")
JMESSAGE(JTRC_EOI, "End Of Image")
JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d")
JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d")
JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
"Warning: thumbnail image size does not match data length %u")
JMESSAGE(JTRC_JFIF_EXTENSION,
"JFIF extension marker: type 0x%02x, length %u")
JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image")
JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u")
JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u")
JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors")
JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors")
JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization")
JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d")
JMESSAGE(JTRC_RST, "RST%d")
JMESSAGE(JTRC_SMOOTH_NOTIMPL,
"Smoothing not supported with nonstandard sampling ratios")
JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d")
JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d")
JMESSAGE(JTRC_SOI, "Start of Image")
JMESSAGE(JTRC_SOS, "Start Of Scan: %d components")
JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d")
JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d")
JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s")
JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s")
JMESSAGE(JTRC_THUMB_JPEG,
"JFIF extension marker: JPEG-compressed thumbnail image, length %u")
JMESSAGE(JTRC_THUMB_PALETTE,
"JFIF extension marker: palette thumbnail image, length %u")
JMESSAGE(JTRC_THUMB_RGB,
"JFIF extension marker: RGB thumbnail image, length %u")
JMESSAGE(JTRC_UNKNOWN_IDS,
"Unrecognized component IDs %d %d %d, assuming YCbCr")
JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
JMESSAGE(JWRN_BOGUS_PROGRESSION,
"Inconsistent progression sequence for component %d coefficient %d")
JMESSAGE(JWRN_EXTRANEOUS_DATA,
"Corrupt JPEG data: %u extraneous bytes before marker 0x%02x")
JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d")
JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
JMESSAGE(JWRN_MUST_RESYNC,
"Corrupt JPEG data: found marker 0x%02x instead of RST%d")
JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
#ifdef JMAKE_ENUM_LIST
JMSG_LASTMSGCODE
} J_MESSAGE_CODE;
#undef JMAKE_ENUM_LIST
#endif /* JMAKE_ENUM_LIST */
/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
#undef JMESSAGE
#ifndef JERROR_H
#define JERROR_H
/* Macros to simplify using the error and trace message stuff */
/* The first parameter is either type of cinfo pointer */
/* Fatal errors (print message and exit) */
#define ERREXIT(cinfo,code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT1(cinfo,code,p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT2(cinfo,code,p1,p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT3(cinfo,code,p1,p2,p3) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(cinfo)->err->msg_parm.i[3] = (p4), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXITS(cinfo,code,str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define MAKESTMT(stuff) do { stuff } while (0)
/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
#define WARNMS(cinfo,code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
#define WARNMS1(cinfo,code,p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
#define WARNMS2(cinfo,code,p1,p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
/* Informational/debugging messages */
#define TRACEMS(cinfo,lvl,code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS1(cinfo,lvl,code,p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS2(cinfo,lvl,code,p1,p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
_mp[4] = (p5); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
_mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMSS(cinfo,lvl,code,str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#endif /* JERROR_H */

168
jfdctflt.c Normal file
View File

@@ -0,0 +1,168 @@
/*
* jfdctflt.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains a floating-point implementation of the
* forward DCT (Discrete Cosine Transform).
*
* This implementation should be more accurate than either of the integer
* DCT implementations. However, it may not give the same results on all
* machines because of differences in roundoff behavior. Speed will depend
* on the hardware's floating point capacity.
*
* A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
* on each column. Direct algorithms are also available, but they are
* much more complex and seem not to be any faster when reduced to code.
*
* This implementation is based on Arai, Agui, and Nakajima's algorithm for
* scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
* Japanese, but the algorithm is described in the Pennebaker & Mitchell
* JPEG textbook (see REFERENCES section in file README). The following code
* is based directly on figure 4-8 in P&M.
* While an 8-point DCT cannot be done in less than 11 multiplies, it is
* possible to arrange the computation so that many of the multiplies are
* simple scalings of the final outputs. These multiplies can then be
* folded into the multiplications or divisions by the JPEG quantization
* table entries. The AA&N method leaves only 5 multiplies and 29 adds
* to be done in the DCT itself.
* The primary disadvantage of this method is that with a fixed-point
* implementation, accuracy is lost due to imprecise representation of the
* scaled quantization values. However, that problem does not arise if
* we use floating point arithmetic.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#ifdef DCT_FLOAT_SUPPORTED
/*
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/*
* Perform the forward DCT on one block of samples.
*/
GLOBAL(void)
jpeg_fdct_float (FAST_FLOAT * data)
{
FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
FAST_FLOAT z1, z2, z3, z4, z5, z11, z13;
FAST_FLOAT *dataptr;
int ctr;
/* Pass 1: process rows. */
dataptr = data;
for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
tmp0 = dataptr[0] + dataptr[7];
tmp7 = dataptr[0] - dataptr[7];
tmp1 = dataptr[1] + dataptr[6];
tmp6 = dataptr[1] - dataptr[6];
tmp2 = dataptr[2] + dataptr[5];
tmp5 = dataptr[2] - dataptr[5];
tmp3 = dataptr[3] + dataptr[4];
tmp4 = dataptr[3] - dataptr[4];
/* Even part */
tmp10 = tmp0 + tmp3; /* phase 2 */
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[0] = tmp10 + tmp11; /* phase 3 */
dataptr[4] = tmp10 - tmp11;
z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
dataptr[2] = tmp13 + z1; /* phase 5 */
dataptr[6] = tmp13 - z1;
/* Odd part */
tmp10 = tmp4 + tmp5; /* phase 2 */
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
dataptr[5] = z13 + z2; /* phase 6 */
dataptr[3] = z13 - z2;
dataptr[1] = z11 + z4;
dataptr[7] = z11 - z4;
dataptr += DCTSIZE; /* advance pointer to next row */
}
/* Pass 2: process columns. */
dataptr = data;
for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
/* Even part */
tmp10 = tmp0 + tmp3; /* phase 2 */
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
dataptr[DCTSIZE*4] = tmp10 - tmp11;
z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
dataptr[DCTSIZE*6] = tmp13 - z1;
/* Odd part */
tmp10 = tmp4 + tmp5; /* phase 2 */
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
dataptr[DCTSIZE*3] = z13 - z2;
dataptr[DCTSIZE*1] = z11 + z4;
dataptr[DCTSIZE*7] = z11 - z4;
dataptr++; /* advance pointer to next column */
}
}
#endif /* DCT_FLOAT_SUPPORTED */

224
jfdctfst.c Normal file
View File

@@ -0,0 +1,224 @@
/*
* jfdctfst.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains a fast, not so accurate integer implementation of the
* forward DCT (Discrete Cosine Transform).
*
* A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
* on each column. Direct algorithms are also available, but they are
* much more complex and seem not to be any faster when reduced to code.
*
* This implementation is based on Arai, Agui, and Nakajima's algorithm for
* scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
* Japanese, but the algorithm is described in the Pennebaker & Mitchell
* JPEG textbook (see REFERENCES section in file README). The following code
* is based directly on figure 4-8 in P&M.
* While an 8-point DCT cannot be done in less than 11 multiplies, it is
* possible to arrange the computation so that many of the multiplies are
* simple scalings of the final outputs. These multiplies can then be
* folded into the multiplications or divisions by the JPEG quantization
* table entries. The AA&N method leaves only 5 multiplies and 29 adds
* to be done in the DCT itself.
* The primary disadvantage of this method is that with fixed-point math,
* accuracy is lost due to imprecise representation of the scaled
* quantization values. The smaller the quantization table entry, the less
* precise the scaled value, so this implementation does worse with high-
* quality-setting files than with low-quality ones.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#ifdef DCT_IFAST_SUPPORTED
/*
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/* Scaling decisions are generally the same as in the LL&M algorithm;
* see jfdctint.c for more details. However, we choose to descale
* (right shift) multiplication products as soon as they are formed,
* rather than carrying additional fractional bits into subsequent additions.
* This compromises accuracy slightly, but it lets us save a few shifts.
* More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
* everywhere except in the multiplications proper; this saves a good deal
* of work on 16-bit-int machines.
*
* Again to save a few shifts, the intermediate results between pass 1 and
* pass 2 are not upscaled, but are represented only to integral precision.
*
* A final compromise is to represent the multiplicative constants to only
* 8 fractional bits, rather than 13. This saves some shifting work on some
* machines, and may also reduce the cost of multiplication (since there
* are fewer one-bits in the constants).
*/
#define CONST_BITS 8
/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
* causing a lot of useless floating-point operations at run time.
* To get around this we use the following pre-calculated constants.
* If you change CONST_BITS you may want to add appropriate values.
* (With a reasonable C compiler, you can just rely on the FIX() macro...)
*/
#if CONST_BITS == 8
#define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */
#define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */
#define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */
#define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */
#else
#define FIX_0_382683433 FIX(0.382683433)
#define FIX_0_541196100 FIX(0.541196100)
#define FIX_0_707106781 FIX(0.707106781)
#define FIX_1_306562965 FIX(1.306562965)
#endif
/* We can gain a little more speed, with a further compromise in accuracy,
* by omitting the addition in a descaling shift. This yields an incorrectly
* rounded result half the time...
*/
#ifndef USE_ACCURATE_ROUNDING
#undef DESCALE
#define DESCALE(x,n) RIGHT_SHIFT(x, n)
#endif
/* Multiply a DCTELEM variable by an INT32 constant, and immediately
* descale to yield a DCTELEM result.
*/
#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
/*
* Perform the forward DCT on one block of samples.
*/
GLOBAL(void)
jpeg_fdct_ifast (DCTELEM * data)
{
DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
DCTELEM tmp10, tmp11, tmp12, tmp13;
DCTELEM z1, z2, z3, z4, z5, z11, z13;
DCTELEM *dataptr;
int ctr;
SHIFT_TEMPS
/* Pass 1: process rows. */
dataptr = data;
for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
tmp0 = dataptr[0] + dataptr[7];
tmp7 = dataptr[0] - dataptr[7];
tmp1 = dataptr[1] + dataptr[6];
tmp6 = dataptr[1] - dataptr[6];
tmp2 = dataptr[2] + dataptr[5];
tmp5 = dataptr[2] - dataptr[5];
tmp3 = dataptr[3] + dataptr[4];
tmp4 = dataptr[3] - dataptr[4];
/* Even part */
tmp10 = tmp0 + tmp3; /* phase 2 */
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[0] = tmp10 + tmp11; /* phase 3 */
dataptr[4] = tmp10 - tmp11;
z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
dataptr[2] = tmp13 + z1; /* phase 5 */
dataptr[6] = tmp13 - z1;
/* Odd part */
tmp10 = tmp4 + tmp5; /* phase 2 */
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
dataptr[5] = z13 + z2; /* phase 6 */
dataptr[3] = z13 - z2;
dataptr[1] = z11 + z4;
dataptr[7] = z11 - z4;
dataptr += DCTSIZE; /* advance pointer to next row */
}
/* Pass 2: process columns. */
dataptr = data;
for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
/* Even part */
tmp10 = tmp0 + tmp3; /* phase 2 */
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
dataptr[DCTSIZE*4] = tmp10 - tmp11;
z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
dataptr[DCTSIZE*6] = tmp13 - z1;
/* Odd part */
tmp10 = tmp4 + tmp5; /* phase 2 */
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
dataptr[DCTSIZE*3] = z13 - z2;
dataptr[DCTSIZE*1] = z11 + z4;
dataptr[DCTSIZE*7] = z11 - z4;
dataptr++; /* advance pointer to next column */
}
}
#endif /* DCT_IFAST_SUPPORTED */

View File

@@ -1,12 +1,16 @@
/*
* jfwddct.c
* jfdctint.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the basic DCT (Discrete Cosine Transform)
* transformation subroutine.
* This file contains a slow-but-accurate integer implementation of the
* forward DCT (Discrete Cosine Transform).
*
* A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
* on each column. Direct algorithms are also available, but they are
* much more complex and seem not to be any faster when reduced to code.
*
* This implementation is based on an algorithm described in
* C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
@@ -19,10 +23,16 @@
* scaled fixed-point arithmetic, with a minimal number of shifts.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#ifdef DCT_ISLOW_SUPPORTED
/*
* This routine is specialized to the case DCTSIZE = 8.
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
@@ -31,10 +41,6 @@
/*
* A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
* on each column. Direct algorithms are also available, but they are
* much more complex and seem not to be any faster when reduced to code.
*
* The poop on this scaling stuff is as follows:
*
* Each 1-D DCT step produces outputs which are a factor of sqrt(N)
@@ -43,6 +49,8 @@
* a simple right shift at the end of the algorithm. The advantage of
* this arrangement is that we save two multiplications per 1-D DCT,
* because the y0 and y4 outputs need not be divided by sqrt(N).
* In the IJG code, this factor of 8 is removed by the quantization step
* (in jcdctmgr.c), NOT in this module.
*
* We have to do addition and subtraction of the integer inputs, which
* is no problem, and multiplication by fractional constants, which is
@@ -58,30 +66,22 @@
* The outputs of the first pass are scaled up by PASS1_BITS bits so that
* they are represented to better-than-integral precision. These outputs
* require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
* with the recommended scaling. (To scale up 12-bit sample data, an
* intermediate INT32 array would be needed.)
* with the recommended scaling. (For 12-bit sample data, the intermediate
* array is INT32 anyway.)
*
* To avoid overflow of the 32-bit intermediate results in pass 2, we must
* have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 25. Error analysis
* have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis
* shows that the values given below are the most effective.
*/
#ifdef EIGHT_BIT_SAMPLES
#if BITS_IN_JSAMPLE == 8
#define CONST_BITS 13
#define PASS1_BITS 2
#else
#define CONST_BITS 13
#define PASS1_BITS 0 /* lose a little precision to avoid overflow */
#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
#endif
#define ONE ((INT32) 1)
#define CONST_SCALE (ONE << CONST_BITS)
/* Convert a positive real constant to an integer scaled by CONST_SCALE. */
#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
* causing a lot of useless floating-point operations at run time.
* To get around this we use the following pre-calculated constants.
@@ -118,34 +118,16 @@
#endif
/* Descale and correctly round an INT32 value that's scaled by N bits.
* We assume RIGHT_SHIFT rounds towards minus infinity, so adding
* the fudge factor is correct for either sign of X.
*/
#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
* For 8-bit samples with the recommended scaling, all the variable
* and constant values involved are no more than 16 bits wide, so a
* 16x16->32 bit multiply can be used instead of a full 32x32 multiply;
* this provides a useful speedup on many machines.
* There is no way to specify a 16x16->32 multiply in portable C, but
* some C compilers will do the right thing if you provide the correct
* combination of casts.
* NB: for 12-bit samples, a full 32-bit multiplication will be needed.
* 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
* For 12-bit samples, a full 32-bit multiplication will be needed.
*/
#ifdef EIGHT_BIT_SAMPLES
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
#define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const)))
#endif
#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
#define MULTIPLY(var,const) (((INT16) (var)) * ((INT32) (const)))
#endif
#endif
#ifndef MULTIPLY /* default definition */
#if BITS_IN_JSAMPLE == 8
#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
#else
#define MULTIPLY(var,const) ((var) * (const))
#endif
@@ -154,14 +136,14 @@
* Perform the forward DCT on one block of samples.
*/
GLOBAL void
j_fwd_dct (DCTBLOCK data)
GLOBAL(void)
jpeg_fdct_islow (DCTELEM * data)
{
INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
INT32 tmp10, tmp11, tmp12, tmp13;
INT32 z1, z2, z3, z4, z5;
register DCTELEM *dataptr;
int rowctr;
DCTELEM *dataptr;
int ctr;
SHIFT_TEMPS
/* Pass 1: process rows. */
@@ -169,7 +151,7 @@ j_fwd_dct (DCTBLOCK data)
/* furthermore, we scale the results by 2**PASS1_BITS. */
dataptr = data;
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
tmp0 = dataptr[0] + dataptr[7];
tmp7 = dataptr[0] - dataptr[7];
tmp1 = dataptr[1] + dataptr[6];
@@ -228,12 +210,13 @@ j_fwd_dct (DCTBLOCK data)
dataptr += DCTSIZE; /* advance pointer to next row */
}
/* Pass 2: process columns. */
/* Note that we must descale the results by a factor of 8 == 2**3, */
/* and also undo the PASS1_BITS scaling. */
/* Pass 2: process columns.
* We remove the PASS1_BITS scaling, but leave the results scaled up
* by an overall factor of 8.
*/
dataptr = data;
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
@@ -252,14 +235,14 @@ j_fwd_dct (DCTBLOCK data)
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS+3);
dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS+3);
dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS);
dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS);
z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
CONST_BITS+PASS1_BITS+3);
CONST_BITS+PASS1_BITS);
dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
CONST_BITS+PASS1_BITS+3);
CONST_BITS+PASS1_BITS);
/* Odd part per figure 8 --- note paper omits factor of sqrt(2).
* cK represents cos(K*pi/16).
@@ -285,14 +268,16 @@ j_fwd_dct (DCTBLOCK data)
z4 += z5;
dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3,
CONST_BITS+PASS1_BITS+3);
CONST_BITS+PASS1_BITS);
dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4,
CONST_BITS+PASS1_BITS+3);
CONST_BITS+PASS1_BITS);
dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3,
CONST_BITS+PASS1_BITS+3);
CONST_BITS+PASS1_BITS);
dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4,
CONST_BITS+PASS1_BITS+3);
CONST_BITS+PASS1_BITS);
dataptr++; /* advance pointer to next column */
}
}
#endif /* DCT_ISLOW_SUPPORTED */

242
jidctflt.c Normal file
View File

@@ -0,0 +1,242 @@
/*
* jidctflt.c
*
* Copyright (C) 1994-1998, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains a floating-point implementation of the
* inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
* must also perform dequantization of the input coefficients.
*
* This implementation should be more accurate than either of the integer
* IDCT implementations. However, it may not give the same results on all
* machines because of differences in roundoff behavior. Speed will depend
* on the hardware's floating point capacity.
*
* A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
* on each row (or vice versa, but it's more convenient to emit a row at
* a time). Direct algorithms are also available, but they are much more
* complex and seem not to be any faster when reduced to code.
*
* This implementation is based on Arai, Agui, and Nakajima's algorithm for
* scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
* Japanese, but the algorithm is described in the Pennebaker & Mitchell
* JPEG textbook (see REFERENCES section in file README). The following code
* is based directly on figure 4-8 in P&M.
* While an 8-point DCT cannot be done in less than 11 multiplies, it is
* possible to arrange the computation so that many of the multiplies are
* simple scalings of the final outputs. These multiplies can then be
* folded into the multiplications or divisions by the JPEG quantization
* table entries. The AA&N method leaves only 5 multiplies and 29 adds
* to be done in the DCT itself.
* The primary disadvantage of this method is that with a fixed-point
* implementation, accuracy is lost due to imprecise representation of the
* scaled quantization values. However, that problem does not arise if
* we use floating point arithmetic.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#ifdef DCT_FLOAT_SUPPORTED
/*
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/* Dequantize a coefficient by multiplying it by the multiplier-table
* entry; produce a float result.
*/
#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval))
/*
* Perform dequantization and inverse DCT on one block of coefficients.
*/
GLOBAL(void)
jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block,
JSAMPARRAY output_buf, JDIMENSION output_col)
{
FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
FAST_FLOAT z5, z10, z11, z12, z13;
JCOEFPTR inptr;
FLOAT_MULT_TYPE * quantptr;
FAST_FLOAT * wsptr;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; ctr--) {
/* Due to quantization, we will usually find that many of the input
* coefficients are zero, especially the AC terms. We can exploit this
* by short-circuiting the IDCT calculation for any column in which all
* the AC terms are zero. In that case each output is equal to the
* DC coefficient (with scale factor as needed).
* With typical images and quantization tables, half or more of the
* column DCT calculations can be simplified this way.
*/
if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
inptr[DCTSIZE*7] == 0) {
/* AC terms all zero */
FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
wsptr[DCTSIZE*0] = dcval;
wsptr[DCTSIZE*1] = dcval;
wsptr[DCTSIZE*2] = dcval;
wsptr[DCTSIZE*3] = dcval;
wsptr[DCTSIZE*4] = dcval;
wsptr[DCTSIZE*5] = dcval;
wsptr[DCTSIZE*6] = dcval;
wsptr[DCTSIZE*7] = dcval;
inptr++; /* advance pointers to next column */
quantptr++;
wsptr++;
continue;
}
/* Even part */
tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
tmp10 = tmp0 + tmp2; /* phase 3 */
tmp11 = tmp0 - tmp2;
tmp13 = tmp1 + tmp3; /* phases 5-3 */
tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */
tmp0 = tmp10 + tmp13; /* phase 2 */
tmp3 = tmp10 - tmp13;
tmp1 = tmp11 + tmp12;
tmp2 = tmp11 - tmp12;
/* Odd part */
tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
z13 = tmp6 + tmp5; /* phase 6 */
z10 = tmp6 - tmp5;
z11 = tmp4 + tmp7;
z12 = tmp4 - tmp7;
tmp7 = z11 + z13; /* phase 5 */
tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */
z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
tmp6 = tmp12 - tmp7; /* phase 2 */
tmp5 = tmp11 - tmp6;
tmp4 = tmp10 + tmp5;
wsptr[DCTSIZE*0] = tmp0 + tmp7;
wsptr[DCTSIZE*7] = tmp0 - tmp7;
wsptr[DCTSIZE*1] = tmp1 + tmp6;
wsptr[DCTSIZE*6] = tmp1 - tmp6;
wsptr[DCTSIZE*2] = tmp2 + tmp5;
wsptr[DCTSIZE*5] = tmp2 - tmp5;
wsptr[DCTSIZE*4] = tmp3 + tmp4;
wsptr[DCTSIZE*3] = tmp3 - tmp4;
inptr++; /* advance pointers to next column */
quantptr++;
wsptr++;
}
/* Pass 2: process rows from work array, store into output array. */
/* Note that we must descale the results by a factor of 8 == 2**3. */
wsptr = workspace;
for (ctr = 0; ctr < DCTSIZE; ctr++) {
outptr = output_buf[ctr] + output_col;
/* Rows of zeroes can be exploited in the same way as we did with columns.
* However, the column calculation has created many nonzero AC terms, so
* the simplification applies less often (typically 5% to 10% of the time).
* And testing floats for zero is relatively expensive, so we don't bother.
*/
/* Even part */
tmp10 = wsptr[0] + wsptr[4];
tmp11 = wsptr[0] - wsptr[4];
tmp13 = wsptr[2] + wsptr[6];
tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13;
tmp0 = tmp10 + tmp13;
tmp3 = tmp10 - tmp13;
tmp1 = tmp11 + tmp12;
tmp2 = tmp11 - tmp12;
/* Odd part */
z13 = wsptr[5] + wsptr[3];
z10 = wsptr[5] - wsptr[3];
z11 = wsptr[1] + wsptr[7];
z12 = wsptr[1] - wsptr[7];
tmp7 = z11 + z13;
tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562);
z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
tmp6 = tmp12 - tmp7;
tmp5 = tmp11 - tmp6;
tmp4 = tmp10 + tmp5;
/* Final output stage: scale down by a factor of 8 and range-limit */
outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3)
& RANGE_MASK];
outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3)
& RANGE_MASK];
outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3)
& RANGE_MASK];
outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3)
& RANGE_MASK];
outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3)
& RANGE_MASK];
outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3)
& RANGE_MASK];
outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3)
& RANGE_MASK];
outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3)
& RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
}
#endif /* DCT_FLOAT_SUPPORTED */

368
jidctfst.c Normal file
View File

@@ -0,0 +1,368 @@
/*
* jidctfst.c
*
* Copyright (C) 1994-1998, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains a fast, not so accurate integer implementation of the
* inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
* must also perform dequantization of the input coefficients.
*
* A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
* on each row (or vice versa, but it's more convenient to emit a row at
* a time). Direct algorithms are also available, but they are much more
* complex and seem not to be any faster when reduced to code.
*
* This implementation is based on Arai, Agui, and Nakajima's algorithm for
* scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
* Japanese, but the algorithm is described in the Pennebaker & Mitchell
* JPEG textbook (see REFERENCES section in file README). The following code
* is based directly on figure 4-8 in P&M.
* While an 8-point DCT cannot be done in less than 11 multiplies, it is
* possible to arrange the computation so that many of the multiplies are
* simple scalings of the final outputs. These multiplies can then be
* folded into the multiplications or divisions by the JPEG quantization
* table entries. The AA&N method leaves only 5 multiplies and 29 adds
* to be done in the DCT itself.
* The primary disadvantage of this method is that with fixed-point math,
* accuracy is lost due to imprecise representation of the scaled
* quantization values. The smaller the quantization table entry, the less
* precise the scaled value, so this implementation does worse with high-
* quality-setting files than with low-quality ones.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#ifdef DCT_IFAST_SUPPORTED
/*
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/* Scaling decisions are generally the same as in the LL&M algorithm;
* see jidctint.c for more details. However, we choose to descale
* (right shift) multiplication products as soon as they are formed,
* rather than carrying additional fractional bits into subsequent additions.
* This compromises accuracy slightly, but it lets us save a few shifts.
* More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
* everywhere except in the multiplications proper; this saves a good deal
* of work on 16-bit-int machines.
*
* The dequantized coefficients are not integers because the AA&N scaling
* factors have been incorporated. We represent them scaled up by PASS1_BITS,
* so that the first and second IDCT rounds have the same input scaling.
* For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to
* avoid a descaling shift; this compromises accuracy rather drastically
* for small quantization table entries, but it saves a lot of shifts.
* For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway,
* so we use a much larger scaling factor to preserve accuracy.
*
* A final compromise is to represent the multiplicative constants to only
* 8 fractional bits, rather than 13. This saves some shifting work on some
* machines, and may also reduce the cost of multiplication (since there
* are fewer one-bits in the constants).
*/
#if BITS_IN_JSAMPLE == 8
#define CONST_BITS 8
#define PASS1_BITS 2
#else
#define CONST_BITS 8
#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
#endif
/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
* causing a lot of useless floating-point operations at run time.
* To get around this we use the following pre-calculated constants.
* If you change CONST_BITS you may want to add appropriate values.
* (With a reasonable C compiler, you can just rely on the FIX() macro...)
*/
#if CONST_BITS == 8
#define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */
#define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */
#define FIX_1_847759065 ((INT32) 473) /* FIX(1.847759065) */
#define FIX_2_613125930 ((INT32) 669) /* FIX(2.613125930) */
#else
#define FIX_1_082392200 FIX(1.082392200)
#define FIX_1_414213562 FIX(1.414213562)
#define FIX_1_847759065 FIX(1.847759065)
#define FIX_2_613125930 FIX(2.613125930)
#endif
/* We can gain a little more speed, with a further compromise in accuracy,
* by omitting the addition in a descaling shift. This yields an incorrectly
* rounded result half the time...
*/
#ifndef USE_ACCURATE_ROUNDING
#undef DESCALE
#define DESCALE(x,n) RIGHT_SHIFT(x, n)
#endif
/* Multiply a DCTELEM variable by an INT32 constant, and immediately
* descale to yield a DCTELEM result.
*/
#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
/* Dequantize a coefficient by multiplying it by the multiplier-table
* entry; produce a DCTELEM result. For 8-bit data a 16x16->16
* multiplication will do. For 12-bit data, the multiplier table is
* declared INT32, so a 32-bit multiply will be used.
*/
#if BITS_IN_JSAMPLE == 8
#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval))
#else
#define DEQUANTIZE(coef,quantval) \
DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS)
#endif
/* Like DESCALE, but applies to a DCTELEM and produces an int.
* We assume that int right shift is unsigned if INT32 right shift is.
*/
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define ISHIFT_TEMPS DCTELEM ishift_temp;
#if BITS_IN_JSAMPLE == 8
#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */
#else
#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */
#endif
#define IRIGHT_SHIFT(x,shft) \
((ishift_temp = (x)) < 0 ? \
(ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \
(ishift_temp >> (shft)))
#else
#define ISHIFT_TEMPS
#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
#endif
#ifdef USE_ACCURATE_ROUNDING
#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n))
#else
#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n))
#endif
/*
* Perform dequantization and inverse DCT on one block of coefficients.
*/
GLOBAL(void)
jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block,
JSAMPARRAY output_buf, JDIMENSION output_col)
{
DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
DCTELEM tmp10, tmp11, tmp12, tmp13;
DCTELEM z5, z10, z11, z12, z13;
JCOEFPTR inptr;
IFAST_MULT_TYPE * quantptr;
int * wsptr;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
int workspace[DCTSIZE2]; /* buffers data between passes */
SHIFT_TEMPS /* for DESCALE */
ISHIFT_TEMPS /* for IDESCALE */
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
quantptr = (IFAST_MULT_TYPE *) compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; ctr--) {
/* Due to quantization, we will usually find that many of the input
* coefficients are zero, especially the AC terms. We can exploit this
* by short-circuiting the IDCT calculation for any column in which all
* the AC terms are zero. In that case each output is equal to the
* DC coefficient (with scale factor as needed).
* With typical images and quantization tables, half or more of the
* column DCT calculations can be simplified this way.
*/
if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
inptr[DCTSIZE*7] == 0) {
/* AC terms all zero */
int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
wsptr[DCTSIZE*0] = dcval;
wsptr[DCTSIZE*1] = dcval;
wsptr[DCTSIZE*2] = dcval;
wsptr[DCTSIZE*3] = dcval;
wsptr[DCTSIZE*4] = dcval;
wsptr[DCTSIZE*5] = dcval;
wsptr[DCTSIZE*6] = dcval;
wsptr[DCTSIZE*7] = dcval;
inptr++; /* advance pointers to next column */
quantptr++;
wsptr++;
continue;
}
/* Even part */
tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
tmp10 = tmp0 + tmp2; /* phase 3 */
tmp11 = tmp0 - tmp2;
tmp13 = tmp1 + tmp3; /* phases 5-3 */
tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */
tmp0 = tmp10 + tmp13; /* phase 2 */
tmp3 = tmp10 - tmp13;
tmp1 = tmp11 + tmp12;
tmp2 = tmp11 - tmp12;
/* Odd part */
tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
z13 = tmp6 + tmp5; /* phase 6 */
z10 = tmp6 - tmp5;
z11 = tmp4 + tmp7;
z12 = tmp4 - tmp7;
tmp7 = z11 + z13; /* phase 5 */
tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
tmp6 = tmp12 - tmp7; /* phase 2 */
tmp5 = tmp11 - tmp6;
tmp4 = tmp10 + tmp5;
wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7);
wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7);
wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6);
wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6);
wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5);
wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5);
wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4);
wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4);
inptr++; /* advance pointers to next column */
quantptr++;
wsptr++;
}
/* Pass 2: process rows from work array, store into output array. */
/* Note that we must descale the results by a factor of 8 == 2**3, */
/* and also undo the PASS1_BITS scaling. */
wsptr = workspace;
for (ctr = 0; ctr < DCTSIZE; ctr++) {
outptr = output_buf[ctr] + output_col;
/* Rows of zeroes can be exploited in the same way as we did with columns.
* However, the column calculation has created many nonzero AC terms, so
* the simplification applies less often (typically 5% to 10% of the time).
* On machines with very fast multiplication, it's possible that the
* test takes more time than it's worth. In that case this section
* may be commented out.
*/
#ifndef NO_ZERO_ROW_TEST
if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 &&
wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
/* AC terms all zero */
JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3)
& RANGE_MASK];
outptr[0] = dcval;
outptr[1] = dcval;
outptr[2] = dcval;
outptr[3] = dcval;
outptr[4] = dcval;
outptr[5] = dcval;
outptr[6] = dcval;
outptr[7] = dcval;
wsptr += DCTSIZE; /* advance pointer to next row */
continue;
}
#endif
/* Even part */
tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]);
tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]);
tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]);
tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562)
- tmp13;
tmp0 = tmp10 + tmp13;
tmp3 = tmp10 - tmp13;
tmp1 = tmp11 + tmp12;
tmp2 = tmp11 - tmp12;
/* Odd part */
z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3];
z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3];
z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7];
z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7];
tmp7 = z11 + z13; /* phase 5 */
tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
tmp6 = tmp12 - tmp7; /* phase 2 */
tmp5 = tmp11 - tmp6;
tmp4 = tmp10 + tmp5;
/* Final output stage: scale down by a factor of 8 and range-limit */
outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3)
& RANGE_MASK];
outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3)
& RANGE_MASK];
outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3)
& RANGE_MASK];
outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3)
& RANGE_MASK];
outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3)
& RANGE_MASK];
outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3)
& RANGE_MASK];
outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3)
& RANGE_MASK];
outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3)
& RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
}
#endif /* DCT_IFAST_SUPPORTED */

View File

@@ -1,11 +1,18 @@
/*
* jrevdct.c
* jidctint.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1998, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the basic inverse-DCT transformation subroutine.
* This file contains a slow-but-accurate integer implementation of the
* inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
* must also perform dequantization of the input coefficients.
*
* A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
* on each row (or vice versa, but it's more convenient to emit a row at
* a time). Direct algorithms are also available, but they are much more
* complex and seem not to be any faster when reduced to code.
*
* This implementation is based on an algorithm described in
* C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
@@ -18,10 +25,16 @@
* scaled fixed-point arithmetic, with a minimal number of shifts.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#ifdef DCT_ISLOW_SUPPORTED
/*
* This routine is specialized to the case DCTSIZE = 8.
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
@@ -30,10 +43,6 @@
/*
* A 2-D IDCT can be done by 1-D IDCT on each row followed by 1-D IDCT
* on each column. Direct algorithms are also available, but they are
* much more complex and seem not to be any faster when reduced to code.
*
* The poop on this scaling stuff is as follows:
*
* Each 1-D IDCT step produces outputs which are a factor of sqrt(N)
@@ -65,7 +74,7 @@
* shows that the values given below are the most effective.
*/
#ifdef EIGHT_BIT_SAMPLES
#if BITS_IN_JSAMPLE == 8
#define CONST_BITS 13
#define PASS1_BITS 2
#else
@@ -73,14 +82,6 @@
#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
#endif
#define ONE ((INT32) 1)
#define CONST_SCALE (ONE << CONST_BITS)
/* Convert a positive real constant to an integer scaled by CONST_SCALE. */
#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
* causing a lot of useless floating-point operations at run time.
* To get around this we use the following pre-calculated constants.
@@ -117,97 +118,103 @@
#endif
/* Descale and correctly round an INT32 value that's scaled by N bits.
* We assume RIGHT_SHIFT rounds towards minus infinity, so adding
* the fudge factor is correct for either sign of X.
*/
#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
* For 8-bit samples with the recommended scaling, all the variable
* and constant values involved are no more than 16 bits wide, so a
* 16x16->32 bit multiply can be used instead of a full 32x32 multiply;
* this provides a useful speedup on many machines.
* There is no way to specify a 16x16->32 multiply in portable C, but
* some C compilers will do the right thing if you provide the correct
* combination of casts.
* NB: for 12-bit samples, a full 32-bit multiplication will be needed.
* 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
* For 12-bit samples, a full 32-bit multiplication will be needed.
*/
#ifdef EIGHT_BIT_SAMPLES
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
#define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const)))
#endif
#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
#define MULTIPLY(var,const) (((INT16) (var)) * ((INT32) (const)))
#endif
#endif
#ifndef MULTIPLY /* default definition */
#if BITS_IN_JSAMPLE == 8
#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
#else
#define MULTIPLY(var,const) ((var) * (const))
#endif
/*
* Perform the inverse DCT on one block of coefficients.
/* Dequantize a coefficient by multiplying it by the multiplier-table
* entry; produce an int result. In this module, both inputs and result
* are 16 bits or less, so either int or short multiply will work.
*/
GLOBAL void
j_rev_dct (DCTBLOCK data)
#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval))
/*
* Perform dequantization and inverse DCT on one block of coefficients.
*/
GLOBAL(void)
jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block,
JSAMPARRAY output_buf, JDIMENSION output_col)
{
INT32 tmp0, tmp1, tmp2, tmp3;
INT32 tmp10, tmp11, tmp12, tmp13;
INT32 z1, z2, z3, z4, z5;
register DCTELEM *dataptr;
int rowctr;
JCOEFPTR inptr;
ISLOW_MULT_TYPE * quantptr;
int * wsptr;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
int workspace[DCTSIZE2]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process rows. */
/* Pass 1: process columns from input, store into work array. */
/* Note results are scaled up by sqrt(8) compared to a true IDCT; */
/* furthermore, we scale the results by 2**PASS1_BITS. */
dataptr = data;
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
inptr = coef_block;
quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; ctr--) {
/* Due to quantization, we will usually find that many of the input
* coefficients are zero, especially the AC terms. We can exploit this
* by short-circuiting the IDCT calculation for any row in which all
* by short-circuiting the IDCT calculation for any column in which all
* the AC terms are zero. In that case each output is equal to the
* DC coefficient (with scale factor as needed).
* With typical images and quantization tables, half or more of the
* row DCT calculations can be simplified this way.
* column DCT calculations can be simplified this way.
*/
if ((dataptr[1] | dataptr[2] | dataptr[3] | dataptr[4] |
dataptr[5] | dataptr[6] | dataptr[7]) == 0) {
if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
inptr[DCTSIZE*7] == 0) {
/* AC terms all zero */
DCTELEM dcval = (DCTELEM) (dataptr[0] << PASS1_BITS);
int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
dataptr[0] = dcval;
dataptr[1] = dcval;
dataptr[2] = dcval;
dataptr[3] = dcval;
dataptr[4] = dcval;
dataptr[5] = dcval;
dataptr[6] = dcval;
dataptr[7] = dcval;
wsptr[DCTSIZE*0] = dcval;
wsptr[DCTSIZE*1] = dcval;
wsptr[DCTSIZE*2] = dcval;
wsptr[DCTSIZE*3] = dcval;
wsptr[DCTSIZE*4] = dcval;
wsptr[DCTSIZE*5] = dcval;
wsptr[DCTSIZE*6] = dcval;
wsptr[DCTSIZE*7] = dcval;
dataptr += DCTSIZE; /* advance pointer to next row */
inptr++; /* advance pointers to next column */
quantptr++;
wsptr++;
continue;
}
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
z2 = (INT32) dataptr[2];
z3 = (INT32) dataptr[6];
z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
tmp0 = ((INT32) dataptr[0] + (INT32) dataptr[4]) << CONST_BITS;
tmp1 = ((INT32) dataptr[0] - (INT32) dataptr[4]) << CONST_BITS;
z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
tmp0 = (z2 + z3) << CONST_BITS;
tmp1 = (z2 - z3) << CONST_BITS;
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
@@ -218,10 +225,10 @@ j_rev_dct (DCTBLOCK data)
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
tmp0 = (INT32) dataptr[7];
tmp1 = (INT32) dataptr[5];
tmp2 = (INT32) dataptr[3];
tmp3 = (INT32) dataptr[1];
tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
@@ -248,49 +255,52 @@ j_rev_dct (DCTBLOCK data)
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
dataptr[0] = (DCTELEM) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
dataptr[7] = (DCTELEM) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
dataptr[6] = (DCTELEM) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
dataptr[2] = (DCTELEM) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
dataptr[5] = (DCTELEM) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
dataptr[3] = (DCTELEM) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
dataptr[4] = (DCTELEM) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
dataptr += DCTSIZE; /* advance pointer to next row */
inptr++; /* advance pointers to next column */
quantptr++;
wsptr++;
}
/* Pass 2: process columns. */
/* Pass 2: process rows from work array, store into output array. */
/* Note that we must descale the results by a factor of 8 == 2**3, */
/* and also undo the PASS1_BITS scaling. */
dataptr = data;
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
/* Columns of zeroes can be exploited in the same way as we did with rows.
* However, the row calculation has created many nonzero AC terms, so the
* simplification applies less often (typically 5% to 10% of the time).
wsptr = workspace;
for (ctr = 0; ctr < DCTSIZE; ctr++) {
outptr = output_buf[ctr] + output_col;
/* Rows of zeroes can be exploited in the same way as we did with columns.
* However, the column calculation has created many nonzero AC terms, so
* the simplification applies less often (typically 5% to 10% of the time).
* On machines with very fast multiplication, it's possible that the
* test takes more time than it's worth. In that case this section
* may be commented out.
*/
#ifndef NO_ZERO_COLUMN_TEST
if ((dataptr[DCTSIZE*1] | dataptr[DCTSIZE*2] | dataptr[DCTSIZE*3] |
dataptr[DCTSIZE*4] | dataptr[DCTSIZE*5] | dataptr[DCTSIZE*6] |
dataptr[DCTSIZE*7]) == 0) {
#ifndef NO_ZERO_ROW_TEST
if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 &&
wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
/* AC terms all zero */
DCTELEM dcval = (DCTELEM) DESCALE((INT32) dataptr[0], PASS1_BITS+3);
JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
& RANGE_MASK];
dataptr[DCTSIZE*0] = dcval;
dataptr[DCTSIZE*1] = dcval;
dataptr[DCTSIZE*2] = dcval;
dataptr[DCTSIZE*3] = dcval;
dataptr[DCTSIZE*4] = dcval;
dataptr[DCTSIZE*5] = dcval;
dataptr[DCTSIZE*6] = dcval;
dataptr[DCTSIZE*7] = dcval;
outptr[0] = dcval;
outptr[1] = dcval;
outptr[2] = dcval;
outptr[3] = dcval;
outptr[4] = dcval;
outptr[5] = dcval;
outptr[6] = dcval;
outptr[7] = dcval;
dataptr++; /* advance pointer to next column */
wsptr += DCTSIZE; /* advance pointer to next row */
continue;
}
#endif
@@ -298,15 +308,15 @@ j_rev_dct (DCTBLOCK data)
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
z2 = (INT32) dataptr[DCTSIZE*2];
z3 = (INT32) dataptr[DCTSIZE*6];
z2 = (INT32) wsptr[2];
z3 = (INT32) wsptr[6];
z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
tmp0 = ((INT32) dataptr[DCTSIZE*0] + (INT32) dataptr[DCTSIZE*4]) << CONST_BITS;
tmp1 = ((INT32) dataptr[DCTSIZE*0] - (INT32) dataptr[DCTSIZE*4]) << CONST_BITS;
tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS;
tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS;
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
@@ -317,10 +327,10 @@ j_rev_dct (DCTBLOCK data)
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
tmp0 = (INT32) dataptr[DCTSIZE*7];
tmp1 = (INT32) dataptr[DCTSIZE*5];
tmp2 = (INT32) dataptr[DCTSIZE*3];
tmp3 = (INT32) dataptr[DCTSIZE*1];
tmp0 = (INT32) wsptr[7];
tmp1 = (INT32) wsptr[5];
tmp2 = (INT32) wsptr[3];
tmp3 = (INT32) wsptr[1];
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
@@ -347,23 +357,33 @@ j_rev_dct (DCTBLOCK data)
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp3,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp10 - tmp3,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp2,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp11 - tmp2,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp12 + tmp1,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12 - tmp1,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp13 + tmp0,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp13 - tmp0,
CONST_BITS+PASS1_BITS+3);
outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
dataptr++; /* advance pointer to next column */
wsptr += DCTSIZE; /* advance pointer to next row */
}
}
#endif /* DCT_ISLOW_SUPPORTED */

398
jidctred.c Normal file
View File

@@ -0,0 +1,398 @@
/*
* jidctred.c
*
* Copyright (C) 1994-1998, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains inverse-DCT routines that produce reduced-size output:
* either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block.
*
* The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M)
* algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step
* with an 8-to-4 step that produces the four averages of two adjacent outputs
* (or an 8-to-2 step producing two averages of four outputs, for 2x2 output).
* These steps were derived by computing the corresponding values at the end
* of the normal LL&M code, then simplifying as much as possible.
*
* 1x1 is trivial: just take the DC coefficient divided by 8.
*
* See jidctint.c for additional comments.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#ifdef IDCT_SCALING_SUPPORTED
/*
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/* Scaling is the same as in jidctint.c. */
#if BITS_IN_JSAMPLE == 8
#define CONST_BITS 13
#define PASS1_BITS 2
#else
#define CONST_BITS 13
#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
#endif
/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
* causing a lot of useless floating-point operations at run time.
* To get around this we use the following pre-calculated constants.
* If you change CONST_BITS you may want to add appropriate values.
* (With a reasonable C compiler, you can just rely on the FIX() macro...)
*/
#if CONST_BITS == 13
#define FIX_0_211164243 ((INT32) 1730) /* FIX(0.211164243) */
#define FIX_0_509795579 ((INT32) 4176) /* FIX(0.509795579) */
#define FIX_0_601344887 ((INT32) 4926) /* FIX(0.601344887) */
#define FIX_0_720959822 ((INT32) 5906) /* FIX(0.720959822) */
#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */
#define FIX_0_850430095 ((INT32) 6967) /* FIX(0.850430095) */
#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */
#define FIX_1_061594337 ((INT32) 8697) /* FIX(1.061594337) */
#define FIX_1_272758580 ((INT32) 10426) /* FIX(1.272758580) */
#define FIX_1_451774981 ((INT32) 11893) /* FIX(1.451774981) */
#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */
#define FIX_2_172734803 ((INT32) 17799) /* FIX(2.172734803) */
#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */
#define FIX_3_624509785 ((INT32) 29692) /* FIX(3.624509785) */
#else
#define FIX_0_211164243 FIX(0.211164243)
#define FIX_0_509795579 FIX(0.509795579)
#define FIX_0_601344887 FIX(0.601344887)
#define FIX_0_720959822 FIX(0.720959822)
#define FIX_0_765366865 FIX(0.765366865)
#define FIX_0_850430095 FIX(0.850430095)
#define FIX_0_899976223 FIX(0.899976223)
#define FIX_1_061594337 FIX(1.061594337)
#define FIX_1_272758580 FIX(1.272758580)
#define FIX_1_451774981 FIX(1.451774981)
#define FIX_1_847759065 FIX(1.847759065)
#define FIX_2_172734803 FIX(2.172734803)
#define FIX_2_562915447 FIX(2.562915447)
#define FIX_3_624509785 FIX(3.624509785)
#endif
/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
* For 8-bit samples with the recommended scaling, all the variable
* and constant values involved are no more than 16 bits wide, so a
* 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
* For 12-bit samples, a full 32-bit multiplication will be needed.
*/
#if BITS_IN_JSAMPLE == 8
#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
#else
#define MULTIPLY(var,const) ((var) * (const))
#endif
/* Dequantize a coefficient by multiplying it by the multiplier-table
* entry; produce an int result. In this module, both inputs and result
* are 16 bits or less, so either int or short multiply will work.
*/
#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval))
/*
* Perform dequantization and inverse DCT on one block of coefficients,
* producing a reduced-size 4x4 output block.
*/
GLOBAL(void)
jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block,
JSAMPARRAY output_buf, JDIMENSION output_col)
{
INT32 tmp0, tmp2, tmp10, tmp12;
INT32 z1, z2, z3, z4;
JCOEFPTR inptr;
ISLOW_MULT_TYPE * quantptr;
int * wsptr;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
int workspace[DCTSIZE*4]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
/* Don't bother to process column 4, because second pass won't use it */
if (ctr == DCTSIZE-4)
continue;
if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 &&
inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) {
/* AC terms all zero; we need not examine term 4 for 4x4 output */
int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
wsptr[DCTSIZE*0] = dcval;
wsptr[DCTSIZE*1] = dcval;
wsptr[DCTSIZE*2] = dcval;
wsptr[DCTSIZE*3] = dcval;
continue;
}
/* Even part */
tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
tmp0 <<= (CONST_BITS+1);
z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865);
tmp10 = tmp0 + tmp2;
tmp12 = tmp0 - tmp2;
/* Odd part */
z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
+ MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
+ MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
+ MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
+ MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
+ MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
+ MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
/* Final output stage */
wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1);
wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1);
wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1);
wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1);
}
/* Pass 2: process 4 rows from work array, store into output array. */
wsptr = workspace;
for (ctr = 0; ctr < 4; ctr++) {
outptr = output_buf[ctr] + output_col;
/* It's not clear whether a zero row test is worthwhile here ... */
#ifndef NO_ZERO_ROW_TEST
if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 &&
wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
/* AC terms all zero */
JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
& RANGE_MASK];
outptr[0] = dcval;
outptr[1] = dcval;
outptr[2] = dcval;
outptr[3] = dcval;
wsptr += DCTSIZE; /* advance pointer to next row */
continue;
}
#endif
/* Even part */
tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1);
tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065)
+ MULTIPLY((INT32) wsptr[6], - FIX_0_765366865);
tmp10 = tmp0 + tmp2;
tmp12 = tmp0 - tmp2;
/* Odd part */
z1 = (INT32) wsptr[7];
z2 = (INT32) wsptr[5];
z3 = (INT32) wsptr[3];
z4 = (INT32) wsptr[1];
tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
+ MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
+ MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
+ MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
+ MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
+ MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
+ MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
/* Final output stage */
outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2,
CONST_BITS+PASS1_BITS+3+1)
& RANGE_MASK];
outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2,
CONST_BITS+PASS1_BITS+3+1)
& RANGE_MASK];
outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0,
CONST_BITS+PASS1_BITS+3+1)
& RANGE_MASK];
outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0,
CONST_BITS+PASS1_BITS+3+1)
& RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
}
/*
* Perform dequantization and inverse DCT on one block of coefficients,
* producing a reduced-size 2x2 output block.
*/
GLOBAL(void)
jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block,
JSAMPARRAY output_buf, JDIMENSION output_col)
{
INT32 tmp0, tmp10, z1;
JCOEFPTR inptr;
ISLOW_MULT_TYPE * quantptr;
int * wsptr;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
int workspace[DCTSIZE*2]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
/* Don't bother to process columns 2,4,6 */
if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6)
continue;
if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 &&
inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) {
/* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */
int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
wsptr[DCTSIZE*0] = dcval;
wsptr[DCTSIZE*1] = dcval;
continue;
}
/* Even part */
z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
tmp10 = z1 << (CONST_BITS+2);
/* Odd part */
z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */
z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */
z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */
z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */
/* Final output stage */
wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2);
wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2);
}
/* Pass 2: process 2 rows from work array, store into output array. */
wsptr = workspace;
for (ctr = 0; ctr < 2; ctr++) {
outptr = output_buf[ctr] + output_col;
/* It's not clear whether a zero row test is worthwhile here ... */
#ifndef NO_ZERO_ROW_TEST
if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) {
/* AC terms all zero */
JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
& RANGE_MASK];
outptr[0] = dcval;
outptr[1] = dcval;
wsptr += DCTSIZE; /* advance pointer to next row */
continue;
}
#endif
/* Even part */
tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2);
/* Odd part */
tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */
+ MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */
+ MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */
+ MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */
/* Final output stage */
outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0,
CONST_BITS+PASS1_BITS+3+2)
& RANGE_MASK];
outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0,
CONST_BITS+PASS1_BITS+3+2)
& RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
}
/*
* Perform dequantization and inverse DCT on one block of coefficients,
* producing a reduced-size 1x1 output block.
*/
GLOBAL(void)
jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block,
JSAMPARRAY output_buf, JDIMENSION output_col)
{
int dcval;
ISLOW_MULT_TYPE * quantptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
SHIFT_TEMPS
/* We hardly need an inverse DCT routine for this: just take the
* average pixel value, which is one-eighth of the DC coefficient.
*/
quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
dcval = DEQUANTIZE(coef_block[0], quantptr[0]);
dcval = (int) DESCALE((INT32) dcval, 3);
output_buf[0][output_col] = range_limit[dcval & RANGE_MASK];
}
#endif /* IDCT_SCALING_SUPPORTED */

View File

@@ -1,53 +1,72 @@
/*
* jinclude.h
*
* Copyright (C) 1991, 1992, 1993, Thomas G. Lane.
* Copyright (C) 1991-1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This is the central file that's #include'd by all the JPEG .c files.
* Its purpose is to provide a single place to fix any problems with
* including the wrong system include files.
* You can edit these declarations if you use a system with nonstandard
* system include files.
* This file exists to provide a single place to fix any problems with
* including the wrong system include files. (Common problems are taken
* care of by the standard jconfig symbols, but on really weird systems
* you may have to edit this file.)
*
* NOTE: this file is NOT intended to be included by applications using the
* JPEG library. Most applications need only include jpeglib.h.
*/
/* Include auto-config file to find out which system include files we need. */
#include "jconfig.h" /* auto configuration options */
#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */
/*
* Normally the __STDC__ macro can be taken as indicating that the system
* include files conform to the ANSI C standard. However, if you are running
* GCC on a machine with non-ANSI system include files, that is not the case.
* In that case change the following, or add -DNONANSI_INCLUDES to your CFLAGS.
* We need the NULL macro and size_t typedef.
* On an ANSI-conforming system it is sufficient to include <stddef.h>.
* Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to
* pull in <sys/types.h> as well.
* Note that the core JPEG library does not require <stdio.h>;
* only the default error handler and data source/destination modules do.
* But we must pull it in because of the references to FILE in jpeglib.h.
* You can remove those references if you want to compile without <stdio.h>.
*/
#ifdef __STDC__
#ifndef NONANSI_INCLUDES
#define INCLUDES_ARE_ANSI /* this is what's tested before including */
#endif
#ifdef HAVE_STDDEF_H
#include <stddef.h>
#endif
/*
* <stdio.h> is included to get the FILE typedef and NULL macro.
* Note that the core portable-JPEG files do not actually do any I/O
* using the stdio library; only the user interface, error handler,
* and file reading/writing modules invoke any stdio functions.
* (Well, we did cheat a bit in jmemmgr.c, but only if MEM_STATS is defined.)
*/
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef NEED_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <stdio.h>
/*
* We need the size_t typedef, which defines the parameter type of malloc().
* In an ANSI-conforming implementation this is provided by <stdio.h>,
* but on non-ANSI systems it's more likely to be in <sys/types.h>.
* On some not-quite-ANSI systems you may find it in <stddef.h>.
* We need memory copying and zeroing functions, plus strncpy().
* ANSI and System V implementations declare these in <string.h>.
* BSD doesn't have the mem() functions, but it does have bcopy()/bzero().
* Some systems may declare memset and memcpy in <memory.h>.
*
* NOTE: we assume the size parameters to these functions are of type size_t.
* Change the casts in these macros if not!
*/
#ifndef INCLUDES_ARE_ANSI /* shouldn't need this if ANSI C */
#include <sys/types.h>
#endif
#ifdef __SASC /* Amiga SAS C provides it in stddef.h. */
#include <stddef.h>
#ifdef NEED_BSD_STRINGS
#include <strings.h>
#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size))
#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size))
#else /* not BSD, assume ANSI/SysV string lib */
#include <string.h>
#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
#endif
/*
@@ -58,12 +77,11 @@
* we always use this SIZEOF() macro in place of using sizeof() directly.
*/
#undef SIZEOF /* in case you included X11/xmd.h */
#define SIZEOF(object) ((size_t) sizeof(object))
/*
* fread() and fwrite() are always invoked through these macros.
* On some systems you may need to twiddle the argument casts.
* The modules that use fread() and fwrite() always invoke them through
* these macros. On some systems you may need to twiddle the argument casts.
* CAUTION: argument order is different from underlying functions!
*/
@@ -71,36 +89,3 @@
((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
#define JFWRITE(file,buf,sizeofbuf) \
((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
/*
* We need the memcpy() and strcmp() functions, plus memory zeroing.
* ANSI and System V implementations declare these in <string.h>.
* BSD doesn't have the mem() functions, but it does have bcopy()/bzero().
* Some systems may declare memset and memcpy in <memory.h>.
*
* NOTE: we assume the size parameters to these functions are of type size_t.
* Change the casts in these macros if not!
*/
#ifdef INCLUDES_ARE_ANSI
#include <string.h>
#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
#else /* not ANSI */
#ifdef BSD
#include <strings.h>
#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size))
#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size))
#else /* not BSD, assume Sys V or compatible */
#include <string.h>
#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
#endif /* BSD */
#endif /* ANSI */
/* Now include the portable JPEG definition files. */
#include "jconfig.h"
#include "jpegdata.h"

View File

@@ -1,157 +0,0 @@
/*
* jmemansi.c (jmemsys.c)
*
* Copyright (C) 1992, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file provides a simple generic implementation of the system-
* dependent portion of the JPEG memory manager. This implementation
* assumes that you have the ANSI-standard library routine tmpfile().
* Also, the problem of determining the amount of memory available
* is shoved onto the user.
*/
#include "jinclude.h"
#include "jmemsys.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare malloc(), free() */
#else
extern void * malloc PP((size_t size));
extern void free PP((void *ptr));
#endif
#ifndef SEEK_SET /* pre-ANSI systems may not define this; */
#define SEEK_SET 0 /* if not, assume 0 is correct */
#endif
static external_methods_ptr methods; /* saved for access to error_exit */
static long total_used; /* total memory requested so far */
/*
* Memory allocation and freeing are controlled by the regular library
* routines malloc() and free().
*/
GLOBAL void *
jget_small (size_t sizeofobject)
{
total_used += sizeofobject;
return (void *) malloc(sizeofobject);
}
GLOBAL void
jfree_small (void * object)
{
free(object);
}
/*
* We assume NEED_FAR_POINTERS is not defined and so the separate entry points
* jget_large, jfree_large are not needed.
*/
/*
* This routine computes the total memory space available for allocation.
* It's impossible to do this in a portable way; our current solution is
* to make the user tell us (with a default value set at compile time).
* If you can actually get the available space, it's a good idea to subtract
* a slop factor of 5% or so.
*/
#ifndef DEFAULT_MAX_MEM /* so can override from makefile */
#define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */
#endif
GLOBAL long
jmem_available (long min_bytes_needed, long max_bytes_needed)
{
return methods->max_memory_to_use - total_used;
}
/*
* Backing store (temporary file) management.
* Backing store objects are only used when the value returned by
* jmem_available is less than the total space needed. You can dispense
* with these routines if you have plenty of virtual memory; see jmemnobs.c.
*/
METHODDEF void
read_backing_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
if (fseek(info->temp_file, file_offset, SEEK_SET))
ERREXIT(methods, "fseek failed on temporary file");
if (JFREAD(info->temp_file, buffer_address, byte_count)
!= (size_t) byte_count)
ERREXIT(methods, "fread failed on temporary file");
}
METHODDEF void
write_backing_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
if (fseek(info->temp_file, file_offset, SEEK_SET))
ERREXIT(methods, "fseek failed on temporary file");
if (JFWRITE(info->temp_file, buffer_address, byte_count)
!= (size_t) byte_count)
ERREXIT(methods, "fwrite failed on temporary file --- out of disk space?");
}
METHODDEF void
close_backing_store (backing_store_ptr info)
{
fclose(info->temp_file);
/* Since this implementation uses tmpfile() to create the file,
* no explicit file deletion is needed.
*/
}
/*
* Initial opening of a backing-store object.
*
* This version uses tmpfile(), which constructs a suitable file name
* behind the scenes. We don't have to use temp_name[] at all;
* indeed, we can't even find out the actual name of the temp file.
*/
GLOBAL void
jopen_backing_store (backing_store_ptr info, long total_bytes_needed)
{
if ((info->temp_file = tmpfile()) == NULL)
ERREXIT(methods, "Failed to create temporary file");
info->read_backing_store = read_backing_store;
info->write_backing_store = write_backing_store;
info->close_backing_store = close_backing_store;
}
/*
* These routines take care of any system-dependent initialization and
* cleanup required. Keep in mind that jmem_term may be called more than
* once.
*/
GLOBAL void
jmem_init (external_methods_ptr emethods)
{
methods = emethods; /* save struct addr for error exit access */
emethods->max_memory_to_use = DEFAULT_MAX_MEM;
total_used = 0;
}
GLOBAL void
jmem_term (void)
{
/* no work */
}

634
jmemdos.c
View File

@@ -1,634 +0,0 @@
/*
* jmemdos.c (jmemsys.c)
*
* Copyright (C) 1992, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file provides an MS-DOS-compatible implementation of the system-
* dependent portion of the JPEG memory manager. Temporary data can be
* stored in extended or expanded memory as well as in regular DOS files.
*
* If you use this file, you must be sure that NEED_FAR_POINTERS is defined
* if you compile in a small-data memory model; it should NOT be defined if
* you use a large-data memory model. This file is not recommended if you
* are using a flat-memory-space 386 environment such as DJGCC or Watcom C.
* Also, this code will NOT work if struct fields are aligned on greater than
* 2-byte boundaries.
*
* Based on code contributed by Ge' Weijers.
*/
/*
* If you have both extended and expanded memory, you may want to change the
* order in which they are tried in jopen_backing_store. On a 286 machine
* expanded memory is usually faster, since extended memory access involves
* an expensive protected-mode-and-back switch. On 386 and better, extended
* memory is usually faster. As distributed, the code tries extended memory
* first (what? not everyone has a 386? :-).
*
* You can disable use of extended/expanded memory entirely by altering these
* definitions or overriding them from the Makefile (eg, -DEMS_SUPPORTED=0).
*/
#ifndef XMS_SUPPORTED
#define XMS_SUPPORTED 1
#endif
#ifndef EMS_SUPPORTED
#define EMS_SUPPORTED 1
#endif
#include "jinclude.h"
#include "jmemsys.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare malloc(), free(), getenv() */
#else
extern void * malloc PP((size_t size));
extern void free PP((void *ptr));
extern char * getenv PP((const char * name));
#endif
#ifdef NEED_FAR_POINTERS
#ifdef __TURBOC__
/* These definitions work for Borland C (Turbo C) */
#include <alloc.h> /* need farmalloc(), farfree() */
#define far_malloc(x) farmalloc(x)
#define far_free(x) farfree(x)
#else
/* These definitions work for Microsoft C and compatible compilers */
#include <malloc.h> /* need _fmalloc(), _ffree() */
#define far_malloc(x) _fmalloc(x)
#define far_free(x) _ffree(x)
#endif
#endif
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
#define READ_BINARY "r"
#else
#define READ_BINARY "rb"
#endif
/*
* Declarations for assembly-language support routines (see jmemdosa.asm).
*
* The functions are declared "far" as are all pointer arguments;
* this ensures the assembly source code will work regardless of the
* compiler memory model. We assume "short" is 16 bits, "long" is 32.
*/
typedef void far * XMSDRIVER; /* actually a pointer to code */
typedef struct { /* registers for calling XMS driver */
unsigned short ax, dx, bx;
void far * ds_si;
} XMScontext;
typedef struct { /* registers for calling EMS driver */
unsigned short ax, dx, bx;
void far * ds_si;
} EMScontext;
EXTERN short far jdos_open PP((short far * handle, char far * filename));
EXTERN short far jdos_close PP((short handle));
EXTERN short far jdos_seek PP((short handle, long offset));
EXTERN short far jdos_read PP((short handle, void far * buffer,
unsigned short count));
EXTERN short far jdos_write PP((short handle, void far * buffer,
unsigned short count));
EXTERN void far jxms_getdriver PP((XMSDRIVER far *));
EXTERN void far jxms_calldriver PP((XMSDRIVER, XMScontext far *));
EXTERN short far jems_available PP((void));
EXTERN void far jems_calldriver PP((EMScontext far *));
static external_methods_ptr methods; /* saved for access to error_exit */
static long total_used; /* total FAR memory requested so far */
/*
* Selection of a file name for a temporary file.
* This is highly system-dependent, and you may want to customize it.
*/
static int next_file_num; /* to distinguish among several temp files */
LOCAL void
select_file_name (char * fname)
{
const char * env;
char * ptr;
FILE * tfile;
/* Keep generating file names till we find one that's not in use */
for (;;) {
/* Get temp directory name from environment TMP or TEMP variable;
* if none, use "."
*/
if ((env = (const char *) getenv("TMP")) == NULL)
if ((env = (const char *) getenv("TEMP")) == NULL)
env = ".";
if (*env == '\0') /* null string means "." */
env = ".";
ptr = fname; /* copy name to fname */
while (*env != '\0')
*ptr++ = *env++;
if (ptr[-1] != '\\' && ptr[-1] != '/')
*ptr++ = '\\'; /* append backslash if not in env variable */
/* Append a suitable file name */
next_file_num++; /* advance counter */
sprintf(ptr, "JPG%03d.TMP", next_file_num);
/* Probe to see if file name is already in use */
if ((tfile = fopen(fname, READ_BINARY)) == NULL)
break;
fclose(tfile); /* oops, it's there; close tfile & try again */
}
}
/*
* Near-memory allocation and freeing are controlled by the regular library
* routines malloc() and free().
*/
GLOBAL void *
jget_small (size_t sizeofobject)
{
/* near data space is NOT counted in total_used */
#ifndef NEED_FAR_POINTERS
total_used += sizeofobject;
#endif
return (void *) malloc(sizeofobject);
}
GLOBAL void
jfree_small (void * object)
{
free(object);
}
/*
* Far-memory allocation and freeing
*/
#ifdef NEED_FAR_POINTERS
GLOBAL void FAR *
jget_large (size_t sizeofobject)
{
total_used += sizeofobject;
return (void FAR *) far_malloc(sizeofobject);
}
GLOBAL void
jfree_large (void FAR * object)
{
far_free(object);
}
#endif
/*
* This routine computes the total memory space available for allocation.
* It's impossible to do this in a portable way; our current solution is
* to make the user tell us (with a default value set at compile time).
* If you can actually get the available space, it's a good idea to subtract
* a slop factor of 5% or so.
*/
#ifndef DEFAULT_MAX_MEM /* so can override from makefile */
#define DEFAULT_MAX_MEM 300000L /* for total usage about 450K */
#endif
GLOBAL long
jmem_available (long min_bytes_needed, long max_bytes_needed)
{
return methods->max_memory_to_use - total_used;
}
/*
* Backing store (temporary file) management.
* Backing store objects are only used when the value returned by
* jmem_available is less than the total space needed. You can dispense
* with these routines if you have plenty of virtual memory; see jmemnobs.c.
*/
/*
* For MS-DOS we support three types of backing storage:
* 1. Conventional DOS files. We access these by direct DOS calls rather
* than via the stdio package. This provides a bit better performance,
* but the real reason is that the buffers to be read or written are FAR.
* The stdio library for small-data memory models can't cope with that.
* 2. Extended memory, accessed per the XMS V2.0 specification.
* 3. Expanded memory, accessed per the LIM/EMS 4.0 specification.
* You'll need copies of those specs to make sense of the related code.
* The specs are available by Internet FTP from SIMTEL20 and its various
* mirror sites; see microsoft/xms20.arc and info/limems41.zip.
*/
/*
* Access methods for a DOS file.
*/
METHODDEF void
read_file_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
if (jdos_seek(info->handle.file_handle, file_offset))
ERREXIT(methods, "seek failed on temporary file");
/* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
if (byte_count > 65535L) /* safety check */
ERREXIT(methods, "MAX_ALLOC_CHUNK should be less than 64K");
if (jdos_read(info->handle.file_handle, buffer_address,
(unsigned short) byte_count))
ERREXIT(methods, "read failed on temporary file");
}
METHODDEF void
write_file_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
if (jdos_seek(info->handle.file_handle, file_offset))
ERREXIT(methods, "seek failed on temporary file");
/* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
if (byte_count > 65535L) /* safety check */
ERREXIT(methods, "MAX_ALLOC_CHUNK should be less than 64K");
if (jdos_write(info->handle.file_handle, buffer_address,
(unsigned short) byte_count))
ERREXIT(methods, "write failed on temporary file --- out of disk space?");
}
METHODDEF void
close_file_store (backing_store_ptr info)
{
jdos_close(info->handle.file_handle); /* close the file */
remove(info->temp_name); /* delete the file */
/* If your system doesn't have remove(), try unlink() instead.
* remove() is the ANSI-standard name for this function, but
* unlink() was more common in pre-ANSI systems.
*/
TRACEMS1(methods, 1, "Closed DOS file %d", info->handle.file_handle);
}
LOCAL boolean
open_file_store (backing_store_ptr info, long total_bytes_needed)
{
short handle;
char tracemsg[TEMP_NAME_LENGTH+40];
select_file_name(info->temp_name);
if (jdos_open((short far *) & handle, (char far *) info->temp_name)) {
/* hack to get around TRACEMS' inability to handle string parameters */
sprintf(tracemsg, "Failed to create temporary file %s", info->temp_name);
ERREXIT(methods, tracemsg); /* jopen_backing_store will fail anyway */
return FALSE;
}
info->handle.file_handle = handle;
info->read_backing_store = read_file_store;
info->write_backing_store = write_file_store;
info->close_backing_store = close_file_store;
/* hack to get around TRACEMS' inability to handle string parameters */
sprintf(tracemsg, "Opened DOS file %d %s", handle, info->temp_name);
TRACEMS(methods, 1, tracemsg);
return TRUE; /* succeeded */
}
/*
* Access methods for extended memory.
*/
#if XMS_SUPPORTED
static XMSDRIVER xms_driver; /* saved address of XMS driver */
typedef union { /* either long offset or real-mode pointer */
long offset;
void far * ptr;
} XMSPTR;
typedef struct { /* XMS move specification structure */
long length;
XMSH src_handle;
XMSPTR src;
XMSH dst_handle;
XMSPTR dst;
} XMSspec;
#define ODD(X) (((X) & 1L) != 0)
METHODDEF void
read_xms_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
XMScontext ctx;
XMSspec spec;
char endbuffer[2];
/* The XMS driver can't cope with an odd length, so handle the last byte
* specially if byte_count is odd. We don't expect this to be common.
*/
spec.length = byte_count & (~ 1L);
spec.src_handle = info->handle.xms_handle;
spec.src.offset = file_offset;
spec.dst_handle = 0;
spec.dst.ptr = buffer_address;
ctx.ds_si = (void far *) & spec;
ctx.ax = 0x0b00; /* EMB move */
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
if (ctx.ax != 1)
ERREXIT(methods, "read from extended memory failed");
if (ODD(byte_count)) {
read_xms_store(info, (void FAR *) endbuffer,
file_offset + byte_count - 1L, 2L);
((char FAR *) buffer_address)[byte_count - 1L] = endbuffer[0];
}
}
METHODDEF void
write_xms_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
XMScontext ctx;
XMSspec spec;
char endbuffer[2];
/* The XMS driver can't cope with an odd length, so handle the last byte
* specially if byte_count is odd. We don't expect this to be common.
*/
spec.length = byte_count & (~ 1L);
spec.src_handle = 0;
spec.src.ptr = buffer_address;
spec.dst_handle = info->handle.xms_handle;
spec.dst.offset = file_offset;
ctx.ds_si = (void far *) & spec;
ctx.ax = 0x0b00; /* EMB move */
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
if (ctx.ax != 1)
ERREXIT(methods, "write to extended memory failed");
if (ODD(byte_count)) {
read_xms_store(info, (void FAR *) endbuffer,
file_offset + byte_count - 1L, 2L);
endbuffer[0] = ((char FAR *) buffer_address)[byte_count - 1L];
write_xms_store(info, (void FAR *) endbuffer,
file_offset + byte_count - 1L, 2L);
}
}
METHODDEF void
close_xms_store (backing_store_ptr info)
{
XMScontext ctx;
ctx.dx = info->handle.xms_handle;
ctx.ax = 0x0a00;
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
TRACEMS1(methods, 1, "Freed XMS handle %u", info->handle.xms_handle);
/* we ignore any error return from the driver */
}
LOCAL boolean
open_xms_store (backing_store_ptr info, long total_bytes_needed)
{
XMScontext ctx;
/* Get address of XMS driver */
jxms_getdriver((XMSDRIVER far *) & xms_driver);
if (xms_driver == NULL)
return FALSE; /* no driver to be had */
/* Get version number, must be >= 2.00 */
ctx.ax = 0x0000;
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
if (ctx.ax < (unsigned short) 0x0200)
return FALSE;
/* Try to get space (expressed in kilobytes) */
ctx.dx = (unsigned short) ((total_bytes_needed + 1023L) >> 10);
ctx.ax = 0x0900;
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
if (ctx.ax != 1)
return FALSE;
/* Succeeded, save the handle and away we go */
info->handle.xms_handle = ctx.dx;
info->read_backing_store = read_xms_store;
info->write_backing_store = write_xms_store;
info->close_backing_store = close_xms_store;
TRACEMS1(methods, 1, "Obtained XMS handle %u", ctx.dx);
return TRUE; /* succeeded */
}
#endif /* XMS_SUPPORTED */
/*
* Access methods for expanded memory.
*/
#if EMS_SUPPORTED
/* The EMS move specification structure requires word and long fields aligned
* at odd byte boundaries. Some compilers will align struct fields at even
* byte boundaries. While it's usually possible to force byte alignment,
* that causes an overall performance penalty and may pose problems in merging
* JPEG into a larger application. Instead we accept some rather dirty code
* here. Note this code would fail if the hardware did not allow odd-byte
* word & long accesses, but all 80x86 CPUs do.
*/
typedef void far * EMSPTR;
typedef union { /* EMS move specification structure */
long length; /* It's easy to access first 4 bytes */
char bytes[18]; /* Misaligned fields in here! */
} EMSspec;
/* Macros for accessing misaligned fields */
#define FIELD_AT(spec,offset,type) (*((type *) &(spec.bytes[offset])))
#define SRC_TYPE(spec) FIELD_AT(spec,4,char)
#define SRC_HANDLE(spec) FIELD_AT(spec,5,EMSH)
#define SRC_OFFSET(spec) FIELD_AT(spec,7,unsigned short)
#define SRC_PAGE(spec) FIELD_AT(spec,9,unsigned short)
#define SRC_PTR(spec) FIELD_AT(spec,7,EMSPTR)
#define DST_TYPE(spec) FIELD_AT(spec,11,char)
#define DST_HANDLE(spec) FIELD_AT(spec,12,EMSH)
#define DST_OFFSET(spec) FIELD_AT(spec,14,unsigned short)
#define DST_PAGE(spec) FIELD_AT(spec,16,unsigned short)
#define DST_PTR(spec) FIELD_AT(spec,14,EMSPTR)
#define EMSPAGESIZE 16384L /* gospel, see the EMS specs */
#define HIBYTE(W) (((W) >> 8) & 0xFF)
#define LOBYTE(W) ((W) & 0xFF)
METHODDEF void
read_ems_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
EMScontext ctx;
EMSspec spec;
spec.length = byte_count;
SRC_TYPE(spec) = 1;
SRC_HANDLE(spec) = info->handle.ems_handle;
SRC_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE);
SRC_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE);
DST_TYPE(spec) = 0;
DST_HANDLE(spec) = 0;
DST_PTR(spec) = buffer_address;
ctx.ds_si = (void far *) & spec;
ctx.ax = 0x5700; /* move memory region */
jems_calldriver((EMScontext far *) & ctx);
if (HIBYTE(ctx.ax) != 0)
ERREXIT(methods, "read from expanded memory failed");
}
METHODDEF void
write_ems_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
EMScontext ctx;
EMSspec spec;
spec.length = byte_count;
SRC_TYPE(spec) = 0;
SRC_HANDLE(spec) = 0;
SRC_PTR(spec) = buffer_address;
DST_TYPE(spec) = 1;
DST_HANDLE(spec) = info->handle.ems_handle;
DST_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE);
DST_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE);
ctx.ds_si = (void far *) & spec;
ctx.ax = 0x5700; /* move memory region */
jems_calldriver((EMScontext far *) & ctx);
if (HIBYTE(ctx.ax) != 0)
ERREXIT(methods, "write to expanded memory failed");
}
METHODDEF void
close_ems_store (backing_store_ptr info)
{
EMScontext ctx;
ctx.ax = 0x4500;
ctx.dx = info->handle.ems_handle;
jems_calldriver((EMScontext far *) & ctx);
TRACEMS1(methods, 1, "Freed EMS handle %u", info->handle.ems_handle);
/* we ignore any error return from the driver */
}
LOCAL boolean
open_ems_store (backing_store_ptr info, long total_bytes_needed)
{
EMScontext ctx;
/* Is EMS driver there? */
if (! jems_available())
return FALSE;
/* Get status, make sure EMS is OK */
ctx.ax = 0x4000;
jems_calldriver((EMScontext far *) & ctx);
if (HIBYTE(ctx.ax) != 0)
return FALSE;
/* Get version, must be >= 4.0 */
ctx.ax = 0x4600;
jems_calldriver((EMScontext far *) & ctx);
if (HIBYTE(ctx.ax) != 0 || LOBYTE(ctx.ax) < 0x40)
return FALSE;
/* Try to allocate requested space */
ctx.ax = 0x4300;
ctx.bx = (unsigned short) ((total_bytes_needed + EMSPAGESIZE-1L) / EMSPAGESIZE);
jems_calldriver((EMScontext far *) & ctx);
if (HIBYTE(ctx.ax) != 0)
return FALSE;
/* Succeeded, save the handle and away we go */
info->handle.ems_handle = ctx.dx;
info->read_backing_store = read_ems_store;
info->write_backing_store = write_ems_store;
info->close_backing_store = close_ems_store;
TRACEMS1(methods, 1, "Obtained EMS handle %u", ctx.dx);
return TRUE; /* succeeded */
}
#endif /* EMS_SUPPORTED */
/*
* Initial opening of a backing-store object.
*/
GLOBAL void
jopen_backing_store (backing_store_ptr info, long total_bytes_needed)
{
/* Try extended memory, then expanded memory, then regular file. */
#if XMS_SUPPORTED
if (open_xms_store(info, total_bytes_needed))
return;
#endif
#if EMS_SUPPORTED
if (open_ems_store(info, total_bytes_needed))
return;
#endif
if (open_file_store(info, total_bytes_needed))
return;
ERREXIT(methods, "Failed to create temporary file");
}
/*
* These routines take care of any system-dependent initialization and
* cleanup required. Keep in mind that jmem_term may be called more than
* once.
*/
GLOBAL void
jmem_init (external_methods_ptr emethods)
{
methods = emethods; /* save struct addr for error exit access */
emethods->max_memory_to_use = DEFAULT_MAX_MEM;
total_used = 0;
next_file_num = 0;
}
GLOBAL void
jmem_term (void)
{
/* Microsoft C, at least in v6.00A, will not successfully reclaim freed
* blocks of size > 32Kbytes unless we give it a kick in the rear, like so:
*/
#ifdef NEED_FHEAPMIN
_fheapmin();
#endif
}

135
jmemdos.h
View File

@@ -1,135 +0,0 @@
/*
* jmemdos.h (jmemsys.h)
*
* Copyright (C) 1992, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This include file defines the interface between the system-independent
* and system-dependent portions of the JPEG memory manager. (The system-
* independent portion is jmemmgr.c; there are several different versions
* of the system-dependent portion, and of this file for that matter.)
*
* This version is suitable for MS-DOS (80x86) implementations.
*/
/*
* These two functions are used to allocate and release small chunks of
* memory (typically the total amount requested through jget_small is
* no more than 20Kb or so). Behavior should be the same as for the
* standard library functions malloc and free; in particular, jget_small
* returns NULL on failure. On most systems, these ARE malloc and free.
* On an 80x86 machine using small-data memory model, these manage near heap.
*/
EXTERN void * jget_small PP((size_t sizeofobject));
EXTERN void jfree_small PP((void * object));
/*
* These two functions are used to allocate and release large chunks of
* memory (up to the total free space designated by jmem_available).
* The interface is the same as above, except that on an 80x86 machine,
* far pointers are used. On other systems these ARE the same as above.
*/
#ifdef NEED_FAR_POINTERS /* typically not needed except on 80x86 */
EXTERN void FAR * jget_large PP((size_t sizeofobject));
EXTERN void jfree_large PP((void FAR * object));
#else
#define jget_large(sizeofobject) jget_small(sizeofobject)
#define jfree_large(object) jfree_small(object)
#endif
/*
* The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may
* be requested in a single call on jget_large (and jget_small for that
* matter, but that case should never come into play). This macro is needed
* to model the 64Kb-segment-size limit of far addressing on 80x86 machines.
* On machines with flat address spaces, any large constant may be used here.
*/
#define MAX_ALLOC_CHUNK 65440L /* leave room for malloc overhead */
/*
* This routine computes the total space available for allocation by
* jget_large. If more space than this is needed, backing store will be used.
* NOTE: any memory already allocated must not be counted.
*
* There is a minimum space requirement, corresponding to the minimum
* feasible buffer sizes; jmemmgr.c will request that much space even if
* jmem_available returns zero. The maximum space needed, enough to hold
* all working storage in memory, is also passed in case it is useful.
*
* It is OK for jmem_available to underestimate the space available (that'll
* just lead to more backing-store access than is really necessary).
* However, an overestimate will lead to failure. Hence it's wise to subtract
* a slop factor from the true available space, especially if jget_small space
* comes from the same pool. 5% should be enough.
*
* On machines with lots of virtual memory, any large constant may be returned.
* Conversely, zero may be returned to always use the minimum amount of memory.
*/
EXTERN long jmem_available PP((long min_bytes_needed, long max_bytes_needed));
/*
* This structure holds whatever state is needed to access a single
* backing-store object. The read/write/close method pointers are called
* by jmemmgr.c to manipulate the backing-store object; all other fields
* are private to the system-dependent backing store routines.
*/
#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */
typedef unsigned short XMSH; /* type of extended-memory handles */
typedef unsigned short EMSH; /* type of expanded-memory handles */
typedef union {
short file_handle; /* DOS file handle if it's a temp file */
XMSH xms_handle; /* handle if it's a chunk of XMS */
EMSH ems_handle; /* handle if it's a chunk of EMS */
} handle_union;
typedef struct backing_store_struct * backing_store_ptr;
typedef struct backing_store_struct {
/* Methods for reading/writing/closing this backing-store object */
METHOD(void, read_backing_store, (backing_store_ptr info,
void FAR * buffer_address,
long file_offset, long byte_count));
METHOD(void, write_backing_store, (backing_store_ptr info,
void FAR * buffer_address,
long file_offset, long byte_count));
METHOD(void, close_backing_store, (backing_store_ptr info));
/* Private fields for system-dependent backing-store management */
/* For the MS-DOS environment, we need: */
handle_union handle; /* reference to backing-store storage object */
char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */
} backing_store_info;
/*
* Initial opening of a backing-store object. This must fill in the
* read/write/close pointers in the object. The read/write routines
* may take an error exit if the specified maximum file size is exceeded.
* (If jmem_available always returns a large value, this routine can just
* take an error exit.)
*/
EXTERN void jopen_backing_store PP((backing_store_ptr info,
long total_bytes_needed));
/*
* These routines take care of any system-dependent initialization and
* cleanup required. The system methods struct address should be saved
* by jmem_init in case an error exit must be taken. jmem_term may assume
* that all requested memory has been freed and that all opened backing-
* store objects have been closed.
* NB: jmem_term may be called more than once, and must behave reasonably
* if that happens.
*/
EXTERN void jmem_init PP((external_methods_ptr emethods));
EXTERN void jmem_term PP((void));

View File

@@ -1,379 +0,0 @@
;
; jmemdosa.asm
;
; Copyright (C) 1992, Thomas G. Lane.
; This file is part of the Independent JPEG Group's software.
; For conditions of distribution and use, see the accompanying README file.
;
; This file contains low-level interface routines to support the MS-DOS
; backing store manager (jmemdos.c). Routines are provided to access disk
; files through direct DOS calls, and to access XMS and EMS drivers.
;
; This file should assemble with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler). If you haven't got
; a compatible assembler, better fall back to jmemansi.c or jmemname.c.
;
; To minimize dependence on the C compiler's register usage conventions,
; we save and restore all 8086 registers, even though most compilers only
; require SI,DI,DS to be preserved. Also, we use only 16-bit-wide return
; values, which everybody returns in AX.
;
; Based on code contributed by Ge' Weijers.
;
JMEMDOSA_TXT segment byte public 'CODE'
assume cs:JMEMDOSA_TXT
public _jdos_open
public _jdos_close
public _jdos_seek
public _jdos_read
public _jdos_write
public _jxms_getdriver
public _jxms_calldriver
public _jems_available
public _jems_calldriver
;
; short far jdos_open (short far * handle, char far * filename)
;
; Create and open a temporary file
;
_jdos_open proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
mov cx,0 ; normal file attributes
lds dx,dword ptr [bp+10] ; get filename pointer
mov ah,3ch ; create file
int 21h
jc open_err ; if failed, return error code
lds bx,dword ptr [bp+6] ; get handle pointer
mov word ptr [bx],ax ; save the handle
xor ax,ax ; return zero for OK
open_err: pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jdos_open endp
;
; short far jdos_close (short handle)
;
; Close the file handle
;
_jdos_close proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
mov bx,word ptr [bp+6] ; file handle
mov ah,3eh ; close file
int 21h
jc close_err ; if failed, return error code
xor ax,ax ; return zero for OK
close_err: pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jdos_close endp
;
; short far jdos_seek (short handle, long offset)
;
; Set file position
;
_jdos_seek proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
mov bx,word ptr [bp+6] ; file handle
mov dx,word ptr [bp+8] ; LS offset
mov cx,word ptr [bp+10] ; MS offset
mov ax,4200h ; absolute seek
int 21h
jc seek_err ; if failed, return error code
xor ax,ax ; return zero for OK
seek_err: pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jdos_seek endp
;
; short far jdos_read (short handle, void far * buffer, unsigned short count)
;
; Read from file
;
_jdos_read proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
mov bx,word ptr [bp+6] ; file handle
lds dx,dword ptr [bp+8] ; buffer address
mov cx,word ptr [bp+12] ; number of bytes
mov ah,3fh ; read file
int 21h
jc read_err ; if failed, return error code
cmp ax,word ptr [bp+12] ; make sure all bytes were read
je read_ok
mov ax,1 ; else return 1 for not OK
jmp short read_err
read_ok: xor ax,ax ; return zero for OK
read_err: pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jdos_read endp
;
; short far jdos_write (short handle, void far * buffer, unsigned short count)
;
; Write to file
;
_jdos_write proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
mov bx,word ptr [bp+6] ; file handle
lds dx,dword ptr [bp+8] ; buffer address
mov cx,word ptr [bp+12] ; number of bytes
mov ah,40h ; write file
int 21h
jc write_err ; if failed, return error code
cmp ax,word ptr [bp+12] ; make sure all bytes written
je write_ok
mov ax,1 ; else return 1 for not OK
jmp short write_err
write_ok: xor ax,ax ; return zero for OK
write_err: pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jdos_write endp
;
; void far jxms_getdriver (XMSDRIVER far *)
;
; Get the address of the XMS driver, or NULL if not available
;
_jxms_getdriver proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
mov ax,4300h ; call multiplex interrupt with
int 2fh ; a magic cookie, hex 4300
cmp al,80h ; AL should contain hex 80
je xmsavail
xor dx,dx ; no XMS driver available
xor ax,ax ; return a nil pointer
jmp short xmsavail_done
xmsavail: mov ax,4310h ; fetch driver address with
int 2fh ; another magic cookie
mov dx,es ; copy address to dx:ax
mov ax,bx
xmsavail_done: les bx,dword ptr [bp+6] ; get pointer to return value
mov word ptr es:[bx],ax
mov word ptr es:[bx+2],dx
pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jxms_getdriver endp
;
; void far jxms_calldriver (XMSDRIVER, XMScontext far *)
;
; The XMScontext structure contains values for the AX,DX,BX,SI,DS registers.
; These are loaded, the XMS call is performed, and the new values of the
; AX,DX,BX registers are written back to the context structure.
;
_jxms_calldriver proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
les bx,dword ptr [bp+10] ; get XMScontext pointer
mov ax,word ptr es:[bx] ; load registers
mov dx,word ptr es:[bx+2]
mov si,word ptr es:[bx+6]
mov ds,word ptr es:[bx+8]
mov bx,word ptr es:[bx+4]
call dword ptr [bp+6] ; call the driver
mov cx,bx ; save returned BX for a sec
les bx,dword ptr [bp+10] ; get XMScontext pointer
mov word ptr es:[bx],ax ; put back ax,dx,bx
mov word ptr es:[bx+2],dx
mov word ptr es:[bx+4],cx
pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jxms_calldriver endp
;
; short far jems_available (void)
;
; Have we got an EMS driver? (this comes straight from the EMS 4.0 specs)
;
_jems_available proc far
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
mov ax,3567h ; get interrupt vector 67h
int 21h
push cs
pop ds
mov di,000ah ; check offs 10 in returned seg
lea si,ASCII_device_name ; against literal string
mov cx,8
cld
repe cmpsb
jne no_ems
mov ax,1 ; match, it's there
jmp short avail_done
no_ems: xor ax,ax ; it's not there
avail_done: pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
ret
ASCII_device_name db "EMMXXXX0"
_jems_available endp
;
; void far jems_calldriver (EMScontext far *)
;
; The EMScontext structure contains values for the AX,DX,BX,SI,DS registers.
; These are loaded, the EMS trap is performed, and the new values of the
; AX,DX,BX registers are written back to the context structure.
;
_jems_calldriver proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
les bx,dword ptr [bp+6] ; get EMScontext pointer
mov ax,word ptr es:[bx] ; load registers
mov dx,word ptr es:[bx+2]
mov si,word ptr es:[bx+6]
mov ds,word ptr es:[bx+8]
mov bx,word ptr es:[bx+4]
int 67h ; call the EMS driver
mov cx,bx ; save returned BX for a sec
les bx,dword ptr [bp+6] ; get EMScontext pointer
mov word ptr es:[bx],ax ; put back ax,dx,bx
mov word ptr es:[bx+2],dx
mov word ptr es:[bx+4],cx
pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jems_calldriver endp
JMEMDOSA_TXT ends
end

1494
jmemmgr.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,251 +0,0 @@
/*
* jmemname.c (jmemsys.c)
*
* Copyright (C) 1992, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file provides a generic implementation of the system-dependent
* portion of the JPEG memory manager. This implementation assumes that
* you must explicitly construct a name for each temp file.
* Also, the problem of determining the amount of memory available
* is shoved onto the user.
*/
#include "jinclude.h"
#include "jmemsys.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare malloc(), free() */
#else
extern void * malloc PP((size_t size));
extern void free PP((void *ptr));
#endif
#ifndef SEEK_SET /* pre-ANSI systems may not define this; */
#define SEEK_SET 0 /* if not, assume 0 is correct */
#endif
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
#define READ_BINARY "r"
#define RW_BINARY "w+"
#else
#define READ_BINARY "rb"
#define RW_BINARY "w+b"
#endif
static external_methods_ptr methods; /* saved for access to error_exit */
static long total_used; /* total memory requested so far */
/*
* Selection of a file name for a temporary file.
* This is system-dependent!
*
* The code as given is suitable for most Unix systems, and it is easily
* modified for most non-Unix systems. Some notes:
* 1. The temp file is created in the directory named by TEMP_DIRECTORY.
* The default value is /usr/tmp, which is the conventional place for
* creating large temp files on Unix. On other systems you'll probably
* want to change the file location. You can do this by editing the
* #define, or by defining TEMP_DIRECTORY in CFLAGS in the Makefile.
* For example, you might say
* CFLAGS= ... '-DTEMP_DIRECTORY="/tmp/"'
* Note that double quotes are needed in the text of the macro.
* With most make systems you have to put single quotes around the
* -D construct to preserve the double quotes.
* (Amiga SAS C has trouble with ":" and such in command-line options,
* so we've put in a special case for the preferred Amiga temp directory.)
*
* 2. If you need to change the file name as well as its location,
* you can override the TEMP_FILE_NAME macro. (Note that this is
* actually a printf format string; it must contain %s and %d.)
* Few people should need to do this.
*
* 3. mktemp() is used to ensure that multiple processes running
* simultaneously won't select the same file names. If your system
* doesn't have mktemp(), define NO_MKTEMP to do it the hard way.
*
* 4. You probably want to define NEED_SIGNAL_CATCHER so that jcmain/jdmain
* will cause the temp files to be removed if you stop the program early.
*/
#ifndef TEMP_DIRECTORY /* so can override from Makefile */
#ifdef AMIGA
#define TEMP_DIRECTORY "JPEGTMP:" /* recommended setting for Amiga */
#else
#define TEMP_DIRECTORY "/usr/tmp/" /* recommended setting for Unix */
#endif
#endif
static int next_file_num; /* to distinguish among several temp files */
#ifdef NO_MKTEMP
#ifndef TEMP_FILE_NAME /* so can override from Makefile */
#define TEMP_FILE_NAME "%sJPG%03d.TMP"
#endif
LOCAL void
select_file_name (char * fname)
{
FILE * tfile;
/* Keep generating file names till we find one that's not in use */
for (;;) {
next_file_num++; /* advance counter */
sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num);
if ((tfile = fopen(fname, READ_BINARY)) == NULL)
break;
fclose(tfile); /* oops, it's there; close tfile & try again */
}
}
#else /* ! NO_MKTEMP */
/* Note that mktemp() requires the initial filename to end in six X's */
#ifndef TEMP_FILE_NAME /* so can override from Makefile */
#define TEMP_FILE_NAME "%sJPG%dXXXXXX"
#endif
LOCAL void
select_file_name (char * fname)
{
next_file_num++; /* advance counter */
sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num);
mktemp(fname); /* make sure file name is unique */
/* mktemp replaces the trailing XXXXXX with a unique string of characters */
}
#endif /* NO_MKTEMP */
/*
* Memory allocation and freeing are controlled by the regular library
* routines malloc() and free().
*/
GLOBAL void *
jget_small (size_t sizeofobject)
{
total_used += sizeofobject;
return (void *) malloc(sizeofobject);
}
GLOBAL void
jfree_small (void * object)
{
free(object);
}
/*
* We assume NEED_FAR_POINTERS is not defined and so the separate entry points
* jget_large, jfree_large are not needed.
*/
/*
* This routine computes the total memory space available for allocation.
* It's impossible to do this in a portable way; our current solution is
* to make the user tell us (with a default value set at compile time).
* If you can actually get the available space, it's a good idea to subtract
* a slop factor of 5% or so.
*/
#ifndef DEFAULT_MAX_MEM /* so can override from makefile */
#define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */
#endif
GLOBAL long
jmem_available (long min_bytes_needed, long max_bytes_needed)
{
return methods->max_memory_to_use - total_used;
}
/*
* Backing store (temporary file) management.
* Backing store objects are only used when the value returned by
* jmem_available is less than the total space needed. You can dispense
* with these routines if you have plenty of virtual memory; see jmemnobs.c.
*/
METHODDEF void
read_backing_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
if (fseek(info->temp_file, file_offset, SEEK_SET))
ERREXIT(methods, "fseek failed on temporary file");
if (JFREAD(info->temp_file, buffer_address, byte_count)
!= (size_t) byte_count)
ERREXIT(methods, "fread failed on temporary file");
}
METHODDEF void
write_backing_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
if (fseek(info->temp_file, file_offset, SEEK_SET))
ERREXIT(methods, "fseek failed on temporary file");
if (JFWRITE(info->temp_file, buffer_address, byte_count)
!= (size_t) byte_count)
ERREXIT(methods, "fwrite failed on temporary file --- out of disk space?");
}
METHODDEF void
close_backing_store (backing_store_ptr info)
{
fclose(info->temp_file); /* close the file */
unlink(info->temp_name); /* delete the file */
/* If your system doesn't have unlink(), use remove() instead.
* remove() is the ANSI-standard name for this function, but if
* your system was ANSI you'd be using jmemansi.c, right?
*/
}
GLOBAL void
jopen_backing_store (backing_store_ptr info, long total_bytes_needed)
{
char tracemsg[TEMP_NAME_LENGTH+40];
select_file_name(info->temp_name);
if ((info->temp_file = fopen(info->temp_name, RW_BINARY)) == NULL) {
/* hack to get around ERREXIT's inability to handle string parameters */
sprintf(tracemsg, "Failed to create temporary file %s", info->temp_name);
ERREXIT(methods, tracemsg);
}
info->read_backing_store = read_backing_store;
info->write_backing_store = write_backing_store;
info->close_backing_store = close_backing_store;
/* hack to get around TRACEMS' inability to handle string parameters */
sprintf(tracemsg, "Using temp file %s", info->temp_name);
TRACEMS(methods, 1, tracemsg);
}
/*
* These routines take care of any system-dependent initialization and
* cleanup required. Keep in mind that jmem_term may be called more than
* once.
*/
GLOBAL void
jmem_init (external_methods_ptr emethods)
{
methods = emethods; /* save struct addr for error exit access */
emethods->max_memory_to_use = DEFAULT_MAX_MEM;
total_used = 0;
next_file_num = 0;
}
GLOBAL void
jmem_term (void)
{
/* no work */
}

View File

@@ -1,7 +1,7 @@
/*
* jmemnobs.c (jmemsys.c)
* jmemnobs.c
*
* Copyright (C) 1992, Thomas G. Lane.
* Copyright (C) 1992-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
@@ -15,50 +15,63 @@
* Note that the max_memory_to_use option is ignored by this implementation.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jmemsys.h"
#include "jpeglib.h"
#include "jmemsys.h" /* import the system-dependent declarations */
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare malloc(), free() */
#else
extern void * malloc PP((size_t size));
extern void free PP((void *ptr));
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
extern void * malloc JPP((size_t size));
extern void free JPP((void *ptr));
#endif
static external_methods_ptr methods; /* saved for access to error_exit */
/*
* Memory allocation and freeing are controlled by the regular library
* routines malloc() and free().
*/
GLOBAL void *
jget_small (size_t sizeofobject)
GLOBAL(void *)
jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
{
return (void *) malloc(sizeofobject);
}
GLOBAL void
jfree_small (void * object)
GLOBAL(void)
jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
{
free(object);
}
/*
* We assume NEED_FAR_POINTERS is not defined and so the separate entry points
* jget_large, jfree_large are not needed.
* "Large" objects are treated the same as "small" ones.
* NB: although we include FAR keywords in the routine declarations,
* this file won't actually work in 80x86 small/medium model; at least,
* you probably won't be able to process useful-size images in only 64KB.
*/
GLOBAL(void FAR *)
jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
{
return (void FAR *) malloc(sizeofobject);
}
GLOBAL(void)
jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
{
free(object);
}
/*
* This routine computes the total memory space available for allocation.
* Here we always say, "we got all you want bud!"
*/
GLOBAL long
jmem_available (long min_bytes_needed, long max_bytes_needed)
GLOBAL(size_t)
jpeg_mem_available (j_common_ptr cinfo, size_t min_bytes_needed,
size_t max_bytes_needed, size_t already_allocated)
{
return max_bytes_needed;
}
@@ -66,31 +79,31 @@ jmem_available (long min_bytes_needed, long max_bytes_needed)
/*
* Backing store (temporary file) management.
* This should never be called and we just error out.
* Since jpeg_mem_available always promised the moon,
* this should never be called and we can just error out.
*/
GLOBAL void
jopen_backing_store (backing_store_ptr info, long total_bytes_needed)
GLOBAL(void)
jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
long total_bytes_needed)
{
ERREXIT(methods, "Backing store not supported");
ERREXIT(cinfo, JERR_NO_BACKING_STORE);
}
/*
* These routines take care of any system-dependent initialization and
* cleanup required. Keep in mind that jmem_term may be called more than
* once.
* cleanup required. Here, there isn't any.
*/
GLOBAL void
jmem_init (external_methods_ptr emethods)
GLOBAL(long)
jpeg_mem_init (j_common_ptr cinfo)
{
methods = emethods; /* save struct addr for error exit access */
emethods->max_memory_to_use = 0;
return 0; /* just set max_memory_to_use to 0 */
}
GLOBAL void
jmem_term (void)
GLOBAL(void)
jpeg_mem_term (j_common_ptr cinfo)
{
/* no work */
}

165
jmemsys.h
View File

@@ -1,78 +1,109 @@
/*
* jmemsys.h
*
* Copyright (C) 1992, Thomas G. Lane.
* Copyright (C) 1992-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This include file defines the interface between the system-independent
* and system-dependent portions of the JPEG memory manager. (The system-
* independent portion is jmemmgr.c; there are several different versions
* of the system-dependent portion, and of this file for that matter.)
* and system-dependent portions of the JPEG memory manager. No other
* modules need include it. (The system-independent portion is jmemmgr.c;
* there are several different versions of the system-dependent portion.)
*
* This is a "generic" skeleton that may need to be modified for particular
* systems. It should be usable as-is on the majority of non-MSDOS machines.
* This file works as-is for the system-dependent memory managers supplied
* in the IJG distribution. You may need to modify it if you write a
* custom memory manager. If system-dependent changes are needed in
* this file, the best method is to #ifdef them based on a configuration
* symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR
* and USE_MAC_MEMMGR.
*/
/* Short forms of external names for systems with brain-damaged linkers. */
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define jpeg_get_small jGetSmall
#define jpeg_free_small jFreeSmall
#define jpeg_get_large jGetLarge
#define jpeg_free_large jFreeLarge
#define jpeg_mem_available jMemAvail
#define jpeg_open_backing_store jOpenBackStore
#define jpeg_mem_init jMemInit
#define jpeg_mem_term jMemTerm
#endif /* NEED_SHORT_EXTERNAL_NAMES */
/*
* These two functions are used to allocate and release small chunks of
* memory (typically the total amount requested through jget_small is
* no more than 20Kb or so). Behavior should be the same as for the
* standard library functions malloc and free; in particular, jget_small
* returns NULL on failure. On most systems, these ARE malloc and free.
* memory. (Typically the total amount requested through jpeg_get_small is
* no more than 20K or so; this will be requested in chunks of a few K each.)
* Behavior should be the same as for the standard library functions malloc
* and free; in particular, jpeg_get_small must return NULL on failure.
* On most systems, these ARE malloc and free. jpeg_free_small is passed the
* size of the object being freed, just in case it's needed.
* On an 80x86 machine using small-data memory model, these manage near heap.
*/
EXTERN void * jget_small PP((size_t sizeofobject));
EXTERN void jfree_small PP((void * object));
EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject));
EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object,
size_t sizeofobject));
/*
* These two functions are used to allocate and release large chunks of
* memory (up to the total free space designated by jmem_available).
* memory (up to the total free space designated by jpeg_mem_available).
* The interface is the same as above, except that on an 80x86 machine,
* far pointers are used. On other systems these ARE the same as above.
* far pointers are used. On most other machines these are identical to
* the jpeg_get/free_small routines; but we keep them separate anyway,
* in case a different allocation strategy is desirable for large chunks.
*/
#ifdef NEED_FAR_POINTERS /* typically not needed except on 80x86 */
EXTERN void FAR * jget_large PP((size_t sizeofobject));
EXTERN void jfree_large PP((void FAR * object));
#else
#define jget_large(sizeofobject) jget_small(sizeofobject)
#define jfree_large(object) jfree_small(object)
#endif
EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo,
size_t sizeofobject));
EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object,
size_t sizeofobject));
/*
* The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may
* be requested in a single call on jget_large (and jget_small for that
* be requested in a single call to jpeg_get_large (and jpeg_get_small for that
* matter, but that case should never come into play). This macro is needed
* to model the 64Kb-segment-size limit of far addressing on 80x86 machines.
* On machines with flat address spaces, any large constant may be used here.
* On those machines, we expect that jconfig.h will provide a proper value.
* On machines with 32-bit flat address spaces, any large constant may be used.
*
* NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type
* size_t and will be a multiple of sizeof(align_type).
*/
#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */
#define MAX_ALLOC_CHUNK 1000000000L
#endif
/*
* This routine computes the total space available for allocation by
* jget_large. If more space than this is needed, backing store will be used.
* NOTE: any memory already allocated must not be counted.
* This routine computes the total space still available for allocation by
* jpeg_get_large. If more space than this is needed, backing store will be
* used. NOTE: any memory already allocated must not be counted.
*
* There is a minimum space requirement, corresponding to the minimum
* feasible buffer sizes; jmemmgr.c will request that much space even if
* jmem_available returns zero. The maximum space needed, enough to hold
* jpeg_mem_available returns zero. The maximum space needed, enough to hold
* all working storage in memory, is also passed in case it is useful.
* Finally, the total space already allocated is passed. If no better
* method is available, cinfo->mem->max_memory_to_use - already_allocated
* is often a suitable calculation.
*
* It is OK for jmem_available to underestimate the space available (that'll
* just lead to more backing-store access than is really necessary).
* It is OK for jpeg_mem_available to underestimate the space available
* (that'll just lead to more backing-store access than is really necessary).
* However, an overestimate will lead to failure. Hence it's wise to subtract
* a slop factor from the true available space, especially if jget_small space
* comes from the same pool. 5% should be enough.
* a slop factor from the true available space. 5% should be enough.
*
* On machines with lots of virtual memory, any large constant may be returned.
* Conversely, zero may be returned to always use the minimum amount of memory.
*/
EXTERN long jmem_available PP((long min_bytes_needed, long max_bytes_needed));
EXTERN(size_t) jpeg_mem_available JPP((j_common_ptr cinfo,
size_t min_bytes_needed,
size_t max_bytes_needed,
size_t already_allocated));
/*
@@ -84,44 +115,84 @@ EXTERN long jmem_available PP((long min_bytes_needed, long max_bytes_needed));
#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */
#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */
typedef unsigned short XMSH; /* type of extended-memory handles */
typedef unsigned short EMSH; /* type of expanded-memory handles */
typedef union {
short file_handle; /* DOS file handle if it's a temp file */
XMSH xms_handle; /* handle if it's a chunk of XMS */
EMSH ems_handle; /* handle if it's a chunk of EMS */
} handle_union;
#endif /* USE_MSDOS_MEMMGR */
#ifdef USE_MAC_MEMMGR /* Mac-specific junk */
#include <Files.h>
#endif /* USE_MAC_MEMMGR */
typedef struct backing_store_struct * backing_store_ptr;
typedef struct backing_store_struct {
/* Methods for reading/writing/closing this backing-store object */
METHOD(void, read_backing_store, (backing_store_ptr info,
JMETHOD(void, read_backing_store, (j_common_ptr cinfo,
backing_store_ptr info,
void FAR * buffer_address,
long file_offset, long byte_count));
METHOD(void, write_backing_store, (backing_store_ptr info,
JMETHOD(void, write_backing_store, (j_common_ptr cinfo,
backing_store_ptr info,
void FAR * buffer_address,
long file_offset, long byte_count));
METHOD(void, close_backing_store, (backing_store_ptr info));
JMETHOD(void, close_backing_store, (j_common_ptr cinfo,
backing_store_ptr info));
/* Private fields for system-dependent backing-store management */
/* For a typical implementation with temp files, we might need: */
#ifdef USE_MSDOS_MEMMGR
/* For the MS-DOS manager (jmemdos.c), we need: */
handle_union handle; /* reference to backing-store storage object */
char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */
#else
#ifdef USE_MAC_MEMMGR
/* For the Mac manager (jmemmac.c), we need: */
short temp_file; /* file reference number to temp file */
FSSpec tempSpec; /* the FSSpec for the temp file */
char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */
#else
/* For a typical implementation with temp files, we need: */
FILE * temp_file; /* stdio reference to temp file */
char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */
#endif
#endif
} backing_store_info;
/*
* Initial opening of a backing-store object. This must fill in the
* read/write/close pointers in the object. The read/write routines
* may take an error exit if the specified maximum file size is exceeded.
* (If jmem_available always returns a large value, this routine can just
* take an error exit.)
* (If jpeg_mem_available always returns a large value, this routine can
* just take an error exit.)
*/
EXTERN void jopen_backing_store PP((backing_store_ptr info,
EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo,
backing_store_ptr info,
long total_bytes_needed));
/*
* These routines take care of any system-dependent initialization and
* cleanup required. The system methods struct address should be saved
* by jmem_init in case an error exit must be taken. jmem_term may assume
* that all requested memory has been freed and that all opened backing-
* store objects have been closed.
* NB: jmem_term may be called more than once, and must behave reasonably
* if that happens.
* cleanup required. jpeg_mem_init will be called before anything is
* allocated (and, therefore, nothing in cinfo is of use except the error
* manager pointer). It should return a suitable default value for
* max_memory_to_use; this may subsequently be overridden by the surrounding
* application. (Note that max_memory_to_use is only important if
* jpeg_mem_available chooses to consult it ... no one else will.)
* jpeg_mem_term may assume that all requested memory has been freed and that
* all opened backing-store objects have been closed.
*/
EXTERN void jmem_init PP((external_methods_ptr emethods));
EXTERN void jmem_term PP((void));
EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo));
EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo));

370
jmorecfg.h Normal file
View File

@@ -0,0 +1,370 @@
/*
* jmorecfg.h
*
* Copyright (C) 1991-1997, Thomas G. Lane.
* Copyright (C) 2009, D. R. Commander.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains additional configuration options that customize the
* JPEG software for special applications or support machine-dependent
* optimizations. Most users will not need to touch this file.
*/
/*
* 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
* few applications need more than 4 channels (maybe 5 for CMYK + alpha
* mask). We recommend 10 as a reasonable compromise; use 4 if you are
* really short on memory. (Each allowed component costs a hundred or so
* bytes of storage, whether actually used in an image or not.)
*/
#define MAX_COMPONENTS 10 /* maximum number of image components */
/*
* Basic data types.
* You may need to change these if you have a machine with unusual data
* type sizes; for example, "char" not 8 bits, "short" not 16 bits,
* or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits,
* but it had better be at least 16.
*/
/* Representation of a single sample (pixel element value).
* We frequently allocate large arrays of these, so it's important to keep
* them small. But if you have memory to burn and access to char or short
* arrays is very slow on your hardware, you might want to change these.
*/
#if BITS_IN_JSAMPLE == 8
/* JSAMPLE should be the smallest type that will hold the values 0..255.
* You can use a signed char by having GETJSAMPLE mask it with 0xFF.
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JSAMPLE;
#define GETJSAMPLE(value) ((int) (value))
#else /* not HAVE_UNSIGNED_CHAR */
typedef char JSAMPLE;
#ifdef __CHAR_UNSIGNED__
#define GETJSAMPLE(value) ((int) (value))
#else
#define GETJSAMPLE(value) ((int) (value) & 0xFF)
#endif /* __CHAR_UNSIGNED__ */
#endif /* HAVE_UNSIGNED_CHAR */
#define MAXJSAMPLE 255
#define CENTERJSAMPLE 128
#endif /* BITS_IN_JSAMPLE == 8 */
#if BITS_IN_JSAMPLE == 12
/* JSAMPLE should be the smallest type that will hold the values 0..4095.
* On nearly all machines "short" will do nicely.
*/
typedef short JSAMPLE;
#define GETJSAMPLE(value) ((int) (value))
#define MAXJSAMPLE 4095
#define CENTERJSAMPLE 2048
#endif /* BITS_IN_JSAMPLE == 12 */
/* Representation of a DCT frequency coefficient.
* This should be a signed value of at least 16 bits; "short" is usually OK.
* Again, we allocate large arrays of these, but you can change to int
* if you have memory to burn and "short" is really slow.
*/
typedef short JCOEF;
/* Compressed datastreams are represented as arrays of JOCTET.
* These must be EXACTLY 8 bits wide, at least once they are written to
* external storage. Note that when using the stdio data source/destination
* managers, this is also the data type passed to fread/fwrite.
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JOCTET;
#define GETJOCTET(value) (value)
#else /* not HAVE_UNSIGNED_CHAR */
typedef char JOCTET;
#ifdef __CHAR_UNSIGNED__
#define GETJOCTET(value) (value)
#else
#define GETJOCTET(value) ((value) & 0xFF)
#endif /* __CHAR_UNSIGNED__ */
#endif /* HAVE_UNSIGNED_CHAR */
/* These typedefs are used for various table entries and so forth.
* They must be at least as wide as specified; but making them too big
* won't cost a huge amount of memory, so we don't provide special
* extraction code like we did for JSAMPLE. (In other words, these
* typedefs live at a different point on the speed/space tradeoff curve.)
*/
/* UINT8 must hold at least the values 0..255. */
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char UINT8;
#else /* not HAVE_UNSIGNED_CHAR */
#ifdef __CHAR_UNSIGNED__
typedef char UINT8;
#else /* not __CHAR_UNSIGNED__ */
typedef short UINT8;
#endif /* __CHAR_UNSIGNED__ */
#endif /* HAVE_UNSIGNED_CHAR */
/* UINT16 must hold at least the values 0..65535. */
#ifdef HAVE_UNSIGNED_SHORT
typedef unsigned short UINT16;
#else /* not HAVE_UNSIGNED_SHORT */
typedef unsigned int UINT16;
#endif /* HAVE_UNSIGNED_SHORT */
/* INT16 must hold at least the values -32768..32767. */
#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */
typedef short INT16;
#endif
/* INT32 must hold at least signed 32-bit values. */
#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
typedef long INT32;
#endif
/* Datatype used for image dimensions. The JPEG standard only supports
* images up to 64K*64K due to 16-bit fields in SOF markers. Therefore
* "unsigned int" is sufficient on all machines. However, if you need to
* handle larger images and you don't mind deviating from the spec, you
* can change this datatype.
*/
typedef unsigned int JDIMENSION;
#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */
/* These macros are used in all function definitions and extern declarations.
* You could modify them if you need to change function linkage conventions;
* in particular, you'll need to do that to make the library a Windows DLL.
* Another application is to make all functions global for use with debuggers
* or code profilers that require it.
*/
/* a function called through method pointers: */
#define METHODDEF(type) static type
/* a function used only in its module: */
#define LOCAL(type) static type
/* a function referenced thru EXTERNs: */
#define GLOBAL(type) type
/* a reference to a GLOBAL function: */
#define EXTERN(type) extern type
/* This macro is used to declare a "method", that is, a function pointer.
* We want to supply prototype parameters if the compiler can cope.
* Note that the arglist parameter must be parenthesized!
* Again, you can customize this if you need special linkage keywords.
*/
#ifdef HAVE_PROTOTYPES
#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
#else
#define JMETHOD(type,methodname,arglist) type (*methodname) ()
#endif
/* Here is the pseudo-keyword for declaring pointers that must be "far"
* on 80x86 machines. Most of the specialized coding for 80x86 is handled
* by just saying "FAR *" where such a pointer is needed. In a few places
* explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol.
*/
#ifdef NEED_FAR_POINTERS
#define FAR far
#else
#define FAR
#endif
/*
* On a few systems, type boolean and/or its values FALSE, TRUE may appear
* in standard header files. Or you may have conflicts with application-
* specific header files that you want to include together with these files.
* Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
*/
#ifndef HAVE_BOOLEAN
typedef int boolean;
#endif
#ifndef FALSE /* in case these macros already exist */
#define FALSE 0 /* values of boolean */
#endif
#ifndef TRUE
#define TRUE 1
#endif
/*
* The remaining options affect code selection within the JPEG library,
* but they don't need to be visible to most applications using the library.
* To minimize application namespace pollution, the symbols won't be
* defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined.
*/
#ifdef JPEG_INTERNALS
#define JPEG_INTERNAL_OPTIONS
#endif
#ifdef JPEG_INTERNAL_OPTIONS
/*
* These defines indicate whether to include various optional functions.
* Undefining some of these symbols will produce a smaller but less capable
* library. Note that you can leave certain source files out of the
* compilation/linking process if you've #undef'd the corresponding symbols.
* (You may HAVE to do that if your compiler doesn't like null source files.)
*/
/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */
/* Capability options common to encoder and decoder: */
#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */
#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */
#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */
/* Encoder capability options: */
#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
/* Note: if you selected 12-bit data precision, it is dangerous to turn off
* ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
* precision, so jchuff.c normally uses entropy optimization to compute
* usable tables for higher precision. If you don't want to do optimization,
* you'll have to supply different default Huffman tables.
* The exact same statements apply for progressive JPEG: the default tables
* don't work for progressive mode. (This may get fixed, however.)
*/
#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */
/* Decoder capability options: */
#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */
#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */
#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */
#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */
#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */
#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */
#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */
/* more capability options later, no doubt */
/*
* Ordering of RGB data in scanlines passed to or from the application.
* If your application wants to deal with data in the order B,G,R, just
* change these macros. You can also deal with formats such as R,G,B,X
* (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing
* the offsets will also change the order in which colormap data is organized.
* RESTRICTIONS:
* 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats.
* 2. These macros only affect RGB<=>YCbCr color conversion, so they are not
* useful if you are using JPEG color spaces other than YCbCr or grayscale.
* 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE
* is not 3 (they don't understand about dummy color components!). So you
* can't use color quantization if you change that value.
*/
#define RGB_RED 0 /* Offset of Red in an RGB scanline element */
#define RGB_GREEN 1 /* Offset of Green */
#define RGB_BLUE 2 /* Offset of Blue */
#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
#define JPEG_NUMCS 12
static const int rgb_red[JPEG_NUMCS] = {
-1, -1, RGB_RED, -1, -1, -1, 0, 0, 2, 2, 3, 1
};
static const int rgb_green[JPEG_NUMCS] = {
-1, -1, RGB_GREEN, -1, -1, -1, 1, 1, 1, 1, 2, 2
};
static const int rgb_blue[JPEG_NUMCS] = {
-1, -1, RGB_BLUE, -1, -1, -1, 2, 2, 0, 0, 1, 3
};
static const int rgb_pixelsize[JPEG_NUMCS] = {
-1, -1, RGB_PIXELSIZE, -1, -1, -1, 3, 4, 3, 4, 4, 4
};
/* Definitions for speed-related optimizations. */
/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying
* two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER
* as short on such a machine. MULTIPLIER must be at least 16 bits wide.
*/
#ifndef MULTIPLIER
#ifndef WITH_SIMD
#define MULTIPLIER int /* type for fastest integer multiply */
#else
#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */
#endif
#endif
/* FAST_FLOAT should be either float or double, whichever is done faster
* by your compiler. (Note that this type is only used in the floating point
* DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.)
* Typically, float is faster in ANSI C compilers, while double is faster in
* pre-ANSI compilers (because they insist on converting to double anyway).
* The code below therefore chooses float if we have ANSI-style prototypes.
*/
#ifndef FAST_FLOAT
#ifdef HAVE_PROTOTYPES
#define FAST_FLOAT float
#else
#define FAST_FLOAT double
#endif
#endif
#endif /* JPEG_INTERNAL_OPTIONS */

Some files were not shown because too many files have changed in this diff Show More