📄 gif2x11.c
字号:
for (i = GifFile->SHeight - 1 ; i >= 0 ; i--) { free( ScreenBuffer[ i ] ); } free( ScreenBuffer ); if ( XImageBuffer != (XImage *) NULL ) XDestroyImage( XImageBuffer ); if ( XIcon ) XFreePixmap( XDisplay , XIcon ); if (DGifCloseFile(GifFile) == GIF_ERROR) { PrintGifError(); exit(EXIT_FAILURE); } GifQprintf("\n"); return 0 ;}/******************************************************************************* The real display routine. *******************************************************************************/static void Screen2X(int argc, char **argv, GifRowType *ScreenBuffer, int ScreenWidth, int ScreenHeight){#define WM_DELETE_WINDOW "WM_DELETE_WINDOW" Status rc ; Atom atomKill ; int i, j, c, Size, x, y, MinIntensity, MaxIntensity, AvgIntensity, IconSizeX, IconSizeY; char *XImageData, *XIconData, KeyBuffer[81]; unsigned long ValueMask; GifColorType *ColorMapEntry = ColorMap->Colors; XSetWindowAttributes SetWinAttr; XSizeHints Hints; XEvent Event; XExposeEvent *EEvent; XKeyEvent *KEvent; XComposeStatus Stat; KeySym KS; /* Let find out what are the intensities in the color map: */ MaxIntensity = 0; MinIntensity = 256 * 100; for (i = 0; i < ColorMapSize; i++) { c = ColorMapEntry[i].Red * 30 + ColorMapEntry[i].Green * 59 + ColorMapEntry[i].Blue * 11; if (c > MaxIntensity) MaxIntensity = c; if (c < MinIntensity) MinIntensity = c; } AvgIntensity = (MinIntensity + MaxIntensity) / 2; /* The big trick here is to select the colors so lets do this first: */ if (ForceFlag) AllocateColors2(); else AllocateColors1(); SetWinAttr.background_pixel = BlackPixel( XDisplay, XScreen ); SetWinAttr.border_pixel = WhitePixel( XDisplay, XScreen ); ValueMask = CWBackPixel | CWBorderPixel; Hints.flags = PSize | PMinSize | PMaxSize; Hints.x = Hints.y = 1; Hints.width = Hints.min_width = Hints.max_width = ScreenWidth; Hints.height = Hints.min_height = Hints.max_height = ScreenHeight; if (PosFlag) { Hints.flags |= USPosition; Hints.x = XPosX; Hints.y = XPosY; } XImageWndw = XCreateWindow(XDisplay, Xroot, XPosX, XPosY, ScreenWidth, ScreenHeight, 1, 0, CopyFromParent, CopyFromParent, ValueMask, &SetWinAttr); /* Set up the icon bit map to be a shrinked BW version of the image: */ if (ScreenWidth > ScreenHeight) { IconSizeX = (ICON_SIZE / 8) * 8; IconSizeY = (ScreenHeight * ICON_SIZE) / ScreenWidth; } else { IconSizeY = ICON_SIZE; IconSizeX = (((ScreenWidth * ICON_SIZE) / ScreenHeight) / 8) * 8; } XIconData = (char *) malloc(IconSizeX * IconSizeY / 8); memset(XIconData, 0, IconSizeX * IconSizeY / 8); for (i = 0; i < IconSizeY; i++) { y = (i * ScreenHeight / IconSizeY); Size = i * IconSizeX / 8; for (j = 0; j < IconSizeX; j++) { x = j * ScreenWidth / IconSizeX; c = ScreenBuffer[y][x]; c = ColorMapEntry[c].Red * 30 + ColorMapEntry[c].Green * 59 + ColorMapEntry[c].Blue * 11 > AvgIntensity; XIconData[Size + j / 8] |= c << (j % 8); } } XIcon = XCreateBitmapFromData(XDisplay, XImageWndw, XIconData, IconSizeX, IconSizeY); XSetStandardProperties(XDisplay, XImageWndw, PROGRAM_NAME, PROGRAM_NAME, XIcon, argv, argc, &Hints); free( XIconData ); atomKill = XInternAtom(XDisplay, WM_DELETE_WINDOW, False ); rc = XSetWMProtocols( XDisplay, XImageWndw , &atomKill , 1 ); if ( rc == 0 ) GIF_EXIT("Failed to trap WM_DELETE_WINDOW event" ); XSelectInput(XDisplay, XImageWndw, ExposureMask | KeyPressMask); /* Set out own cursor: */ XCursor = XCreateFontCursor(XDisplay, XC_diamond_cross); XDefineCursor(XDisplay, XImageWndw, XCursor); XMapWindow(XDisplay, XImageWndw); /* Create the image in X format: */ if ((XImageData = (char *) malloc(ScreenWidth * ScreenHeight * BYTESPERPIXEL)) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); for (i = 0; i < ScreenHeight; i++) { y = i * ScreenWidth; for (j = 0; j < ScreenWidth; j++) { XImageData[(y + j)*BYTESPERPIXEL] = XColorTable[ScreenBuffer[i][j]].blue; XImageData[(y + j)*BYTESPERPIXEL+1] = XColorTable[ScreenBuffer[i][j]].green; XImageData[(y + j)*BYTESPERPIXEL+2] = XColorTable[ScreenBuffer[i][j]].red; } } XImageBuffer = XCreateImage(XDisplay, XVisual, DefaultDepth(XDisplay, DefaultScreen(XDisplay)), ZPixmap, 0, XImageData, ScreenWidth, ScreenHeight, BitmapPad(XDisplay), ScreenWidth*BYTESPERPIXEL); while (TRUE) { XNextEvent(XDisplay, &Event); switch (Event.type) { case Expose: EEvent = (XExposeEvent *) &Event; XPutImage(XDisplay, XImageWndw, XGraphContext, XImageBuffer, EEvent->x, EEvent->y, EEvent->x, EEvent->y, EEvent->width, EEvent->height); break; case KeyPress: KEvent = (XKeyEvent *) &Event; XLookupString(KEvent, KeyBuffer, 80, &KS, &Stat); if (KeyBuffer[0] == 3) return; /* if (KeyBuffer[0] == 3) { free(XImageData ); return; } made by XDestroyImage */ break; case ClientMessage : if ( Event.xclient.data.l[0] == atomKill ) return ; break ; } }}/******************************************************************************* Routine to allocate the requested colors from the X server. ** Colors are allocated until success by stripping off the least bits of the ** colors. *******************************************************************************/static void AllocateColors1(void){ int Strip, Msk, i; char Msg[80]; for (i = 0; i < 256; i++) XPixelTable[i] = 0; /* Put reasonable color for out of range. */ for (Strip = 0, Msk = 0xff; Strip < 8; Strip++, Msk <<= 1) { for (i = 0; i < ColorMapSize; i++) { /* Prepare color entry in X format. */ XColorTable[i].red = (ColorMap->Colors[i].Red & Msk) << 8; XColorTable[i].green = (ColorMap->Colors[i].Green & Msk) << 8; XColorTable[i].blue = (ColorMap->Colors[i].Blue & Msk) << 8; XColorTable[i].flags = DoRed | DoGreen | DoBlue; if (XAllocColor(XDisplay, XColorMap, &XColorTable[i])) XPixelTable[i] = XColorTable[i].pixel; else break; } if (i < ColorMapSize) XFreeColors(XDisplay, XColorMap, XPixelTable, i, 0L); else break; } if (Strip == 8) GIF_EXIT("Can not display the image - not enough colors available."); if (Strip != 0) { sprintf(Msg, "%d bits were stripped off the color map.", Strip); GIF_MESSAGE(Msg); }}/******************************************************************************* Routine to allocate the requested colors from the X server. ** Two stages are performed: ** 1. Colors are requested directly. ** 2. If not enough colors can be allocated, the closest current color ** in current table is selected instead. ** This allocation is not optimal as when fail to allocate all colors one ** should pick the right colors to do allocate in order to minimize the ** closest distance from the unallocated ones under some norm (what is a good ** norm for the RGB space?). Improve it if you are bored. *******************************************************************************/static void AllocateColors2(void){ int i, j, Index = 0, Count = 0, XNumOfColors; char Msg[80]; unsigned long D, Distance, AvgDistance = 0, Red, Green, Blue; GifBooleanType Failed = FALSE; XColor *XOldColorTable; for (i = 0; i < 256; i++) { if (i < ColorMapSize) { /* Prepere color entry in X format. */ XColorTable[i].red = ColorMap->Colors[i].Red << 8; XColorTable[i].green = ColorMap->Colors[i].Green << 8; XColorTable[i].blue = ColorMap->Colors[i].Blue << 8; XColorTable[i].flags = DoRed | DoGreen | DoBlue; XPixelTable[i] = -1; /* Not allocated yet. */ } else XPixelTable[i] = 0; /* Put reasonable color for out of range. */ } for (i = 0; i < ColorMapSize; i++) /* Allocate the colors from X: */ if (XAllocColor(XDisplay, XColorMap, &XColorTable[i])) XPixelTable[i] = XColorTable[i].pixel; else Failed = TRUE; if (Failed) { XNumOfColors = DisplayCells(XDisplay, XScreen); XOldColorTable = (XColor *) malloc(sizeof(XColor) * XNumOfColors); for (i = 0; i < XNumOfColors; i++) XOldColorTable[i].pixel = i; XQueryColors(XDisplay, XColorMap, XOldColorTable, XNumOfColors); for (i = 0; i < ColorMapSize; i++) { /* Allocate closest colors from X: */ if (XPixelTable[i] == -1) { /* Failed to allocate this one. */ Distance = 0xffffffff; Red = XColorTable[i].red; Green = XColorTable[i].green; Blue = XColorTable[i].blue; for (j = 0; j < XNumOfColors; j++) { /* Find the closest color in 3D RGB space using L1 norm. */ if ((D = ABS(Red - XOldColorTable[j].red) + ABS(Green - XOldColorTable[j].green) + ABS(Blue - XOldColorTable[j].blue)) < Distance) { Distance = D; Index = j; } } XPixelTable[i] = Index; AvgDistance += Distance; Count++; } } free(XOldColorTable); sprintf(Msg, "Colors will be approximated (average error = %ld).\n", AvgDistance / Count); GIF_MESSAGE(Msg); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -