> If it is confirmed a 64bit issue, then the fix may require the openjpeg
> 2000 library to have C99 as a requirement. C99 defines standard types to
> handle such issues without any knowledge of the platform the compiler is
> on. The current library is built with C99 in the Makefile, but it has
> not been made a requirement for other project files to build openjpeg.
Any project which uses Autoconf can easily emulate the C99 int types.
That is what my project, littlecms, and the forthcoming libtiff4 do.
This allows working on older systems.
> I think we can safely deprecate support for compilers that do not
> support at least C99 or C++ standards. If a compiler doesn't support C99
> but does support C++, then we can fallback to C++ standards for now to
> support 64bit types.
A problem is that the popular open source compiler GCC decided not to
provide replacements for the C99 stdint header files if they are
missing so older systems won't be fixed by simply installing/updating
GCC. It took three years (or more) beyond 1999 before updated
operating systems were released with conformant header files. And
then of course there are those who continue to use older Windows
compilers.
Bob
--
Bob Friesenhahn
bfri...@simple.dallas.tx.us, http://www.simplesystems.org/users/bfriesen/
GraphicsMagick Maintainer, http://www.GraphicsMagick.org/
This is what I have so far in opj_headers.h:
...include C90 standard headers
... include openjpeg.h header
/*
==========================================================
C99 Standard: detection and includes
==========================================================
*/
#define OPJ_C99 (__STDC_VERSION__ >= 199901L)
#if OPJ_C99
#include <stddef.h>
#include <stdint.h>
#endif
/*
==========================================================
Non-C99 support and deprecation
==========================================================
*/
#if OPJ_C99 || defined(__cplusplus)
#define INLINE inline
#elif defined(__GNUC__)
#define INLINE __inline__
#elif defined(_MSC_VER)
#define INLINE __inline
#elif defined(__MWERKS__)
#define INLINE inline
#else
#define INLINE /* inline */
#endif
#if !OPJ_C99 && defined(__GNUC__)
#define restrict __restrict__
#elif !OPJ_C99
#define restrict /* restrict */
#endif
#if !OPJ_C99 && defined(__cplusplus)
#include <cstddefs>
#elif !OPJ_C99 && !defined(__cplusplus)
#error Your compiler is neither set to C99 nor C++ standard mode.
32bit int type compatibility assumed.
typedef int ptrdiff_t;
#endif
...include misc defs
..include module headers
While the C99 standard was deleloped, there was an <inttypes.h> header
in early drafts. Later on <stdint.h> was added. The <inttypes.h>
header includes everything that <stdint.h> does and is part of the
final standard.
>
> This is what I have so far in opj_headers.h:
> #define OPJ_C99 (__STDC_VERSION__ >= 199901L)
Unfortunately, __STDC_VERSION__ is useless on systems using GCC when
it comes to deciding which headers and standard types may be
available.
> #if OPJ_C99
> #include <stddef.h>
> #include <stdint.h>
> #endif
The above will fail to work on Solaris 9. If you include <inttypes.h>
rather than <stdint.h> then it will work for Solaris 9. But it won't
work for Solaris 8 or earlier.
>
>> #define OPJ_C99 (__STDC_VERSION__ >= 199901L)
>>
>
> Unfortunately, __STDC_VERSION__ is useless on systems using GCC when
> it comes to deciding which headers and standard types may be
> available.
>
GCC has -std=c99, which is what has been set in the Makefile in the
repository. Can you explain more why you think it is useless?
>
>> #if OPJ_C99
>> #include <stddef.h>
>> #include <stdint.h>
>> #endif
>>
>
> The above will fail to work on Solaris 9. If you include <inttypes.h>
> rather than <stdint.h> then it will work for Solaris 9. But it won't
> work for Solaris 8 or earlier.
>
__STDC_VERSION__ isn't set before Solaris 10 (Sun Studio 10). Solaris 9
and 8 will fallback to C++ standard.
The two main declarations needed are:
size_t
ptrdiff_t
The optional ones are:
uint8_t
uint32_t
int32_t
C89/C90 (default for many compilers) has size_t defined by stdlib.h. C99
and C++ define ptrdiff_t. Instead of worrying about if inttypes.h
exists, we can default uint8_t to unsigned char.
The main reason to use uint8_t is to avoid issues in compilers that try
to change the size of char. The libopenjpeg code now uses 'unsigned
char', so if uint8_t can be detected then that is a plus other it goes
back to the default as it is now, unsigned char.
Popular compilers have nuances about int and unsigned since 64bit
(GCC4.x+/MSVC7+). Both "int" and "unsigned" keywords are stuck to 32bit
terms in those compilers. Hence, libopenjpeg compiles find now on 64bit
systems that have stuck nuances as such. However, there are potential
pointer difference compatibility issues. Also, it probably is not a good
idea to assume other compilers will have these nuances. Instead of a
messy header file to handle all cases of these nuances, we can default
uint32_t and int32_t as mentioned above in uint8_t. Maybe offer an
#ifdef to override these defaults when C99 is not found.
Because part of the headers are provided by the compiler but most of
the headers are provided by the operating system. Since GCC does not
provide <stdint.h> if it is missing then you can't count on GCC's
claim of compliance to know if the header is available. The option
does influence the compiler itself to respect C99 syntax.
>> The above will fail to work on Solaris 9. If you include <inttypes.h>
>> rather than <stdint.h> then it will work for Solaris 9. But it won't
>> work for Solaris 8 or earlier.
>>
> __STDC_VERSION__ isn't set before Solaris 10 (Sun Studio 10). Solaris 9
> and 8 will fallback to C++ standard.
I am not sure how to answer this except to point out that many
different verions of GCC and the Sun compiler will work on Solaris 10.
It is likely that the compiler produces this define. Solaris 10's
assert.h knows about __STDC_VERSION__, but Solaris 9's does not.
> The two main declarations needed are:
>
> size_t
> ptrdiff_t
The size_t is defined by original POSIX so it is available on all Unix
type systems. As far as Solaris goes, I see that ptrdiff_t was added
in Solaris 7.
> The main reason to use uint8_t is to avoid issues in compilers that try
> to change the size of char. The libopenjpeg code now uses 'unsigned
> char', so if uint8_t can be detected then that is a plus other it goes
> back to the default as it is now, unsigned char.
I have yet to encounter a system where 'char' is not 8 bits, although
I have encountered at least one system where char is signed.
> Popular compilers have nuances about int and unsigned since 64bit
> (GCC4.x+/MSVC7+). Both "int" and "unsigned" keywords are stuck to 32bit
> terms in those compilers. Hence, libopenjpeg compiles find now on 64bit
> systems that have stuck nuances as such. However, there are potential
> pointer difference compatibility issues. Also, it probably is not a good
> idea to assume other compilers will have these nuances. Instead of a
> messy header file to handle all cases of these nuances, we can default
> uint32_t and int32_t as mentioned above in uint8_t. Maybe offer an
> #ifdef to override these defaults when C99 is not found.
It is true that normal systems (i.e. other than weird ones like Cray)
will have a 32-bit int. There is value for OpenJPEG to be able to
support really large images so it seems that OpenJPEG should have the
ability to use 64-bit types as well. I have not encountered any
general purpose CPUs which don't support a 64-bit type, although some
of them provide less performance, or don't provide type conversions
to/from an unsigned 64-bit type (an issue with older Visual Studio).
I do realize compilers did support parts of C99 before they conformed to
ISO C99.
> There is value for OpenJPEG to be able to
> support really large images so it seems that OpenJPEG should have the
> ability to use 64-bit types as well. I have not encountered any
> general purpose CPUs which don't support a 64-bit type, although some
> of them provide less performance, or don't provide type conversions
> to/from an unsigned 64-bit type (an issue with older Visual Studio).
>
Right now OpenJPEG seems to only support images with max 2GB dimensions
since the default file formats for j2k, jp2, etc and the transform use
32bit units by the standard. The C99/C++ standards could help to deal
with addressable space beyond 32bit in order to handle images with that
maximum.
ISO C99 helps avoid the need to define messy fringe cases in the
preprocessor, so we need to take a step in that direction.
C standards dictate that sizeof(char) == 1. Thus you can count on char
being 8 bits on anything except maybe a PDP-10. However, yes
signedness is not standardized and is typically whatever is optimal
for the architecture.
Sizeof counts the number of characters, not bits, so sizeof(char) == 1
indicates very little.
I think we should just be the ones to make v2 active.
Anyone tried getting it working with SL yet? We're certainly the ones
to handle that...
> I do have a suggestion. If the only reason to
> switch to v2 is to gain a fully workable opacity component, then the
> current version 1.3 can be used to decode while the v2 can be used to
> encode. I suggest this because v2 is reported to not work with truncated
> streams like v1.3 can do at the time.
This can probably be fixed...
Just getting v2 up to snuff seems like less work than trying to link
v1.3 and v2 into the same app at the same time. :P
I agree. I'll post a patch that merges the latest changes from v1.3
after it was released into v2, so we can get going on this.
I'll post a patch when I clean-up what I've done. Part patch here to
openjpeg, and the rest over there.