GTK+ Draw bitmap as mask using foreground colour - c

I've made a custom font as a bitmap stored in a XPM-image, and want to be able to draw it with a changeable foreground colour to a GdkDrawable-object. Basically, what I want is to use an image as a font and be able to change the colour. Any suggestions how to do this?

It's not exactly the solution I intended at first, but it's a solution and it will have to do until a better one appears.
/* XPM-image containing font consist of 96 (16x6) ASCII-characters starting with space. */
#include "font.xpm"
typedef struct Font {
GdkPixbuf *image[16]; /* Image of font for each colour. */
const int width; /* Grid-width. */
const int height; /* Grid-height */
const int ascent; /* Font ascent from baseline. */
const int char_width[96]; /* Width of each character. */
} Font;
typedef enum TextColor { FONT_BLACK,FONT_BROWN,FONT_YELLOW,FONT_CYAN,FONT_RED,FONT_WHITE } TextColor;
typedef enum TextAlign { ALIGN_LEFT,ALIGN_RIGHT,ALIGN_CENTER } TextAlign;
Font font = {
{0},
7,9,9,
{
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,6,5,5,
5,5,5,5,5,5,5,6,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,6,5,5,
5,5,5,5,5,5,5,6,5,5,5,5,5,5,5,5,
}
};
void load_font(Font *font,const char **font_xpm) {
const char *colors[] = { /* It's not complicated to adjust for more elaborate colour schemes. */
". c #000000", /* Black */
". c #3A2613", /* Brown */
". c #FFFF00", /* Yellow */
". c #00FFFF", /* Cyan */
". c #FF0000", /* Red */
". c #FFFFFF", /* White */
NULL};
int i;
memset(font->image,0,sizeof(GdkPixbuf *)*16);
for(i=0; colors[i]!=NULL; ++i) {
font_xpm[2] = colors[i]; /* Second colour is assumed to be font colour. */
font->image[i] = gdk_pixbuf_new_from_xpm_data(font_xpm);
}
}
int draw_string(Font *font,int x,int y,TextAlign align,TextColor color,const char *str) {
int i,w = 0;
const char *p;
for(p=str; *p; ++p) i = *p-' ',w += i>=0 && i<96? font->char_width[i] : 0;
if(align==ALIGN_RIGHT) x -= w;
else if(align==ALIGN_CENTER) x -= w/2;
for(p=str; *p; ++p) {
i = *p-' ';
if(i>=0 && i<96) {
gdk_draw_pixbuf(pixmap,gc,font->image[(int)color],(i%16)*font->width,(i/16)*font->height,x,y,font->char_width[i],font->height,GDK_RGB_DITHER_NONE,0,0);
x += font->metrics[i];
}
}
return x;
}

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.

Returning SetConsoleTextAttribute colour value from function in c

Currently im trying to call a function to change the color the text background using the windows.h functions to do so. I have done it before but not from another function. Is the problem that the function needs to return the color value somehow or there is just something wrong.
The function was called from another function if that changes anything.
Code Together:
void setColour(HANDLE* hConsole, int ChangeColour, int Red, int Green, int Blue, int Colour) {
CONSOLE_SCREEN_BUFFER_INFOEX info;
info.cbSize = sizeof(info);
GetConsoleScreenBufferInfoEx(hConsole, &info);
info.ColorTable[ChangeColour] = RGB(Red, Green, Blue);
SetConsoleTextAttribute(hConsole, Colour);
}
void mainMenu(WindowProp* Dimensions, HANDLE* hConsole) {
getWindowSize(Dimensions);
clearScreen();
setColour(hConsole, 3, 120, 120, 236, 48);
printf("Set");
int DisplayRowCount, DisplayColumnCount;
for (DisplayRowCount = 0; DisplayRowCount <= Dimensions->Y-1; DisplayRowCount++) {
for (DisplayColumnCount = 0; DisplayColumnCount <= Dimensions->X-1; DisplayColumnCount++) {
printf(" ");
}
}
}
mainMenu called from main:
mainMenu(&WindowP, hConsole);
Ok so I got it fixed. I first decided to declare the HANDLE value in the mainMenu() function and remove the HANDLE pointer.
Secondly, the setColour() function's GetConsoleScreenBufferInfoEx() did get called before changing the color values but wasn't called after modifying the color values thus i needed to call GetConsoleScreenBufferInfoEx() a second time to get the new color values to use.
Fixed Code:
void setColour(HANDLE* hConsole, int ChangeColour, int Red, int Green, int Blue, int Colour) {
CONSOLE_SCREEN_BUFFER_INFOEX info;
info.cbSize = sizeof(info);
GetConsoleScreenBufferInfoEx(hConsole, &info);
info.ColorTable[ChangeColour] = RGB(Red, Green, Blue);
GetConsoleScreenBufferInfoEx(hConsole, &info);
SetConsoleTextAttribute(hConsole, Colour);
}
void mainMenu(WindowProp* Dimensions) {
getWindowSize(Dimensions);
clearScreen();
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
setColour(hConsole, 3, 120, 120, 236, 48);
int DisplayRowCount, DisplayColumnCount;
for (DisplayRowCount = 0; DisplayRowCount <= Dimensions->Y-1; DisplayRowCount++) {
for (DisplayColumnCount = 0; DisplayColumnCount <= Dimensions->X-1; DisplayColumnCount++) {
printf(" ");
}
}
}

How to pass Parameters?

I have been converting convert rose.png -sparse-color barycentric '0,0 black 69,0 white roseModified.png into MagickWand C API.
double arguments[6];
arguments[0] = 0.0;
arguments[1] = 0.0;
// arguments[2] = "black";
arguments[2] = 69.0;
arguments[3] = 0.0;
// arguments[5] = "white";
MagickSparseColorImage(wand0, BarycentricColorInterpolate, 4,arguments);
MagickWriteImage(wand0,"rose_cylinder_22.png");
I don't know how to pass the double argument. click here
for method's defenition.
UPDATE:
Source Image
After I executed convert rose.png -sparse-color barycentric '0,0 black 69,0 white' roseModified.png, I got below Image
I haven't got the output like this with my C program. There might be something with white and black.
For sparse colors, you need to convert the color to doubles for each channel. Depending on how dynamic you need to generate spares color points, you may need to start building basic stack-management methods.
Here's an example. (Mind that this is a quick example, and can be improved on greatly)
#include <stdlib.h>
#include <MagickWand/MagickWand.h>
// Let's create a structure to keep track of arguments.
struct arguments {
size_t count;
double * values;
};
// Set-up structure, and allocate enough memory for all colors.
void allocate_arguments(struct arguments * stack, size_t size)
{
stack->count = 0;
// (2 coords + 3 color channel) * number of colors
stack->values = malloc(sizeof(double) * (size * 5));
}
// Append a double value to structure.
void push_double(struct arguments * stack, double value)
{
stack->values[stack->count++] = value;
}
// Append all parts of a color to structure.
void push_color(struct arguments * stack, PixelWand * color)
{
push_double(stack, PixelGetRed(color));
push_double(stack, PixelGetGreen(color));
push_double(stack, PixelGetBlue(color));
}
#define NUMBER_OF_COLORS 2
int main(int argc, const char * argv[]) {
MagickWandGenesis();
MagickWand * wand;
PixelWand ** colors;
struct arguments A;
allocate_arguments(&A, NUMBER_OF_COLORS);
colors = NewPixelWands(NUMBER_OF_COLORS);
PixelSetColor(colors[0], "black");
PixelSetColor(colors[1], "white");
// 0,0 black
push_double(&A, 0);
push_double(&A, 0);
push_color(&A, colors[0]);
// 69,0 white
push_double(&A, 69);
push_double(&A, 0);
push_color(&A, colors[1]);
// convert rose:
wand = NewMagickWand();
MagickReadImage(wand, "rose:");
// -sparse-color barycentric '0,0 black 69,0 white'
MagickSparseColorImage(wand, BarycentricColorInterpolate, A.count, A.values);
MagickWriteImage(wand, "/tmp/output.png");
MagickWandTerminus();
return 0;
}

How we can give coordinates to direcfb->createsurface function

My requirement is to create a small surface(region) and I want to display a small icon using that surface. So , I want to create a surface having height and width as 100 px * 100 px and for coordinates I don't know which params I have to initialize.
The below code is just for your ref.
DFBSurfaceDescription desc = { 0 };
desc.flags |= DSDESC_CAPS | DSDESC_PIXELFORMAT | DSDESC_WIDTH |DSDESC_HEIGHT;
desc.caps = DSCAPS_VIDEOONLY ; //DSCAPS_VIDEOONLY ; //DSCAPS_SHARED; DSCAPS_SYSTEMONLY;
desc.pixelformat = DSPF_ARGB ;
desc.width = pstBuffer->ui4InWidth;
desc.height = pstBuffer->ui4InHeight;
ret = gpstDfb->CreateSurface( gpstDfb, &desc, &source );
And the desc structure is defined as below :
typedef struct {
DFBSurfaceDescriptionFlags flags; /* field validation */
DFBSurfaceCapabilities caps; /* capabilities */
int width; /* pixel width */
int height; /* pixel height */
DFBSurfacePixelFormat pixelformat; /* pixel format */
struct {
void *data; /* data pointer of existing buffer */
int pitch; /* pitch of buffer */
} preallocated[2];
struct {
const DFBColor *entries;
unsigned int size;
} palette; /* initial palette */
unsigned long resource_id; /* universal resource id, either user specified for general
purpose surfaces or id of layer or window */
DFBSurfaceHintFlags hints; /* usage hints for optimized allocation, format selection etc. */
} DFBSurfaceDescription;

how to stop linux framebuffer to clear automatically while drawing multiple frames

I am writing a gif decoder, This image is an animated image.When I write the first frame, it displays fine. When, I display the second frame, it displays only the changed pixels. Other pixels are automatically changed to black. I don't know why?.
My first frame has the complete picture.
The second frame has again only the pixel changed and it contains the rest of the unchanged pixels.
Now, when I draw the second buffer, it redraws the unchanged pixels also. And the unchanged pixels are drawn as black ( or precisely in monitor I see these unchanged pixels are absent). That's when it has to draw the second frame.It draws the changed pixels( which is correct), but it re-draws the unchanged pixel as well. And this unchanged pixel are seen as a black ( that is no color). I feel it is a refreshing issue. Or It could be something else. Help is appreciated.
Required: It should redraw the complete image.
In short, this is the snippet of my function.
Unfortunately, it clears off the previous display - linux framebuffer.
I want to stop clearning the linux framebuffer.
here is the complete file.
/** This is using the Direct Fb calls here; and is tightly coupled with Linux Framebuffer **/
static int fbfd = 0;
static struct fb_var_screeninfo vinfo;
static struct fb_fix_screeninfo finfo;
static long int screensize = 0;
static char *fbp = 0;
static int x = 0, y = 0;
static long int location = 0;
/** This is a clone to linux Frame buffer, and will be called to dump on Framebuffer **/
char *local_display_mem;
/** local functions **/
static void SetBackground(FrameData *tempInfo);
static void SetPixel(char *fbp, unsigned int x, unsigned int y, Byte red, Byte green, Byte blue);
/** This is the entry function to initialize the display **/
void display_init()
{
// Open the file for reading and writing
fbfd = open("/dev/fb0", O_RDWR);
if (fbfd == -1)
{
perror("cannot open framebuffer device");
exit(1);
}
#ifdef DEBUG
printf("The framebuffer device was opened successfully.\n");
#endif
/** Read the Screen Information **/
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1)
{
perror("Driver error-- reading fixed information");
exit(1);
}
// Get variable screen information
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1)
{
perror("Error reading variable information");
exit(1);
}
#ifdef DEBUG
printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
#endif
// Figure out the size of the screen in bytes
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
// Map the device to memory
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
local_display_mem = (char*)malloc(screensize);
if ((int)fbp == -1)
{
perror("Error: mmap failed\r\n");
exit(1);
}
#ifdef DEBUG
printf("The framebuffer device was mapped to memory successfully.\n");
#endif
printf("Shreyas..Display Initialized..\r\n");
//munmap(fbp, screensize);
//close(fbfd);
}
/** This function is called by gif_read to display the Image **/
void Display(FrameData *FrameInfo)
{
short int ImageStartX = 0;
short int ImageStartY = 0;
int Index = 0;
printf("\r\n INFO: Display Called.\r\n");
while(1)
{
Index = 0;
ImageStartX = (FrameInfo->frameScreenInfo.LeftPosition);
ImageStartY = (FrameInfo->frameScreenInfo.TopPosition);
while(ImageStartY < ((FrameInfo->frameScreenInfo.ImageHeight)+(FrameInfo->frameScreenInfo.TopPosition)))
{
while(ImageStartX < ((FrameInfo->frameScreenInfo.ImageWidth)+(FrameInfo->frameScreenInfo.LeftPosition)))
{
if(FrameInfo->frame[Index] != FrameInfo->transperencyindex)
{
SetPixel(local_display_mem,ImageStartX,ImageStartY,((FrameInfo->CMAP)+(FrameInfo->frame[Index]))->Red,((FrameInfo->CMAP)+(FrameInfo->frame[Index]))->Green,((FrameInfo->CMAP)+(FrameInfo->frame[Index]))->Blue);
}
Index++;
ImageStartX++;
}
ImageStartY++;
ImageStartX=(FrameInfo->frameScreenInfo.LeftPosition);
}
printf("INFO:..Dumping Framebuffer\r\n");
memcpy(fbp,local_display_mem,screensize);
/** Tune this multiplication to meet the right output on the display **/
usleep((FrameInfo->InterFrameDelay)*100000);
if( FrameInfo->DisposalMethod == 2)
{
printf("set the Background\r\n");
SetBackground(FrameInfo);
}
FrameInfo = FrameInfo->Next;
}
}
static void SetBackground(FrameData *tempInfo)
{
unsigned int ImageStartX=0;
unsigned int ImageStartY=0;
ImageStartX=(tempInfo->frameScreenInfo.LeftPosition);
ImageStartY=(tempInfo->frameScreenInfo.TopPosition);
while(ImageStartY<(tempInfo->frameScreenInfo.ImageHeight))
{
while(ImageStartX<(tempInfo->frameScreenInfo.ImageWidth))
{
SetPixel(local_display_mem,ImageStartX,ImageStartY,255,255,255);
ImageStartX++;
}
ImageStartX=(tempInfo->frameScreenInfo.LeftPosition);
ImageStartY++;
}
}
static void SetPixel(char *fbp_lc, unsigned int x, unsigned int y, Byte red, Byte green, Byte blue)
{
//printf("Shreyas..set pixel called\r\n");
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
(y+vinfo.yoffset) * finfo.line_length;
if (vinfo.bits_per_pixel == 32)
{
*(fbp_lc + location) = blue; // Some blue
*(fbp_lc + location + 1) = green; // A little green
*(fbp_lc + location + 2) = red; // A lot of red
*(fbp_lc + location + 3) = 0; // No transparency
//location += 4;
}
else
{ //assume 16bpp
unsigned short int t = red<<11 | green << 5 | blue;
*((unsigned short int*)(fbp_lc + location)) = t;
}
//printf("Shreyas..set pixel exit called\r\n");
}
/** This is windows version of display function, and it works correctly.
void Display(FrameData *FrameInfo)
{
short int ImageStartX=0;
short int ImageStartY=0;
int Index=0;
DisplayCntrl=GetDC(hWnd);
printf("Shreyas.. Display Init is called\r\n");
//display_init();
while(1)
{
Index=0;
ImageStartX=(FrameInfo->frameScreenInfo.LeftPosition);
ImageStartY=(FrameInfo->frameScreenInfo.TopPosition);
while(ImageStartY<((FrameInfo->frameScreenInfo.ImageHeight)+(FrameInfo->frameScreenInfo.TopPosition)))
{
while(ImageStartX<((FrameInfo->frameScreenInfo.ImageWidth)+(FrameInfo->frameScreenInfo.LeftPosition)))
{
if(FrameInfo->frame[Index]!=FrameInfo->transperencyindex)
SetPixel(DisplayCntrl,ImageStartX,ImageStartY,RGB(((FrameInfo->CMAP)+(FrameInfo->frame[Index]))->Red,((FrameInfo->CMAP)+(FrameInfo->frame[Index]))->Green,((FrameInfo->CMAP)+(FrameInfo->frame[Index]))->Blue));
Index++;
ImageStartX++;
}
ImageStartY++;
ImageStartX=(FrameInfo->frameScreenInfo.LeftPosition);
}
Sleep((FrameInfo->InterFrameDelay*10));
WaitForSingleObject(hWnd,10);
if( FrameInfo->DisposalMethod==2)
{
SETBACKGROUND(FrameInfo);
}
FrameInfo=FrameInfo->Next;
}
}
This is the windows version of the same code.
extern hWnd;
HDC DisplayCntrl;
void SETBACKGROUND(FrameData *tempInfo)
{
unsigned int ImageStartX=0;
unsigned int ImageStartY=0;
ImageStartX=(tempInfo->frameScreenInfo.LeftPosition);
ImageStartY=(tempInfo->frameScreenInfo.TopPosition);
while(ImageStartY<(tempInfo->frameScreenInfo.ImageHeight))
{
while(ImageStartX<(tempInfo->frameScreenInfo.ImageWidth))
{
SetPixel(DisplayCntrl,ImageStartX,ImageStartY,RGB(255,255,255));
ImageStartX++;
}
ImageStartX=(tempInfo->frameScreenInfo.LeftPosition);
ImageStartY++;
}
}
void Display(FrameData *FrameInfo)
{
short int ImageStartX=0;
short int ImageStartY=0;
int Index=0;
DisplayCntrl=GetDC(hWnd);
printf("the size of short int is %d",sizeof(short int));
while(1)
{
Index=0;
ImageStartX=(FrameInfo->frameScreenInfo.LeftPosition);
ImageStartY=(FrameInfo->frameScreenInfo.TopPosition);
while(ImageStartY<((FrameInfo->frameScreenInfo.ImageHeight)+(FrameInfo->frameScreenInfo.TopPosition)))
{
while(ImageStartX<((FrameInfo->frameScreenInfo.ImageWidth)+(FrameInfo->frameScreenInfo.LeftPosition)))
{
if(FrameInfo->frame[Index]!=FrameInfo->transperencyindex)
{
SetPixel(DisplayCntrl,ImageStartX,ImageStartY,RGB(((FrameInfo->CMAP)+(FrameInfo->frame[Index]))->Red,((FrameInfo->CMAP)+(FrameInfo->frame[Index]))->Green,((FrameInfo->CMAP)+(FrameInfo->frame[Index]))->Blue));
}
Index++;
ImageStartX++;
}
ImageStartY++;
ImageStartX=(FrameInfo->frameScreenInfo.LeftPosition);
}
Sleep((FrameInfo->InterFrameDelay*10));
WaitForSingleObject(hWnd,10);
if( FrameInfo->DisposalMethod==2)
{
SETBACKGROUND(FrameInfo);
}
FrameInfo=FrameInfo->Next;
}
}
Since you use a local memory buffer local_display_mem, it doesn't matter if somebody would clear the framebuffer - the memcpy will overwrite every pixel.
This means that the condition FrameInfo->frame[Index] != FrameInfo->transperencyindex is always true for some reason since that would cause the algorithm to set each pixel again instead of only updating the changed pixels.

Resources