Notes on photo sphere/panoramic EXIF metadata
- Google's EXIF/XMP metadata tag specification for panoramic images
- Panorama images with sky are to have a negative value for the CroppedAreaTopPixels tag. (The panoramic viewer of Facebook ignores the value altogether, though, and assumes the horizon in the middle of the picture.)
- If a camera or software normally produces panoramic images with cylindrical projection, then doing a vertical capture actually produces a transverse cylindrical image. There is no standardized value for the EXIF ProjectionType field to cover this. (One option is to reproject them to equirectangular — which, again, is not very well supported.)
- Facebook's document on what tags to set
- The Facebook web interface insists that FullPanoHeightPixels be half the size of FullPanoWidthPixels. Else you get “no new photos were uploaded”.
Posted 2024-11-21 09:11 / Tags: Photo. / link
Error condition propagation in the Linux kernel source
At the request of Philip Fry on a comment posted by me on David Zeuthen's blog post “Writing a C library, part 3”, I am posting a short overview of error conveyance in the Linux kernel (source).
David Zeuthen wrote in his blog post about the integer variable errno: “For simple libraries just using libc's errno is often [the] simplest approach to handling run-time errors (since it's thread-safe and every C programmer knows it)”.
A global variable — is it simple? Yes, I could agree on that. Thread-safe? Yes, contemporary implementations of C-derived environments that support threads, in other words, POSIX, have redefined errno such that it has a per-thread-specific location. It may look something like:
extern int *errno_location(void);
#define errno (*errno_location())
Whereby errno_location is a function with deeper magic that just eventually returns a pointer to a thread-unique location. The indirection via the pointer is necessary because errno is supposed to be an lvalue that can be assigned to. Due to the new macro, I am reluctant to still call it a “variable” in this context, since it is not a named variable anymore, but a dereference of a function's return value.
Anyhow, it does retain errno's properties: it is, in essence, still a “global variable”, or to be more exact, an object with static storage duration with added global scope/visibility. The pro and contra for such objects I need not repeat here.
So my replying comment to David's posting was: “It may be safe from other threads due to TLS [thread-local storage], but it is still a object with global scope, which results in having to longwindingly save and restore errno across calls to other opaque library functions. The Linux kernel in contrast shows how to do without such a global.”. An example to the necessary save-and-restore cycle is this piece of common housekeeping done just before forking:
bool all_or_nothing(int *p)
{
unsigned int i;
for (i = 0; i < PIPE_PAIRS * 2; ++i)
p[i] = -1;
if (build_pipes(p) != 0) {
saved_errno = errno;
kill_pipes(p); /* calls close() */
errno = saved_errno;
return false;
}
return true;
}
The handling in the error path is somewhat cumbersome, because close can set errno. This prompted me to present the case of how the Linux kernel internally conveys error conditions. One code example:
int all_or_nothing(int *p)
{
unsigned int i;
int ret;
for (i = 0; i < PIPE_PAIRS * 2; ++i)
p[i] = -1;
ret = build_pipes(p);
if (ret < 0)
kill_pipes(p);
return ret;
}
Error conveyance in the Linux kernel generally follows this abstract ruleset:
- Error conditions are conveyed through a function's return value rather than a global.
- If the range of (all possible) error values does not collide with the function's normal computational “output”, the return value domain may be overloaded.
Posted 2011-07-06 07:07 / Tags: Kernel, Linux. / link