Ubuntu imagemagick C transparent background - c

hello i'm trying to create a png with transparent background using the C api of imagemagick. I'm working on macosx and this is what i wrote:
UPDATED
i have this function that create me new image:
Image *new_image(Image *composed_image, ImageInfo *composed_image_info){
ExceptionInfo *exception;
MagickPixelPacket *background;
// make it transparent
background->red = QuantumRange;
background->blue = QuantumRange;
background->green = QuantumRange;
background->opacity = QuantumRange;
exception=AcquireExceptionInfo();
composed_image = NewMagickImage(composed_image_info, WIDTH, HEIGHT, background);
if (exception->severity != UndefinedException) CatchException(exception);
if (composed_image == (Image *) NULL) printf("Errore composed \n");
exception = DestroyExceptionInfo(exception);
WriteImage(composed_image_info, composed_image);
return composed_image;
}
then the main main:
int main(int argc, char **argv) {
int images_counter = argc-3;
Image *images[images_counter], *composed_image;
ImageInfo *composed_image_info;
ExceptionInfo *exception;
// create new blank image
composed_image_info = CloneImageInfo((ImageInfo *) NULL);
strcpy(composed_image_info->filename, argv[argc-2]);
composed_image = new_image(composed_image, composed_image_info);
strcpy(composed_image->filename, argv[argc-2]);
// get all the images
for(size_t i = 0; i < images_counter; ++i) images[i] = read_image(argv[i+1]);
// build all the images together
for(size_t i = 0; i < images_counter; ++i) build_image(images[i], composed_image);
// write the image
WriteImage(composed_image_info, composed_image);
// close and return
MagickCoreTerminus();
return(0);
}
on osx it works but when i try it on Ubuntu server the created image is with white background, am i doing something wrong?
thanks

Related

How to use text in EFI graphic mode?

I am super new to creating efi application. My aim is to create a small application in efi, that displays some text on a background. But I am stuck with trying to display text on the display (Great would be to have a custom font, but that is not necessary at this stage). I want the app (also) to run on apple systems (to boot from a usb)
How do I find good documentation on the EFI functions? It seems super hard to find good examples etc.
How can I display a text on a background with EFI?
This is what I got so far. I change the background to a color using the graphics protocol. How do I display a text on it. The Output String doesn't seem to work.
#include "efibind.h"
#include "efidef.h"
#include "efidevp.h"
#include "eficon.h"
#include "efiapi.h"
#include "efierr.h"
#include "efiprot.h"
static EFI_GUID GraphicsOutputProtocolGUID = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
/**
* efi_main - The entry point for the EFI application
* #image: firmware-allocated handle that identifies the image
* #SystemTable: EFI system table
*/
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systemTable) {
EFI_BOOT_SERVICES *bs = systemTable->BootServices;
EFI_STATUS status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *graphicsProtocol;
SIMPLE_TEXT_OUTPUT_INTERFACE *conOut = systemTable->ConOut;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
UINTN SizeOfInfo, sWidth, sHeight;
status = bs->LocateProtocol(&GraphicsOutputProtocolGUID, NULL,
(void**)&graphicsProtocol);
if (EFI_ERROR(status) || graphicsProtocol == NULL) {
conOut->OutputString(conOut, L"Failed to init gfx!\r\n");
return status;
}
conOut->ClearScreen(conOut);
//Switch to current mode so gfx is started.
status = graphicsProtocol->SetMode(graphicsProtocol, graphicsProtocol->Mode->Mode);
if (EFI_ERROR(status)) {
conOut->OutputString(conOut, L"Failed to set default mode!\r\n");
return status;
}
EFI_GRAPHICS_OUTPUT_BLT_PIXEL p;
p.Red = 200;
p.Green = 77;
p.Blue = 13;
graphicsProtocol->QueryMode(graphicsProtocol, graphicsProtocol->Mode->Mode, &SizeOfInfo, &info);
sWidth = info->HorizontalResolution;
sHeight = info->VerticalResolution;
status = graphicsProtocol->Blt(graphicsProtocol, &p, EfiBltVideoFill, 0, 0, 0, 0, sWidth, sHeight, 0);
while (1) {
conOut->OutputString(conOut, L"Some text that I want to display\r\n");
bs->Stall(500000);
}
return EFI_SUCCESS;
}
UEFI supports graphics output. It also supports text output (which can mean either output to a serial console, or text rendered to a graphical console, or both). But there is no defined way to interact between these in a controlled manner.
Applications that provide a graphical environment with text elements (BIOS configuration menu, GRUB) generally do this using their own frameworks to draw text on the graphical console using GRAPHICS_OUTPUT_PROTOCOL.
This is a short example of a text renderer using the font module from LVGL (which can be used standalone, replace #include "../../lv_conf.h" in the lv_font.h file with #define USE_LV_FONT_DEJAVU_20 8) and the Blt method from the GRAPHICS_OUTPUT_PROTOCOL
#include <Uefi.h>
#include <Library\UefiLib.h>
#include <Protocol\GraphicsOutput.h>
#include "lv_font.h"
#define LETTER_SPACE 2
#define WAIT_SECONDS 10
#define FONT &lv_font_dejavu_20
static EFI_BOOT_SERVICES *gBS;
static EFI_RUNTIME_SERVICES *gRT;
static EFI_GRAPHICS_OUTPUT_PROTOCOL *gGOP = (EFI_GRAPHICS_OUTPUT_PROTOCOL *)NULL;
static EFI_GRAPHICS_OUTPUT_BLT_PIXEL gWhite = { 255,255,255,0 };
static void _util_render_glyph(UINT32 x, UINT32 y, CHAR8 letter)
{
UINT32 height;
UINT32 width;
UINT32 pm_x;
UINT32 pm_y;
UINT32 index;
const UINT8* bitmap;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *pixelmap;
if (gGOP == NULL) {
return;
}
height = lv_font_get_height(FONT);
width = lv_font_get_width(FONT, letter);
// glyph is not defined in this font
if (width == 0) {
return;
}
bitmap = lv_font_get_bitmap(FONT, letter);
// using 8 bpp for simplicity
if (EFI_ERROR(gBS->AllocatePool(EfiLoaderData, height * width * sizeof(*pixelmap), (VOID**)&pixelmap))) {
return;
}
gBS->SetMem((VOID*)pixelmap, height * width * sizeof(*pixelmap), 0);
// get the current content of the framebuffer to allow 'transparent' blt operations
gGOP->Blt(gGOP, pixelmap, EfiBltVideoToBltBuffer, x, y, 0, 0, width, height, 0);
for (pm_y = 0; pm_y < height; pm_y++) {
for (pm_x = 0; pm_x < width; pm_x++) {
index = width * pm_y + pm_x;
if (bitmap[index] > 200) {
pixelmap[index].Red = 0;
pixelmap[index].Blue = 0;
pixelmap[index].Green = 0;
pixelmap[index].Reserved = 0;
}
else if (bitmap[index] > 100) {
pixelmap[index].Red = 105;
pixelmap[index].Blue = 105;
pixelmap[index].Green = 105;
pixelmap[index].Reserved = 0;
}
}
}
gGOP->Blt(gGOP, pixelmap, EfiBltBufferToVideo, 0, 0, x, y, width, height, 0);
gBS->FreePool(pixelmap);
}
static void _util_render_text(UINT32 x, UINT32 y, const CHAR8 *string)
{
UINT32 index;
UINTN length;
UINT32 scr_w;
UINT32 scr_h;
UINT32 str_x;
UINT32 gly_w;
UINT32 gly_h;
if (string == NULL) {
return;
}
if (gGOP == NULL) {
return;
}
scr_w = gGOP->Mode->Info->HorizontalResolution;
scr_h = gGOP->Mode->Info->VerticalResolution;
length = AsciiStrnLenS(string, 32);
gly_h = lv_font_get_height(FONT);
// check if the string can be printed
if ((y + gly_h) > scr_h) {
return;
}
if (x > scr_w) {
return;
}
// print the string glyph by glyph
str_x = x;
for (index = 0; index < length; index++) {
// check if the glyph can be printed
gly_w = lv_font_get_width(FONT, string[index]);
if ((str_x + gly_w) > scr_w) {
break;
}
// print the glyph
_util_render_glyph(str_x, y, string[index]);
// calculate the position of the next glyph
str_x += gly_w + LETTER_SPACE;
}
}
static void _util_fill_screen(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *color)
{
if (gGOP == NULL) {
return;
}
gGOP->Blt(gGOP, color, EfiBltVideoFill, 0, 0, 0, 0, gGOP->Mode->Info->HorizontalResolution, gGOP->Mode->Info->VerticalResolution, 0);
}
static void _util_wait(UINT32 seconds)
{
EFI_TIME time;
UINT8 current_second = 255;
UINT32 elapsed_seconds = 0;
//wait for some seconds
while (elapsed_seconds <= WAIT_SECONDS) {
if (!EFI_ERROR(gRT->GetTime(&time, (EFI_TIME_CAPABILITIES*)NULL))) {
if (current_second != time.Second) {
elapsed_seconds++;
current_second = time.Second;
}
}
else {
break;
}
CpuPause();
}
}
EFI_STATUS
EFIAPI
UefiMain(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable)
{
EFI_STATUS eRc;
gBS = SystemTable->BootServices;
gRT = SystemTable->RuntimeServices;
eRc = gBS->LocateProtocol(
&gEfiGraphicsOutputProtocolGuid,
NULL,
(VOID**)&gGOP);
if (EFI_ERROR(eRc) || gGOP == NULL) {
return EFI_SUCCESS;
}
_util_fill_screen(&gWhite);
_util_render_text(0, 0, "HELLO WORLD!");
_util_wait(WAIT_SECONDS);
return EFI_SUCCESS;
}
I tested it on a pc and on a mac it runs on both. Using the tools provided by LVGL on their website you can use any font you want.
If you target MacEFI specifically, you'll need an additional protocol call to force the console into text mode, like this.

IMG_Load: Couldn't open xxx.png

Context: I am currently trying to practice my C skills a little bit with the SDL 2.0.7 and SDL2_image-2.0.2.
Problem: I get an error message during the execution of my program "IMG_Load: Couldn't open xxx.png". The error seems stupid as it is very explicit: "i can't find the image", but as the image is in the appropriate folder... I think I need a fresh eye to spot the stupid mistake.
Platform: Windows 10
IDE: Visual Studio 2017
Steps done to solve the problem:
1) Tried to reduce my code lenght/functionalities to its minimum. Result: Error is still here.
2) I created a new project and copy/pasted the simplified code. Result: On the new project, there is no error, everything is working fine.
3) I compared project's options and the folder. To me they are the same:
It shouldn't be useful but just in case, here is my:
Code sample:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_render.h>
#include "SDL_timer.h"
int main(int argc, char *argv[])
{
printf("argc = %d\n", argc);
for (int i = 0; i < argc; ++i)
{
printf("argv[ %d ] = %s\n", i, argv[i]);
}
SDL_Window* pWindow = NULL;
SDL_Renderer* pRenderer = NULL;
SDL_Texture* pTexture = NULL;
SDL_Surface* pLoadedSurface = NULL;
SDL_Rect* tileClipsArray = NULL;
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER))
{
fprintf(stderr, "Erreur d'initialisation de la SDL : %s\n", SDL_GetError());
}
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if (!(IMG_Init(imgFlags) & imgFlags))
{
printf("IMG_Load: %s\n", IMG_GetError());
}
pWindow = SDL_CreateWindow("TestLoadingImage",
SDL_WINDOWPOS_CENTERED, // initial X position.
SDL_WINDOWPOS_CENTERED, // Initial Y position.
640, // Width, in pixels.
480, // Height, in pixels.
SDL_WINDOW_OPENGL); // Window flags
assert(NULL != pWindow);
//Create renderer for the window
pRenderer = SDL_CreateRenderer(pWindow,
-1, // Index of the rendering driver to initialize, -1 to initialize the first one supporting the requested flags.
SDL_RENDERER_ACCELERATED
| SDL_RENDERER_PRESENTVSYNC); // RendererFlags
assert(NULL != pRenderer);
//Initialize renderer color
SDL_SetRenderDrawColor(pRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
pLoadedSurface = IMG_Load("GroundTiles.png");
if (NULL == pLoadedSurface)
{
printf("IMG_Load: %s\n", IMG_GetError());
assert(NULL != pLoadedSurface);
}
//Create texture from surface pixels
pTexture = SDL_CreateTextureFromSurface(pRenderer, pLoadedSurface);
assert(NULL != pTexture);
//Get image dimensions
const int textureWidth = pLoadedSurface->w;
const int textureHeight = pLoadedSurface->h;
const int tileClipWidth = 128;
const int tileClipHeight = 128;
const int nbLines = textureHeight / tileClipHeight;
const int nbColumns = textureWidth / tileClipWidth;
const int nbTileClips = nbLines + nbColumns;
tileClipsArray = malloc(nbTileClips * sizeof(SDL_Rect));
int tileClipIndex = 0;
for (int tileClipLineIndex = 0; tileClipLineIndex < nbLines; ++tileClipLineIndex)
{
for (int tileClipColumnIndex = 0; tileClipColumnIndex < nbColumns; ++tileClipColumnIndex)
{
tileClipsArray[tileClipIndex].x = tileClipColumnIndex * tileClipWidth;
tileClipsArray[tileClipIndex].y = tileClipLineIndex * tileClipHeight;
tileClipsArray[tileClipIndex].w = tileClipWidth;
tileClipsArray[tileClipIndex].h = tileClipHeight;
++tileClipIndex;
}
}
//Get rid of old loaded surface
SDL_FreeSurface(pLoadedSurface);
pLoadedSurface = NULL;
int canLoop = 1;
SDL_Event event;
int lastUpdate = SDL_GetTicks();
int now = 0;
int timeToSpendPerClip = 5000;
int timeSpentwithThisClip = 0;
int clipToUse = 0;
while (canLoop)
{
now = SDL_GetTicks();
if (now - lastUpdate > 16)
{
timeSpentwithThisClip += now - lastUpdate;
lastUpdate = now;
// We are processing all the events received this frame.
while (SDL_PollEvent(&event))
{
// We need to know what kind of event we are dealing with.
switch (event.type)
{
case SDL_QUIT:
canLoop = 0;
break;
}
}
SDL_RenderClear(pRenderer);
if (timeSpentwithThisClip > timeToSpendPerClip)
{
clipToUse = rand() % 4;
timeSpentwithThisClip = 0;
}
// Set rendering space and render to screen.
SDL_Rect renderQuad;
renderQuad.x = 50;
renderQuad.y = 50;
renderQuad.w = tileClipsArray[clipToUse].w;
renderQuad.h = tileClipsArray[clipToUse].h;
SDL_RenderCopyEx(pRenderer, pTexture, &tileClipsArray[clipToUse], &renderQuad, 0.0, NULL, SDL_FLIP_NONE);
SDL_RenderPresent(pRenderer);
}
}
SDL_DestroyTexture(pTexture);
free(tileClipsArray);
SDL_DestroyRenderer(pRenderer);
pRenderer = NULL;
SDL_DestroyWindow(pWindow);
pWindow = NULL;
IMG_Quit();
SDL_Quit();
return EXIT_SUCCESS;
}
I'm probably going to copy/paste all my files from the project 1 into the project 2, but I would like to understand my mistake!

XGetImage is mangled for chrome, firefox, electron, when using XCompositeRedirectWindow

I am attempting to create a thumbnailer (for i3wm on linux) which generates an icon from a screenshot for all the available windows. The aim being to replicate something like how windows uses Alt-Tab to produce a pane of windows to choose from;
The current prototype uses pygtk to generate the dialog, and it creates thumbnails of the windows in the _NET_CLIENT_LIST using XGetImage where the windows have been redirected using XCompositeRedirectWindow. It works pretty well except for that images captured from windows which are browsers, (e.g. firefox, chrome, electron) are mangled, or wrong;
Basically, tools like xwd, scrot and import don't work for the hidden windows in i3, presumably because they are unmapped. So I have pulled some code together to create the thumbnails. The core of it is based on an example using XCompositeRedirectWindow from X11/extensions/Xcomposite.h from here.
My attempt at creating a short example is here;
https://gist.github.com/tolland/4bb1e97db258b92618adfb783ce66fac
it can be compiled with;
$ gcc example.c -lX11 -lXcomposite -lXrender -lpng -o example
and then to output png files for each of the windows;
$ mkdir -p /tmp/png_out && ./example
will produce pngs for each of the images
window found was 58720312
found window name for 58720312 : build : sudo
filename /tmp/png_out/58720312_test3.png
window found was 79691781
found window name for 79691781 : .xsession-errors - glogg
filename /tmp/png_out/79691781_test3.png
window found was 62914576
found window name for 62914576 : Edit - Stack Overflow - Mozilla Firefox
filename /tmp/png_out/62914576_test3.png
So the code I am currently using to walk the _NET_CLIENT_LIST is this;
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <libpng16/png.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xrender.h>
//Compile hint: gcc -shared -O3 -lX11 -fPIC -Wl,-soname,prtscn -o prtscn.so prtscn.c
typedef int bool;
#define true 1
#define false 0
const int DEBUG = 0;
void getScreen2(const int, const int, const int, const int, const XID);
void write_png_for_image(XImage *image, XID xid, int width, int height,
char *filename);
typedef int (*handler)(Display *, XErrorEvent *);
XID getWindows(Display *display, Window parent, Window window, XID xid,
int depth);
int main() {
Display *display = XOpenDisplay(NULL);
Window root = DefaultRootWindow(display);
uint nwindows;
Window root_return, parent_return, *windows;
Atom a = XInternAtom(display, "_NET_CLIENT_LIST", true);
Atom actualType;
int format;
unsigned long numItems, bytesAfter;
unsigned char *data = 0;
int status = XGetWindowProperty(display, root, a, 0L, (~0L),
false,
AnyPropertyType, &actualType, &format, &numItems, &bytesAfter, &data);
char* window_name_return;
if (status >= Success && numItems) {
long *array = (long*) data;
for (long k = 0; k < numItems; k++) {
Window window = (Window) array[k];
//not finding chrome window name
printf("window found was %d \n", window);
if (XFetchName(display, window, &window_name_return)) {
printf("found window name for %d : %s \n", window,
window_name_return);
}
//XMapWindow(display, parent);
XMapWindow(display, window);
XWindowAttributes attr;
Status status = XGetWindowAttributes(display, window, &attr);
if (status == 0)
printf("Fail to get window attributes!\n");
getScreen2(0, 0, attr.width, attr.height, window);
}
XFree(data);
}
return 0;
}
which calls this function to map the window and call XCompositeRedirectWindow;
void getScreen2(const int xx, const int yy, const int W, const int H,
const XID xid) {
Display *display = XOpenDisplay(NULL);
Window root = DefaultRootWindow(display);
// turn on --sync to force error on correct method
//https://www.x.org/releases/X11R7.6/doc/man/man3/XSynchronize.3.xhtml
XSynchronize(display, True);
int counter = 1;
// select which xid to operate on, the winder or its parent
//XID xwid = fparent;
XID xwid = xid;
// Requests the X server to direct the hierarchy starting at window to off-screen storage
XCompositeRedirectWindow(display, xwid, CompositeRedirectAutomatic);
XWindowAttributes attr;
Status status = XGetWindowAttributes(display, xwid, &attr);
int width = attr.width;
int height = attr.height;
int depth = attr.depth;
Pixmap xc_pixmap = XCompositeNameWindowPixmap(display, xwid);
if (!xc_pixmap) {
printf("xc_pixmap not found\n");
}
//XWriteBitmapFile(display, "test1.xpm", pixmap, W, H, -1, -1);
XRenderPictFormat *format = XRenderFindVisualFormat(display, attr.visual);
XRenderPictureAttributes pa;
pa.subwindow_mode = IncludeInferiors;
Picture picture = XRenderCreatePicture(display, xwid, format,
CPSubwindowMode, &pa);
char buffer[50];
int n;
int file_counter = 1;
n = sprintf(buffer, "/tmp/%d_test%d.xpm", xid, file_counter++);
XWriteBitmapFile(display, buffer, xc_pixmap, W, H, -1, -1);
n = sprintf(buffer, "/tmp/%d_test%d.xpm", xid, file_counter++);
XWriteBitmapFile(display, buffer, xid, W, H, -1, -1);
XImage *image = XGetImage(display, xid, 0, 0, W, H, AllPlanes, ZPixmap);
if (!image) {
printf("XGetImage failed\n");
}
char filename[255];
int n2;
n2 = sprintf(filename, "/tmp/png_out/%d_test%d.png", xid, file_counter++);
printf("filename %s \n", filename);
write_png_for_image(image, xid, W, H, filename);
//XFree(image);
XDestroyImage(image);
XDestroyWindow(display, root);
XCloseDisplay(display);
}
and then this to write out the png;
void write_png_for_image(XImage *image, XID xid, int width, int height,
char *filename) {
int code = 0;
FILE *fp;
png_structp png_ptr;
png_infop png_info_ptr;
png_bytep png_row;
char buffer[50];
int n;
n = sprintf(buffer, filename, xid);
// Open file
fp = fopen(buffer, "wb");
if (fp == NULL) {
fprintf(stderr, "Could not open file for writing\n");
code = 1;
}
// Initialize write structure
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
fprintf(stderr, "Could not allocate write struct\n");
code = 1;
}
// Initialize info structure
png_info_ptr = png_create_info_struct(png_ptr);
if (png_info_ptr == NULL) {
fprintf(stderr, "Could not allocate info struct\n");
code = 1;
}
// Setup Exception handling
if (setjmp(png_jmpbuf (png_ptr))) {
fprintf(stderr, "Error during png creation\n");
code = 1;
}
png_init_io(png_ptr, fp);
// Write header (8 bit colour depth)
png_set_IHDR(png_ptr, png_info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
// Set title
char *title = "Screenshot";
if (title != NULL) {
png_text title_text;
title_text.compression = PNG_TEXT_COMPRESSION_NONE;
title_text.key = "Title";
title_text.text = title;
png_set_text(png_ptr, png_info_ptr, &title_text, 1);
}
png_write_info(png_ptr, png_info_ptr);
// Allocate memory for one row (3 bytes per pixel - RGB)
png_row = (png_bytep) malloc(3 * width * sizeof(png_byte));
unsigned long red_mask = image->red_mask;
unsigned long green_mask = image->green_mask;
unsigned long blue_mask = image->blue_mask;
// Write image data
//int xxx, yyy;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
unsigned long pixel = XGetPixel(image, x, y);
unsigned char blue = pixel & blue_mask;
unsigned char green = (pixel & green_mask) >> 8;
unsigned char red = (pixel & red_mask) >> 16;
png_byte *ptr = &(png_row[x * 3]);
ptr[0] = red;
ptr[1] = green;
ptr[2] = blue;
}
png_write_row(png_ptr, png_row);
}
// End write
png_write_end(png_ptr, NULL);
// Free
fclose(fp);
if (png_info_ptr != NULL)
png_free_data(png_ptr, png_info_ptr, PNG_FREE_ALL, -1);
if (png_ptr != NULL)
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
if (png_row != NULL)
free(png_row);
}
However when the windows is browser based, the image is mangled like so;
Do I need to do something special to get browser windows working?
References;
https://www.talisman.org/~erlkonig/misc/x11-composite-tutorial/
Get a screenshot of a window that is cover or not visible or minimized with Xcomposite extension for X11

Pixel manipulation using sdl

I am trying to manipulate pixel using sdl and manage to read them up now. Below is my sample code. When I print I this printf("\npixelvalue is is : %d",MyPixel); I get values like this
11275780
11275776
etc
I know these are not in hex form but how to manipulate say I want to filter just the blue colors out? Secondly after manipulation how to generate the new image?
#include "SDL.h"
int main( int argc, char* argv[] )
{
SDL_Surface *screen, *image;
SDL_Event event;
Uint8 *keys;
int done = 0;
if (SDL_Init(SDL_INIT_VIDEO) == -1)
{
printf("Can't init SDL: %s\n", SDL_GetError());
exit(1);
}
atexit(SDL_Quit);
SDL_WM_SetCaption("sample1", "app.ico");
/* obtain the SDL surfance of the video card */
screen = SDL_SetVideoMode(640, 480, 24, SDL_HWSURFACE);
if (screen == NULL)
{
printf("Can't set video mode: %s\n", SDL_GetError());
exit(1);
}
printf("Loading here");
/* load BMP file */
image = SDL_LoadBMP("testa.bmp");
Uint32* pixels = (Uint32*)image->pixels;
int width = image->w;
int height = image->h;
printf("Widts is : %d",image->w);
for(int iH = 1; iH<=height; iH++)
for(int iW = 1; iW<=width; iW++)
{
printf("\nIh is : %d",iH);
printf("\nIw is : %d",iW);
Uint32* MyPixel = pixels + ( (iH-1) + image->w ) + iW;
printf("\npixelvalue is is : %d",MyPixel);
}
if (image == NULL) {
printf("Can't load image of tux: %s\n", SDL_GetError());
exit(1);
}
/* Blit image to the video surface */
SDL_BlitSurface(image, NULL, screen, NULL);
SDL_UpdateRect(screen, 0, 0, screen->w, screen->h);
/* free the image if it is no longer needed */
SDL_FreeSurface(image);
/* process the keyboard event */
while (!done)
{
// Poll input queue, run keyboard loop
while ( SDL_PollEvent(&event) )
{
if ( event.type == SDL_QUIT )
{
done = 1;
break;
}
}
keys = SDL_GetKeyState(NULL);
if (keys[SDLK_q])
{
done = 1;
}
// Release CPU for others
SDL_Delay(100);
}
// Release memeory and Quit SDL
SDL_FreeSurface(screen);
SDL_Quit();
return 0;
}
Use SDL_MapRGB and SDL_MapRGBA to sort colors out. SDL will filter it out for you, based on surface format.
Just like this:
Uint32 rawpixel = getpixel(surface, x, y);
Uint8 red, green, blue;
SDL_GetRGB(rawpixel, surface->format, &red, &green, &blue);
You are printing the value of the pointer MyPixel. To get the value you have to dereference the pointer to the pixel value like this: *MyPixel
Then the printf would look like this:
printf("\npixelvalue is : %d and the address of that pixel is: %p\n",*MyPixel , MyPixel);
Other errors:
Your for loops are incorrect. You should loop from 0 to less than width or height, or else you will read uninitialized memory.
You didn't lock the surface. Although you are only reading the pixels and nothing should go wrong it is still not correct.
Test for correctness if the image pointer comes after you are already using the pointer. Put the test right after the initialization.
If I recall correctly I used sdl_gfx for pixel manipulation.
It also contains function like drawing a circle, oval etc.

How to directly query the camera about image luminance/ Skip compentation in OpenCV

I am developing a program in VS 2010 using OpenCV. I want to measure the luminance of every frame that the computer's camera captures. However, the camera's software stabilizes the luminance after 2-3 frames. Eg, if i put my thumb in front of the camera the first frame's luminance is 2 (scale from 0 to 255), but then while keeping my thumb in front of the camera the luminance becomes 7 and the 20 - it is stabilized there for the next frames. So the camera tries to make too dark pictures brighter and too bright pictures darker.
How can i measure the actual luminance without the camera's interference?
My code is:
#ifdef _CH_
#pragma package <opencv>
#endif
#include "stdafx.h"
#include <highgui.h>
#include "cv.h"
#include <stdio.h>
#include <stdlib.h>
#include "..\utilities.h"
int _tmain(int argc, _TCHAR* argv[])
{
FILE *file;
IplImage *img;
IplImage* grayscale_image;
int c, i, j, Luminance = 0, Pixel_Num = 0;
int Avg_Luminance;
int width_step;
int pixel_step;
// allocate memory for an image
// capture from video device #1
CvCapture* capture;
// create a window to display the images
cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE);
// position the window
cvMoveWindow("mainWin", 5, 5);
while(1)
{
if(file = fopen("luminance_value.txt", "w+"))
{
// retrieve the captured frame
capture= cvCaptureFromCAM(1);
img=cvQueryFrame(capture);
grayscale_image = cvCreateImage( cvGetSize(img), 8, 1 );
cvConvertImage( img, grayscale_image );
width_step= grayscale_image->widthStep;
pixel_step= grayscale_image->widthStep/grayscale_image->width;
Pixel_Num = grayscale_image->width * grayscale_image->height;
for(i = 0; i < grayscale_image->height; i++)
{
for(j = 0; j < grayscale_image->width; j++)
{
unsigned char* point = GETPIXELPTRMACRO( grayscale_image, j, i, width_step, pixel_step);
Luminance += point[0];
}
}
Avg_Luminance = Luminance / Pixel_Num;
//Avg_Luminance = cvGetCaptureProperty(capture,CV_CAP_PROP_BRIGHTNESS);
//file = fopen("luminance_value.txt", "w+");
fprintf(file, "%d", Avg_Luminance);
fclose(file);
printf("Avg_Luminance = %d\n", Avg_Luminance);
Luminance = 0;
Pixel_Num = 0;
// show the image in the window
cvShowImage("mainWin", grayscale_image );
cvReleaseCapture(&capture);
// wait 10 ms for a key to be pressed
c=cvWaitKey(10000);
// escape key terminates program
if(c == 27)
break;
}
else
{
continue;
}
}
return 0;
}

Resources