SDL2 pre-multiplying alpha channel when loading surface on OS X? - c

I'm loading 32 bit RGBA normalmap textures, with a heightmap encoded in the alpha channel, via SDL2 2.0.7 and SDL2_image 2.0.2 on OS X Sierra.
Every pixel in these textures has a non-zero RGB value, encoding a directional normal vector. A directional vector of (0, 0, 0) (i.e. black) is invalid.
And yet, when I load such a texture via SDL2_image, the areas of the texture with an alpha value of 0 also yield RGB values of 0. I think SDL is perhaps pre-multiplying the alpha value for these pixels?
Attached is one of these normalmap textures. You can confirm it is valid by opening the texture in e.g. GIMP and using the color picker on one of the transparent areas. You'll see that, indeed, the transparent areas still have an RGB color that is blue-ish (an encoded normal vector).
And below is a minimal test case illustrating the issue for the attached PNG file:
#include <SDL_image.h>
#include <assert.h>
int main(int argc, char **argv) {
SDL_Surface *s = IMG_Load("green3_2_nm.png");
assert(s);
for (int i = 0; i < s->w * s->h; i++) {
const Uint32 *in = (Uint32 *) (s->pixels + i * s->format->BytesPerPixel);
SDL_Color color;
SDL_GetRGBA(*in, s->format, &color.r, &color.g, &color.b, &color.a);
assert(color.r || color.g || color.b);
}
SDL_FreeSurface(s);
return 0;
}
I'm compiling this test case with gcc $(pkg-config --cflags --libs sdl2_image) test.c
The assertion on line 15 will fail several rows into the image -- i.e. exactly where the alpha value drops to 0.
I have tried both TGA and PNG image formats, but SDL does the same thing to both of them.
Is this a bug in SDL, or am I missing something? I'm curious if folks see this same issue on other platforms as well.
===
Answer: Core Graphics, the default image loading backend for SDL2_image on Apple OS X, does indeed pre-multiply alpha -- always. The solution is to recompile SDL2_image without Core Graphics support, and instead enable libpng, libjpeg, and any other image codecs you require:
./configure \
--disable-imageio \
--disable-png-shared \
--disable-tif-shared \
--disable-jpg-shared \
--disable-webp-shared
On my system, I had to disable Core Graphics (imageio) and also the shared library loading of the other codecs, as you can see. This produced a fat SDL2_image.so that was statically linked against libpng, libjpg, etc.. but worked as expected.

SDL_image is a wrapper around platform-specific image loading code, rather than using the same image loader on all platforms.
Linux: LibPNG, LibJPEG
macOS, iOS: Core Graphics
Windows: WinCodec
This has the advantage of reducing the size of SDL_image, since it doesn't have to ship with any image decoding code, and can instead link dynamically against something that's likely installed on your system already. However, on macOS and iOS, Core Graphics does not support non-premultiplied alpha, so SDL_image has to reverse it.
See: mac-opengl - Re: kCGImageAlphaFirst not implemented (Was: (no subject)) from May 2007 (from the Wayback machine):
Honestly, I wouldn't expect CGBitmapContextCreate() to support non- premultiplied alpha any time soon.
...
I'm not sure if using ImageIO + CoreGraphics was ever really targetted at being used for an image loading scheme for OpenGL applications.
This behavior was discovered in LibSDL bug #838 - OSX SDL darkens colours proportional to increase in alpha and a workaround was introduced in SDL_image changeset 240.
You can see that the workaround merely un-premultiplies the alpha, this is a horribly lossy process.
To address this, you could build your own version of SDL_image on macOS that uses LibPNG. This should be possible just through configuration, you should not have to make any changes to the SDL_image code itself. To do this, use the --disable-imageio option. SDL_image ships with its own copy of the LibPNG code, so you should not need to install LibPNG in order to get this to work.

Related

How can I add a library I downloaded to my C compiler?

I've downloaded CSFML from github and would like to use it in one of my programs. How can I do so? I have a source folder containing some header files. It has three sub-folders.
include
lib
share
CSFML is the C-binding to SFML, which itself is a cross-platform multimedia framework.
Instructions for macOS
The instructions differ depending on the platform. Also whether you want to install them system-wide or have the bindings in a separate folder (e.g. if you play around with different versions of the bindings). There are also many different ways to use it from different development environments or build systems.
Here for example instructions on how to use it on the command line under macOS. The following instructions may therefore not fit your needs exactly, but should at least make the start easier.
Install SFML
Because CSFML is only a C binding to SFML, you must first download and install SFML.
For macOS you can get it from here: https://www.sfml-dev.org/files/SFML-2.5.1-macOS-clang.tar.gz
Due to https://www.sfml-dev.org/tutorials/2.5/start-osx.php#installing-sfml you need to:
Copy the content of Frameworks to /Library/Frameworks
...
Copy the content of extlibs to /Library/Frameworks
Project Structure
There are also different ways to set up a project structure, e.g. you could simply put your include, lib, and share directory in a subdirectory with the actual name csfml.
Then create a test.c file.
Building
You can then build your test program like this:
gcc -Wall -Wextra -I./csfml/include -L./csfml/lib test.c -lcsfml-graphics -lcsfml-window -o test
-I tells the compiler to look for include files in csfml/include, while -L tells the linker to look for the csfml-graphics and csfml-window libraries in the csfml/lib folder.
Dynamic Link Path
If you try to run the ./test executable, it will tell you that it cannot find libcsfml-graphics.dylib. To allow the dynamic linker to find the library at runtime, you can specify the path as follows:
export DYLD_LIBRARY_PATH=./csfml/lib
Then a call to ./test would actually run the program under macOS.
Test Program
For the sake of completeness: a simple test program drawing a red circle with a white border on a black background would look like this:
#include <SFML/Window.h>
#include <SFML/Graphics.h>
int main() {
sfVideoMode mode = {640, 640, 32};
sfRenderWindow *window = sfRenderWindow_create(mode, "csfml quick test", sfResize | sfClose, NULL);
sfCircleShape *circle = sfCircleShape_create();
sfCircleShape_setRadius(circle, 320.0f);
sfCircleShape_setFillColor(circle, sfRed);
sfCircleShape_setOutlineColor(circle, sfWhite);
sfCircleShape_setOutlineThickness(circle, 1.0f);
while (sfRenderWindow_isOpen(window)) {
sfEvent event;
while (sfRenderWindow_pollEvent(window, &event)) {
if (event.type == sfEvtClosed) {
sfRenderWindow_close(window);
}
}
sfRenderWindow_clear(window, sfBlack);
sfRenderWindow_drawCircleShape(window, circle, NULL);
sfRenderWindow_display(window);
}
return 0;
}

RGB pictures detected as YCbCr with libjpeg-turbo

I'm using libjpeg-turbo to open jpeg pictures in a C program. Pictures in RGB colorspace are detected as YCbCr. Grayscale and CMYK colorspaces are correctly detected.
I though about a problem related to 2 different versions of jpeglib.h (where J_COLOR_SPACE enum is defined) or libjpeg conflicting with libjpeg-turbo, but there is just one jpeglib.h on the environment I'm using for compiling libjpeg-turbo and my program.
Any idea much appreciated.

a lib that loads bmp files on a gnome-based system in C

This is a project that our university is asking us to go through (asking for help on third places is not restricted)
We have to build a 3D scene in which objects are mapped with textures.
I'm stuck where I need to load a BMP file's data into the program.
We have to use a library that is already present in the system (forbidden to code it).
My request is :
Using fedora (gnome environment), is there a pre-built library into which a function that loads BMP files and returns a pointer to the payload is existent ?
EDIT : We are forbidden to install any additional libs, the lib must be a pre-built lib of Fedora.
Take a look at the GDK library and the funcion gdk_pixbuf_new_from_file. As you can see in the API you can use:
GdkPixbuf *bmp_pixbuf;
GError *error = NULL;
bmp_pixbuf = gdk_pixbuf_new_from_file ("/tmp/myfile.bmp", &error);
if (bmp_pixbuf == NULL) {
/* Error codes are GDK_PIXBUF_ERROR and G_FILE_ERROR */
}
It's important to check first the BMP support in GDK using:
$ gdk-pixbuf-query-loaders-64 | grep bmp
You need a library like libpixbufloader-bmp.so.
I don't know what library are you using to create the 3D scene, but you can get the raw pixels after load the pixbuf with gdk_pixbuf_get_pixels and then load into a surface.
Hope this help.
freeimage is the package name which does have method to upload bmp image. From online documentation at freeimage project page I can see the API:
DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Load(FREE_IMAGE_FORMAT fif, const char
*filename, int flags FI_DEFAULT(0));
You can
yum install freeimage-devel
on fedora for development. Use this method and link to the library.
I'll reuse a previous answer:
Sean Barrett's stb_image.c is a stand-alone single-file public domain image loader for JPEG, PNG, BMP, TGA, PSD, GIF, HDR and PIC files.

tools to rotate window like cvmovewindow

there is a command to move a window (probably showing image captured from camera) in OpenCV which is cvMoveWindow. But, is there a command in OpenCV which allows window rotation?
if OpenCV does not have one, is there any library doing so?
I've googled for several days but could not find one
You can't rotate the window itself since OpenCV provides no feature for this task, but you can rotate the image instead.
A solution that might be faster than warpAffine is: call cvTranspose() followed by cvFlip() to rotate the image 90 degrees.
The following code uses the C++ interface of OpencV to demonstrate this operation:
cv::Mat src = imread("image.png", 1);
cv::Mat dst;
cv::transpose(src, dst);
cv::flip(dst, dst, 1);
There is no command in opencv to rotate a window. However you can rotate the image and display it in a window. I think it will be hard to find any library which can do this because it has something to do with OS.
Check this link to do away with image rotation

What's the easiest way to display an image in C/Linux? [duplicate]

This question already has answers here:
Easy way to display a continuously updating image in C/Linux
(5 answers)
Closed 5 years ago.
I'm quite comfortable with C for numerical computation, but not for graphical programming. I have a Nx by Ny by 3 RGB matrix in a command-line program for linux (gcc, ubuntu) and I want to pop up a window with it as an image. What's the easiest way to do this? It has to be relatively quick because I'll be updating the image frequently.
Thanks
Here is how to display and image with Gtk2 using C. You can find more information (including a tutorial) on the Gtk2 site.
#include <gtk/gtk.h>
void destroy(void) {
gtk_main_quit();
}
int main (int argc, char** argv) {
GtkWidget* window;
GtkWidget* image;
gtk_init (&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
image = gtk_image_new_from_file(argv[1]);
gtk_signal_connect(GTK_OBJECT (window), "destroy",
GTK_SIGNAL_FUNC (destroy), NULL);
gtk_container_add(GTK_CONTAINER (window), image);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
Here is how to compile it:
gcc -Wall img.c -o img `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0`
You could try using image magick it seems to have a function for displaying an image to an x window with a minimal amount of work. I have used image magick in the past and have been pleased with it. I have not tried this specific function though.
Display function
The C language itself doesn't have any built-in graphics capability. You can use a graphics toolkit like Qt, gtk, wxWidgets, etc. You could also construct an image file (BMP is pretty simple), and then launch (using fork and exec) an application to view it. Ubuntu uses gnome by default, you could fork "gnome-open" with a command-line argument that is the name of the file you created, and gnome-open will then launch whichever application is associated with the file type.
It sounds like maybe you're doing some scientific computing and just need a quick way to display results.
Something like gnuplot may give you better mileage than learning a generic windowing toolkit. It's a general plotting utility and specifically geared towards displaying data sets.
Draw the image to a pixmap, create an X window (or allocate a framebuffer), and write the pixmap to the window.
Or, look at ImageMagick's implementation of the display command.
If you don't mind learning GTK+, then that might be the most straightforward way. Create a window and a drawable, and make the drawable a child of the window. Create a pixmap of your image and draw it to the drawable. Cairo will simplify this, since you'll only need to tweak your image format to make it work.
The cairo graphics library is also a good way to go, see http://cairographics.org/ . It's cross platform, fairly efficient, and will let you work with Gnome/KDE/Windows or just generating image files fairly simply. It's designed for vectors, so also handles clipping, fonts and scaling well.

Resources