#ifdef FLJ #undef MOD_BACKGROUNDIMAGE #endif #include #include "jpeg/jpeglib.h" #include #include #ifdef MOD_BACKGROUNDIMAGE #include #include "putty.h" #include "terminal.h" #include "kitty_image.h" extern Conf *conf ;// extern Config cfg; //extern int offset_width, offset_height ; //extern int font_width, font_height ; #ifndef NCFGCOLOURS #define NCFGCOLOURS 24 #endif #ifndef NEXTCOLOURS #define NEXTCOLOURS 240 #endif #ifndef NALLCOLOURS #define NALLCOLOURS (NCFGCOLOURS + NEXTCOLOURS) #endif //extern COLORREF colours[NALLCOLOURS] ; extern HWND MainHwnd ; int stricmp(const char *s1, const char *s2) ; int GetSessionField( const char * session_in, const char * folder_in, const char * field, char * result ) ; int get_param( const char * val ) ; int return_offset_height(void) ; int return_offset_width(void) ; int return_font_height(void) ; int return_font_width(void) ; COLORREF return_colours258(void) ; static BOOL (WINAPI * pAlphaBlend)( HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION ) = 0 ; //static HWND hwnd; HDC textdc = NULL ; HBITMAP textbm = NULL ; COLORREF colorinpixel; HDC colorinpixeldc = NULL ; HBITMAP colorinpixelbm = NULL; HDC backgrounddc = NULL ; HBITMAP backgroundbm = NULL ; HDC backgroundblenddc = NULL ; HBITMAP backgroundblendbm = NULL; BOOL bBgRelToTerm; bool resizing; RECT size_before; #ifdef DLL #define TARGET extern __declspec(dllexport) #else #define TARGET #endif static int ShrinkBitmapEnable = 1 ; void SetShrinkBitmapEnable( int v ) { if( v ) ShrinkBitmapEnable = 1 ; else ShrinkBitmapEnable = 0 ; } // // Fonctions de shrink de bitmap // #define Alloc(p,t) (t *)malloc((p)*sizeof(t)) #define For(i,n) for ((i)=0;(i)<(n);(i)++) #define iFor(n) For (i,n) #define jFor(n) For (j,n) typedef struct { WORD x, y ; // dimensions WORD l ; // bytes per scan-line (32-bit allignment) BYTE *b ; // bits of bitmap,3 bytes/pixel, BGR } tWorkBMP ; // 24-bit working bitmap void CreateWorkingBitmap( WORD dx, WORD dy, tWorkBMP *w ) { w->x=dx ; w->y=dy ; w->l=(dx+1)*3&0xfffc ; w->b=Alloc( w->l*dy, BYTE ) ; } HBITMAP CreateEmptyBitmap( WORD dx, WORD dy ) { HDC h = GetDC( NULL ) ; HBITMAP b = CreateCompatibleBitmap( h, dx, dy ) ; ReleaseDC( NULL, h ) ; return(b) ; } void SetBMIHeader( BITMAPINFO *b, short dx, short dy ) { b->bmiHeader.biSize = sizeof(BITMAPINFOHEADER) ; b->bmiHeader.biWidth = dx ; b->bmiHeader.biHeight = -dy ; b->bmiHeader.biPlanes = 1 ; b->bmiHeader.biBitCount = 24 ; b->bmiHeader.biCompression = BI_RGB ; b->bmiHeader.biSizeImage = 0 ; b->bmiHeader.biXPelsPerMeter = 1 ; b->bmiHeader.biYPelsPerMeter = 1 ; b->bmiHeader.biClrUsed = 0 ; b->bmiHeader.biClrImportant = 0 ; } POINT GetBitmapSize( HBITMAP h ) { POINT p ; BITMAP o ; GetObject( h, sizeof(o), &o ) ; p.x = o.bmWidth ; p.y = o.bmHeight ; return(p) ; } void OpenBitmapForWork( HBITMAP b, tWorkBMP *w ) { BITMAPINFO s ; HDC h = GetDC( NULL ) ; POINT v = GetBitmapSize( b ) ; CreateWorkingBitmap( v.x, v.y, w ) ; SetBMIHeader( &s,w->x, w->y ) ; GetDIBits( h, b, 0, w->y, w->b, &s, DIB_RGB_COLORS ) ; ReleaseDC( NULL, h ) ; } void SaveWorkingBitmap( tWorkBMP *w, HBITMAP b ) { BITMAPINFO s ; HDC h = GetDC( NULL ) ; SetBMIHeader( &s, w->x, w->y ) ; SetDIBits( h, b, 0, w->y, w->b, &s, DIB_RGB_COLORS ) ; ReleaseDC( NULL, h ) ; } void ShrinkWorkingBitmap( tWorkBMP *a, tWorkBMP *b, WORD bx, WORD by ) { BYTE *uy = a->b, *ux, i ; WORD x, y, nx, ny = 0 ; DWORD df = 3*bx, nf = df*by, j ; float k, qx[2], qy[2], q[4], *f = Alloc( nf, float ) ; CreateWorkingBitmap( bx, by, b) ; jFor (nf) f[j]=0; j=0; For( y, a->y ) { ux=uy; uy+=a->l; nx=0; ny+=by; if (ny>a->y) { qy[0]=1-(qy[1]=(ny-a->y)/(float)by); For (x,a->x) { nx+=bx; if (nx>a->x) { qx[0]=1-(qx[1]=(nx-a->x)/(float)bx); iFor (4) q[i]=qx[i&1]*qy[i>>1]; iFor (3) { f[j]+=(*ux)*q[0]; f[j+3]+=(*ux)*q[1]; f[j+df]+=(*ux)*q[2]; f[(j++)+df+3]+=(*(ux++))*q[3]; } } else iFor (3) { f[j+i]+=(*ux)*qy[0]; f[j+df+i]+=(*(ux++))*qy[1]; } if (nx>=a->x) nx-=a->x; if (!nx) j+=3; } } else { For (x,a->x) { nx+=bx; if (nx>a->x) { qx[0]=1-(qx[1]=(nx-a->x)/(float)bx); iFor (3) { f[j]+=(*ux)*qx[0]; f[(j++)+3]+=(*(ux++))*qx[1]; } } else iFor (3) f[j+i]+=*(ux++); if (nx>=a->x) nx-=a->x; if (!nx) j+=3; } if (nyy) j-=df; } if (ny>=a->y) ny-=a->y; } nf=0; k=bx*by/(float)(a->x*a->y); uy=b->b; For (y,by) { jFor (df) uy[j]=(unsigned char)(f[nf++]*k+.5); uy+=b->l; } free (f); } TARGET HBITMAP ShrinkBitmap( HBITMAP a, WORD bx, WORD by ) // creates and returns new bitmap with dimensions of // [bx,by] by shrinking bitmap a both [bx,by] must be less or equal // than the dims of a, unless the result is nonsense { tWorkBMP in, out ; HBITMAP b=CreateEmptyBitmap( bx, by ) ; OpenBitmapForWork( a, &in ) ; ShrinkWorkingBitmap( &in, &out, bx, by ) ; free( in.b ) ; SaveWorkingBitmap( &out, b ) ; free( out.b ) ; return( b ) ; } HBITMAP ResizeBmp( HBITMAP hBmpSrc, WORD bx, WORD by ) { SIZE newSize ; newSize.cx = bx; newSize.cy = by; // taille actuelle BITMAP bmpInfo; GetObject(hBmpSrc, sizeof(BITMAP), &bmpInfo); SIZE oldSize; oldSize.cx = bmpInfo.bmWidth; oldSize.cy = bmpInfo.bmHeight; // selection source ds un DC HDC hdc = GetDC(NULL); HDC hDCSrc = CreateCompatibleDC(hdc); HBITMAP hOldBmpSrc = (HBITMAP)SelectObject(hDCSrc, hBmpSrc); // création bitmap dest et sélection ds un DC HDC hDCDst = CreateCompatibleDC(hdc); HBITMAP hBmpDst = CreateCompatibleBitmap(hdc, newSize.cx, newSize.cy); HBITMAP hOldBmpDst = (HBITMAP)SelectObject(hDCDst, hBmpDst); // resize StretchBlt(hDCDst, 0, 0, newSize.cx, newSize.cy, hDCSrc, 0, 0, oldSize.cx, oldSize.cy, SRCCOPY); // libération ressources SelectObject(hDCSrc, hOldBmpSrc); SelectObject(hDCDst, hOldBmpDst); DeleteDC(hDCSrc); DeleteDC(hDCDst); ReleaseDC(NULL, hdc); return hBmpDst; } static void fill_dc(HDC dc, int width, int height, COLORREF color) { HBRUSH clrBrush = CreateSolidBrush(color); HPEN clrPen = CreatePen(PS_SOLID, 0, color); HBRUSH oldBrush; HPEN oldPen; oldBrush = SelectObject(dc, clrBrush); oldPen = SelectObject(dc, clrPen); Rectangle(dc, 0, 0, width, height); SelectObject(dc, oldBrush); SelectObject(dc, oldPen); } static BOOL load_wallpaper_bmp(HBITMAP* rawImage, int* style, int* x, int* y) { LONG lRes; HKEY kDesktop; DWORD pathLen = MAX_PATH; DWORD numBufLen = 10; char wpPath[MAX_PATH]; char wpStyleBuf[10]; char wpTileBuf[10]; int wpStyle = -1; int wpTile = -1; // NOTE: In the non-wallpaper case (i.e., load_file_bmp), we load parameters // like x, y and style from cfg, but in the wallpaper case we ignore our // stored configuration and get that information from the system. // ENHANCE: It's possible to set WallpaperOriginX and WallpaperOriginY to // specify an exact position for the start of the wallpaper, but this // function doesn't support that yet. I don't think it's possible to set // it through the normal UI anyway, you have to hack the registry to do it. // For now, we'll never return an (x,y) positioning request to the caller. *x = *y = 0; lRes = RegOpenKeyEx( HKEY_CURRENT_USER, "Control Panel\\Desktop", 0, KEY_READ, &kDesktop ); if(lRes != ERROR_SUCCESS) { RegCloseKey(kDesktop); return FALSE; // TODO: Should the error be reported to the user here? } lRes = RegQueryValueEx(kDesktop, "Wallpaper", NULL, NULL, (LPBYTE)wpPath, &pathLen); if(lRes != ERROR_SUCCESS) { RegCloseKey(kDesktop); return FALSE; // TODO: Should the error be reported to the user here? } lRes = RegQueryValueEx( kDesktop, "WallpaperStyle", NULL, NULL, (LPBYTE)wpStyleBuf, &numBufLen ); if(lRes == ERROR_SUCCESS) wpStyle = atoi(wpStyleBuf); lRes = RegQueryValueEx( kDesktop, "TileWallpaper", NULL, NULL, (LPBYTE)wpTileBuf, &numBufLen ); if(lRes == ERROR_SUCCESS) wpTile = atoi(wpTileBuf); if(wpStyle < 0 && wpStyle > 3) wpStyle = 0; // Default to tile. else if(wpTile > 0) wpStyle = 0; // Force tile. else if(wpStyle == 0 && wpTile == 0) wpStyle = 1; // For Explorer, wpStyle == wpTile == 0 means center, and // it doesn't ever set wpStyle to 1. We call wpStyle == 1 // center and don't use wpTile, to simplify things after // this point. RegCloseKey(kDesktop); if( *rawImage!=NULL ) { DeleteObject( *rawImage ) ; *rawImage=NULL ; } *rawImage = LoadImage( NULL, wpPath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); if(*rawImage == 0) return FALSE; // TODO: Should the error be reported to the user here? *style = wpStyle; return TRUE; } static BOOL load_file_bmp(HBITMAP* rawImage, int* style, int* x, int* y) { *x = conf_get_int( conf,CONF_bg_image_abs_x); *y = conf_get_int( conf,CONF_bg_image_abs_y ); *style = conf_get_int( conf,CONF_bg_image_style); if( *rawImage!=NULL ) { DeleteObject( *rawImage ) ; *rawImage=NULL ; } *rawImage = LoadImage( NULL, conf_get_filename( conf, CONF_bg_image_filename )->path, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); if(*rawImage == 0) return FALSE; // TODO: Should the error be reported to the user here? return TRUE; } jmp_buf JPEG_bailout; int usePalette = 0; char *loadError = NULL; COLORREF skycolour = RGB(0, 0, 255); HBITMAP CreateHBitmap(int w, int h, LPVOID *lpBits) { HBITMAP bitmap; BITMAPINFOHEADER BIH ; int iSize = sizeof(BITMAPINFOHEADER) ; memset(&BIH, 0, iSize); // Fill in the header info. BIH.biSize = iSize; BIH.biWidth = w; BIH.biHeight = h; BIH.biPlanes = 1; BIH.biBitCount = 24; BIH.biCompression = BI_RGB; HDC hDC = CreateCompatibleDC(NULL); bitmap = CreateDIBSection(hDC, (BITMAPINFO*)&BIH, DIB_RGB_COLORS, lpBits, NULL, 0); DeleteDC(hDC); return bitmap; } // LOADJPEGIMAGE -- Load JPEG image into memory HBITMAP loadJPEGimage(FILE *input_file, HGLOBAL *LimageBitmap, int *LsizeX, int *LsizeY) { int i; LPBITMAPINFOHEADER bh; DWORD bmpsize; struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPARRAY colormap; LPBYTE pix; int linewid; int pixbytes; static LPBYTE sl = NULL; static HGLOBAL imageBitmap = NULL; // In-memory bitmap sl = NULL; imageBitmap = NULL; if (setjmp(JPEG_bailout) != 0) { /* Since we arrive here via longjmp() from parts unknown, we may have allocated the line buffer or bitmap prior to bailing out. If they've been allocated, release them. */ if (sl != NULL) { GlobalFree(sl); sl = NULL; } if (imageBitmap != NULL) { GlobalFree(imageBitmap); imageBitmap = NULL; } return NULL; } cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, input_file); jpeg_read_header(&cinfo, TRUE); cinfo.desired_number_of_colors = 254; cinfo.quantize_colors = usePalette; jpeg_start_decompress(&cinfo); pixbytes = (usePalette ? 1 : 3); sl = GlobalAlloc(GMEM_FIXED, cinfo.output_width * pixbytes); if (sl == NULL) { loadError = "Cannot allocate JPEG decoder row buffer"; return NULL; } linewid = ((((cinfo.output_width * pixbytes) + (sizeof(LONG) - 1)) / sizeof(LONG)) * sizeof(LONG)); bmpsize = sizeof(BITMAPINFOHEADER) + (usePalette ? (256 * sizeof(RGBQUAD)) : 0) + (linewid * cinfo.output_height); imageBitmap = GlobalAlloc(GMEM_FIXED, bmpsize); if (imageBitmap == NULL) { loadError = "Cannot allocate bitmap for decoded JPEG image"; GlobalFree(sl); return NULL; } // Plug in header fields with information from cinfo bh = (LPBITMAPINFOHEADER) imageBitmap; pix = ((LPBYTE) imageBitmap) + sizeof(BITMAPINFOHEADER) + (usePalette ? (256 * sizeof(RGBQUAD)) : 0); pix = pix + 0 ; // Pour eviter un warning de compilation bh->biSize = sizeof(BITMAPINFOHEADER); bh->biWidth = cinfo.output_width; bh->biHeight = cinfo.output_height; bh->biPlanes = 1; bh->biBitCount = usePalette ? 8 : 24; bh->biCompression = BI_RGB; bh->biSizeImage = 0; bh->biXPelsPerMeter = bh->biYPelsPerMeter = 2835; bh->biClrUsed = 0; bh->biClrImportant = 0; /* Construct the palette from the colour map optimised for the JPEG file. */ if (usePalette) { colormap = cinfo.colormap; for (i = 0; i < cinfo.actual_number_of_colors; i++) { if (cinfo.num_components == 1) { ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbRed = ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbGreen = ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbBlue = GETJSAMPLE(colormap[0][i]); ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbReserved = 0; } else { ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbRed = GETJSAMPLE(colormap[0][i]); ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbGreen = GETJSAMPLE(colormap[1][i]); ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbBlue = GETJSAMPLE(colormap[2][i]); ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[i])->rgbReserved = 0; } } /* Plug black and our text colour in the last two slots of the palette so we canbe sure they're available. */ ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[254])->rgbRed = ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[254])->rgbGreen = ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[254])->rgbBlue = ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[254])->rgbReserved = 0; ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[255])->rgbRed = GetRValue(skycolour); ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[255])->rgbGreen = GetGValue(skycolour); ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[255])->rgbBlue = GetBValue(skycolour); ((LPRGBQUAD) &((LPBITMAPINFO) bh)->bmiColors[255])->rgbReserved = 0; } // Return scan lines and transfer to the pixel array BYTE *pDst = NULL; HBITMAP hBitmap = CreateHBitmap(bh->biWidth, bh->biHeight, (void**)&pDst); int nStorageWidth = ((bh->biWidth * 24 + 31) & ~31) >> 3; //dword alignment JSAMPARRAY ppDst = &pDst; /* LPBYTE px = pix + (linewid * (bh->biHeight - 1)); for (i = 0; i < (int) cinfo.output_height; i++) { unsigned char *slp[1] = { sl }; jpeg_read_scanlines(&cinfo, slp, 1); if (usePalette) { memcpy(px, sl, cinfo.output_width); } else { int j, k; if (cinfo.num_components == 3) { for (j = k = 0; j < (int) cinfo.output_width; j++, k += 3) { px[k] = sl[k + 2]; px[k + 1] = sl[k + 1]; px[k + 2] = sl[k]; } } else { for (j = k = 0; j < (int) cinfo.output_width; j++, k += 3) { px[k] = sl[j]; px[k + 1] = sl[j]; px[k + 2] = sl[j]; } } } px -= linewid; } */ pDst = pDst + (cinfo.output_height-1)*nStorageWidth ; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines (&cinfo, ppDst, 1); if(cinfo.out_color_components==3) { //swap R & B BYTE* p = pDst; int i ; for( i=0;ibiWidth;i++) { BYTE r = p[0]; p[0] = p[2]; p[2] = r; p += 3; } } //pDst += nStorageWidth; pDst -= nStorageWidth; } GlobalFree(sl); jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); *LsizeX = (int) bh->biWidth; *LsizeY = (int) bh->biHeight; *LimageBitmap = imageBitmap; return hBitmap; } static BOOL load_file_jpeg(HBITMAP* rawImage, int* style, int* x, int* y) { *x = conf_get_int( conf, CONF_bg_image_abs_x ); *y = conf_get_int( conf, CONF_bg_image_abs_y ); *style = conf_get_int( conf, CONF_bg_image_style ); int res=TRUE, LsizeX, LsizeY ; FILE *fp ; HGLOBAL LimageBitmap = NULL ; if( ( fp=fopen( conf_get_filename( conf,CONF_bg_image_filename)->path, "rb" ) ) == NULL ) return FALSE ; if( *rawImage!=NULL ) { DeleteObject( *rawImage ) ; *rawImage=NULL ; } *rawImage = loadJPEGimage(fp, &LimageBitmap,&LsizeX, &LsizeY) ; if( rawImage == NULL ) res =FALSE ; fclose( fp ) ; GlobalFree(LimageBitmap); return res; } static HBITMAP CreateDIBSectionWithFileMapping(HDC dc, int width, int height, HANDLE fmap) { BITMAPINFOHEADER BMI; BMI.biSize = sizeof(BITMAPINFOHEADER); BMI.biWidth = width; BMI.biHeight = height; BMI.biPlanes = 1; BMI.biBitCount = 32; BMI.biCompression = BI_RGB; BMI.biSizeImage = 0; BMI.biXPelsPerMeter = 0; BMI.biYPelsPerMeter = 0; BMI.biClrUsed = 0; BMI.biClrImportant = 0; return(CreateDIBSection(dc, (BITMAPINFO *)&BMI, DIB_RGB_COLORS, 0, fmap, 0)); } /***********SCREEN CAPTURE*******************/ /******************************/ void init_dc_blend(void) { //HMODULE * msimg32_dll = LoadLibrary("msimg32.dll"); HMODULE msimg32_dll = LoadLibrary("msimg32.dll"); if(msimg32_dll) pAlphaBlend = GetProcAddress(msimg32_dll, "AlphaBlend"); if(pAlphaBlend) { HDC hdc = GetDC(MainHwnd); // Create one pixel size bitmap for use in color_blend. if( colorinpixeldc !=NULL ) { DeleteDC(colorinpixeldc ) ; } colorinpixeldc = CreateCompatibleDC(hdc); if( colorinpixelbm!=NULL ) { DeleteObject(colorinpixelbm) ; } colorinpixelbm = CreateCompatibleBitmap(hdc, 1, 1); SelectObject(colorinpixeldc, colorinpixelbm); colorinpixel = 0; SetPixelV(colorinpixeldc, 0, 0, colorinpixel); ReleaseDC(MainHwnd, hdc); } } void color_blend( HDC destDc, int x, int y, int width, int height, COLORREF alphacolor, int opacity) { if(pAlphaBlend) { // Fast alpha blending for Win98&2000 and newer... BLENDFUNCTION blender; // Create one pixel size bitmap for use in color_blend. if(colorinpixel != alphacolor) { colorinpixel = alphacolor; SetPixelV(colorinpixeldc, 0, 0, alphacolor); } blender.BlendOp = AC_SRC_OVER; blender.BlendFlags = 0; blender.SourceConstantAlpha = (0xff * opacity) / 100; blender.AlphaFormat = 0; (*pAlphaBlend)(destDc, x, y, width, height, colorinpixeldc, 0, 0, 1, 1, blender); } else { // Slow alpha blending for Win95&NT... // Note: Only tested with WinXP, should work on 95/NT.. probably. int i, alphacolorR, alphacolorG, alphacolorB, bk_opacity; HBITMAP tmpbm; HDC tmpdc; static HANDLE fmap; static int fmap_size; static unsigned char * pRGB; if(fmap_size < width * height * 4) { if(fmap) { UnmapViewOfFile(pRGB); CloseHandle(fmap); } fmap_size = width * height * 4; fmap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, fmap_size, NULL); pRGB = MapViewOfFile(fmap, FILE_MAP_ALL_ACCESS, 0, 0, fmap_size); } // Create DIBSection so we get pixels easily. tmpdc = CreateCompatibleDC(destDc); tmpbm = CreateDIBSectionWithFileMapping(destDc, width, height, fmap); SelectObject(tmpdc, tmpbm); // Copy bitmap to temporary bitmap for easy pixel access. BitBlt(tmpdc, 0, 0, width, height, destDc, x, y, SRCCOPY); // Moved stuff out from the loop alphacolorR = GetRValue(alphacolor) * opacity; alphacolorG = GetGValue(alphacolor) * opacity; alphacolorB = GetBValue(alphacolor) * opacity; bk_opacity = 100 - opacity; for(i=0; i= width ) { w = 0 ; } opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * (1.0*w)/(1.0*width) ; break ; case 4: // De droite a gauche w++ ; if( w >= width ) { w = 0 ; } opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * (1.0*w)/(1.0*width) ; opacity = 100 - opacity ; break ; case 5: // Du centre vers l'exterieur if( (i%(4*width)) == 0 ) { h++ ; } w++ ; if( w >= width ) { w = 0 ; } l = sqrt( pow(1.0*width/2.0-w,2.0)+pow(1.0*height/2.0-h,2.0) ) / sqrt( pow(1.0*width/2.0,2.0)+pow(1.0*height/2.0,2.0) ); opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * l ; break ; case 6: // De l'exterieur vers le centre if( (i%(4*width)) == 0 ) { h++ ; } w++ ; if( w >= width ) { w = 0 ; } l = sqrt( pow(1.0*width/2.0-w,2.0)+pow(1.0*height/2.0-h,2.0) ) / sqrt( pow(1.0*width/2.0,2.0)+pow(1.0*height/2.0,2.0) ); opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * l ; opacity = 100 - opacity ; break ; case 7: if( (i%(4*width)) == 0 ) { h++ ; } w++ ; if( w >= width ) { w = 0 ; } l = sqrt( pow(1.0*w,2.0)+pow(1.0*h,2.0) )/sqrt( pow(1.0*width,2.0)+pow(1.0*height,2.0) ) ; opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * l ; break ; case 8: if( (i%(4*width)) == 0 ) { h++ ; } w++ ; if( w >= width ) { w = 0 ; } l = sqrt( pow(1.0*w,2.0)+pow(1.0*h,2.0) )/sqrt( pow(1.0*width,2.0)+pow(1.0*height,2.0) ) ; opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * l ; opacity = 100 - opacity ; break ; case 9: if( (i%(4*width)) == 0 ) { h++ ; } w++ ; if( w >= width ) { w = 0 ; } l = sqrt( pow(1.0*(width-w),2.0)+pow(1.0*h,2.0) )/sqrt( pow(1.0*width,2.0)+pow(1.0*height,2.0) ) ; opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * l ; break ; case 10: if( (i%(4*width)) == 0 ) { h++ ; } w++ ; if( w >= width ) { w = 0 ; } l = sqrt( pow(1.0*(width-w),2.0)+pow(1.0*h,2.0) )/sqrt( pow(1.0*width,2.0)+pow(1.0*height,2.0) ) ; opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * l ; opacity = 100 - opacity ; break ; default: // De haut en bas if( (i%(4*width)) == 0 ) { h++ ; opacity = OpacityMin + 1.0*( OpacityMax-OpacityMin ) * (1.0*h)/(1.0*height) ; } break ; } if( opacity < 0 ) opacity = 0 ; if( opacity > 100 ) opacity = 100 ; alphacolorR = GetRValue(alphacolor) * opacity; alphacolorG = GetGValue(alphacolor) * opacity; alphacolorB = GetBValue(alphacolor) * opacity; bk_opacity = 100 - opacity ; pRGB[i + 0] = (pRGB[i + 0] * bk_opacity + alphacolorB) / 100; pRGB[i + 1] = (pRGB[i + 1] * bk_opacity + alphacolorG) / 100; pRGB[i + 2] = (pRGB[i + 2] * bk_opacity + alphacolorR) / 100; } // Copy temporary bitmap back to original BitBlt(destDc, x, y, width, height, tmpdc, 0, 0, SRCCOPY); DeleteObject(tmpbm); DeleteDC(tmpdc); } void CreateBlankBitmap( HBITMAP * rawImage, const int width, const int height ) { HDC dc= CreateCompatibleDC(NULL); BITMAPINFO bi; ZeroMemory( &bi.bmiHeader, sizeof(BITMAPINFOHEADER) ); bi.bmiHeader.biWidth=width; // Set size you need bi.bmiHeader.biHeight=height; // Set size you need bi.bmiHeader.biPlanes=1; bi.bmiHeader.biBitCount=24; // Can be 8, 16, 32 bpp or bi.bmiHeader.biSizeImage=0; bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); bi.bmiHeader.biClrUsed= 0; bi.bmiHeader.biClrImportant= 0; VOID *pvBits; if( *rawImage!=NULL ) { DeleteObject( *rawImage ) ; *rawImage=NULL ; } *rawImage = CreateDIBSection( dc,&bi,DIB_RGB_COLORS,&pvBits,NULL,0 ); ReleaseDC(NULL, dc) ; HDC hDC = GetDC(MainHwnd); HDC hDCDst = CreateCompatibleDC(hDC); // memory device context for dest bitmap ReleaseDC(NULL, hDC); // hdcMem contains your rendered particle HBRUSH hBrush = CreateSolidBrush(RGB(255,0,0)); // Paints the rectangular band with the brush RECT Rect = {0, 0, width-1, height-1}; FillRect(hDCDst, &Rect, hBrush); // Deletes the brush DeleteObject(hBrush); HGDIOBJ holdDIBDst = SelectObject(hDCDst, *rawImage); // transfer the image to your DIB bitmap BitBlt(hDCDst, 0, 0 ,width, height, hDC, 0, 0, SRCCOPY); // clean up SelectObject(hDCDst, holdDIBDst); DeleteDC(hDCDst); } BOOL load_bg_bmp() { HBITMAP rawImage = NULL; BITMAP rawImageInfo; HDC hdcPrimary; HDC bmpdc; int deskWidth, deskHeight, clientWidth, clientHeight; int x, y; int style; //COLORREF backgroundcolor = colours[258]; // Default Background COLORREF backgroundcolor = return_colours258() ; COLORREF alphacolor = backgroundcolor; // Start off assuming this is true. bBgRelToTerm = conf_get_int( conf,CONF_bg_image_abs_fixed); RECT clientRect; GetWindowRect( MainHwnd, &clientRect ) ; clientWidth = clientRect.right-clientRect.left+1 ; clientHeight = clientRect.bottom-clientRect.top+1 ; switch( conf_get_int( conf,CONF_bg_type) ) { // Solid case 0: // No bitmap file to load. We'll handle this case below. break; // Wallpaper case 1: backgroundcolor = GetSysColor(COLOR_BACKGROUND); bBgRelToTerm = FALSE; // Wallpaper is never positioned relative to term. if(!load_wallpaper_bmp(&rawImage, &style, &x, &y)) rawImage = NULL; // Make sure rawImage is still NULL. break; // Image case 2: { backgroundcolor = GetSysColor(COLOR_BACKGROUND) ; if( conf_get_filename(conf,CONF_bg_image_filename)->path[0] == '#' ) { int r=0,g=0,b=0; sscanf( conf_get_filename(conf,CONF_bg_image_filename)->path, "#%02X%02X%02X", &r, &g, &b ) ; backgroundcolor = RGB( r, g, b ) ; BYTE *pDst = NULL; rawImage = CreateHBitmap(10, 10, (void**)&pDst); style = 4 ; } else if( !stricmp( conf_get_filename(conf,CONF_bg_image_filename)->path+strlen(conf_get_filename(conf,CONF_bg_image_filename)->path)-4, ".jpg" ) ) { if(!load_file_jpeg(&rawImage, &style, &x, &y)) rawImage = NULL; // Make sure rawImage is still NULL. } else if( !stricmp( conf_get_filename(conf,CONF_bg_image_filename)->path+strlen(conf_get_filename(conf,CONF_bg_image_filename)->path)-5, ".jpeg" ) ) { if(!load_file_jpeg(&rawImage, &style, &x, &y)) rawImage = NULL; // Make sure rawImage is still NULL. } else if(!load_file_bmp(&rawImage, &style, &x, &y)) rawImage = NULL; // Make sure rawImage is still NULL. break; } } hdcPrimary = GetDC(MainHwnd); deskWidth = GetDeviceCaps(hdcPrimary, HORZRES); deskHeight = GetDeviceCaps(hdcPrimary, VERTRES); // Securite pour ne pas depacer les limites de l'ecran principal if( (bBgRelToTerm == 0) &&((clientRect.right>deskWidth)||(clientRect.bottom>deskHeight)) ) { //DeleteObject(rawImage); rawImage = NULL ; bBgRelToTerm = 1 ; } if(rawImage == NULL) { // Create a solid bitmap. We'll get here in two cases: either the user // selected the Solid background option, or the attempt to do something // fancier (use the system wallpaper or an image file) failed. /* if( backgrounddc!=NULL ) DeleteDC(backgrounddc) ; backgrounddc = CreateCompatibleDC(hdcPrimary); if( backgroundbm!=NULL ) DeleteObject(backgroundbm); backgroundbm = CreateCompatibleBitmap(hdcPrimary, deskWidth, deskHeight); SelectObject(backgrounddc, backgroundbm); */ // Do not create anything, use default 'no background'-code instead. } else { // We've managed to load a good image. Now, we need to manipulate it to // the right size, location, etc. // Find the width and height of the image we just loaded. GetObject(rawImage, sizeof(rawImageInfo), &rawImageInfo); // Create a temporary DC to wrap the raw image. bmpdc = CreateCompatibleDC(hdcPrimary); SelectObject(bmpdc, rawImage); // Create a memory DC that has a new bitmap of the appropriate final // image size. if( textdc!=NULL ) { DeleteDC(textdc) ; } textdc = CreateCompatibleDC(hdcPrimary); if( textbm!= NULL ) { DeleteObject(textbm) ; } textbm = CreateCompatibleBitmap(hdcPrimary, deskWidth, deskHeight); SelectObject(textdc, textbm); if( backgrounddc!=NULL ) { DeleteDC(backgrounddc) ; } backgrounddc = CreateCompatibleDC(hdcPrimary); if( backgroundbm!=NULL ) { DeleteObject(backgroundbm) ; } backgroundbm = CreateCompatibleBitmap(hdcPrimary, deskWidth, deskHeight) ; SelectObject(backgrounddc, backgroundbm); switch(style) { case 0: { // Tile for(y = 0; y < deskHeight; y += rawImageInfo.bmHeight) { for(x = 0; x < deskWidth; x += rawImageInfo.bmWidth) { BitBlt( backgrounddc, x, y, rawImageInfo.bmWidth, rawImageInfo.bmHeight, bmpdc, 0, 0, SRCCOPY ); } } } break; case 1: // Center // Calculate x & y, ignoring values they may already have, then drop // down to the (X,Y) placement case below. x = (deskWidth - rawImageInfo.bmWidth) / 2; y = (deskHeight - rawImageInfo.bmHeight) / 2; case 3: { // Absolute Place at given (X,Y) // Start out with a background color fill. fill_dc(backgrounddc, deskWidth, deskHeight, backgroundcolor); BitBlt( backgrounddc, x, y, rawImageInfo.bmWidth, rawImageInfo.bmHeight, bmpdc, 0, 0, SRCCOPY ); break; } case 2: // Stretch StretchBlt( backgrounddc, 0, 0, deskWidth, deskHeight, bmpdc, 0, 0, rawImageInfo.bmWidth, rawImageInfo.bmHeight, SRCCOPY ); break; case 4: // blank background fill_dc(backgrounddc, deskWidth, deskHeight, backgroundcolor) ; break ; case 5: // Stretch a la taille de la fenetre { if( (ShrinkBitmapEnable)&&(clientWidth= 0 ) { color_blend( backgroundblenddc, 0, 0, deskWidth, deskHeight, alphacolor, conf_get_int(conf,CONF_bg_opacity)); } else { if( bBgRelToTerm == 1 ) { deskWidth = clientWidth ; deskHeight = clientHeight ; } color_opacity_gradient( backgroundblenddc, 0, 0, deskWidth, deskHeight, alphacolor, -conf_get_int(conf,CONF_bg_opacity) ); } } ReleaseDC(MainHwnd, hdcPrimary); //DeleteDC(hdcPrimary); return TRUE; } void paint_term_edges(Terminal*term, HDC hdc, LONG paint_left, LONG paint_top, LONG paint_right, LONG paint_bottom) { if(backgrounddc == 0) load_bg_bmp(); if(backgrounddc) { LONG topLeftX = paint_left; LONG topLeftY = paint_top; LONG width = (paint_right - paint_left); LONG height = (paint_bottom - paint_top); HDC srcdc = backgroundblenddc; POINT srcTopLeft; RECT size_now; srcTopLeft.x = topLeftX; srcTopLeft.y = topLeftY; if(!bBgRelToTerm) ClientToScreen(MainHwnd, &srcTopLeft); if(!srcdc) srcdc = backgrounddc; if(resizing) { GetClientRect(MainHwnd, &size_now); if(size_now.bottom > size_before.bottom || size_now.right > size_before.right) { // Draw on full area on resize. BitBlt(hdc, topLeftX, topLeftY, width, height, srcdc, srcTopLeft.x, srcTopLeft.y, SRCCOPY); return; } } //debug_log("1: %d %d %d %d\n",size_before.top,size_before.bottom,size_before.left,size_before.right) ; //debug_log("2: %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %d\n",topLeftX,topLeftY,width,height,srcTopLeft.x,srcTopLeft.y,size_now.top,size_now.bottom,size_now.left,size_now.right,resizing) ; // Draw top edge BitBlt( hdc, topLeftX, topLeftY, width, return_offset_height(), srcdc, srcTopLeft.x, srcTopLeft.y, SRCCOPY ); // Draw left edge BitBlt( hdc, topLeftX, topLeftY+1, return_offset_width(), height-2, srcdc, srcTopLeft.x, srcTopLeft.y+1, SRCCOPY ); // Draw right edge (extra width for clean resizing) BitBlt( hdc, topLeftX+width-1, topLeftY+1, return_offset_width(), height-2, srcdc, srcTopLeft.x+width-1, srcTopLeft.y+1, SRCCOPY ); // Draw bottom edge (extra height for clean resizing) BitBlt( hdc, topLeftX, topLeftY+height-1, width, return_offset_height(), srcdc, srcTopLeft.x, srcTopLeft.y+height-1, SRCCOPY ); } else { HBRUSH bgbrush, oldbrush; HPEN edge, oldpen; //COLORREF backgroundcolor = colours[258]; COLORREF backgroundcolor = return_colours258() ; bgbrush = CreateSolidBrush(backgroundcolor); edge = CreatePen(PS_SOLID, 0, backgroundcolor); oldbrush = SelectObject(hdc, bgbrush); oldpen = SelectObject(hdc, edge); /* * Jordan Russell reports that this apparently * ineffectual IntersectClipRect() call masks a * Windows NT/2K bug causing strange display * problems when the PuTTY window is taller than * the primary monitor. It seems harmless enough... */ IntersectClipRect(hdc, paint_left, paint_top, paint_right, paint_bottom); ExcludeClipRect(hdc, return_offset_width(), return_offset_height(), return_offset_width()+return_font_width()*(term->cols), return_offset_height()+return_font_height()*(term->rows)); //debug_log("3: %d %d %d %d %d %d %d\n",resizing,paint_left, paint_top, paint_right, paint_bottom,offset_width,offset_height ) ; //debug_log("4: %d %d %d %d\n",size_before.top,size_before.bottom,size_before.left,size_before.right) ; //debug_log("5: %d %d %d %d %d %d\n",paint_top,paint_bottom,paint_left,paint_right,term->cols,term->rows); Rectangle(hdc, paint_left, paint_top, paint_right, paint_bottom); SelectObject(hdc, oldpen); DeleteObject(edge); SelectObject(hdc, oldbrush); DeleteObject(bgbrush); } } /* void original_paint_term_edges(HDC hdc, LONG paint_left, LONG paint_top, LONG paint_right, LONG paint_bottom) { if(backgrounddc == 0) load_bg_bmp(); if(backgrounddc) { LONG topLeftX = paint_left; LONG topLeftY = paint_top; LONG width = (paint_right - paint_left); LONG height = (paint_bottom - paint_top); HDC srcdc = backgroundblenddc; POINT srcTopLeft; RECT size_now; srcTopLeft.x = topLeftX; srcTopLeft.y = topLeftY; if(!bBgRelToTerm) ClientToScreen(hwnd, &srcTopLeft); if(!srcdc) srcdc = backgrounddc; if(resizing) { GetClientRect(hwnd, &size_now); if(size_now.bottom > size_before.bottom || size_now.right > size_before.right) { // Draw on full area on resize. BitBlt(hdc, topLeftX, topLeftY, width, height, srcdc, srcTopLeft.x, srcTopLeft.y, SRCCOPY); return; } } //debug_log("1: %d %d %d %d\n",size_before.top,size_before.bottom,size_before.left,size_before.right) ; //debug_log("2: %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %d\n",topLeftX,topLeftY,width,height,srcTopLeft.x,srcTopLeft.y,size_now.top,size_now.bottom,size_now.left,size_now.right,resizing) ; // Draw top edge BitBlt( hdc, topLeftX, topLeftY, width, offset_height, srcdc, srcTopLeft.x, srcTopLeft.y, SRCCOPY ); // Draw left edge BitBlt( hdc, topLeftX, topLeftY+1, offset_width, height-2, srcdc, srcTopLeft.x, srcTopLeft.y+1, SRCCOPY ); // Draw right edge (extra width for clean resizing) BitBlt( hdc, topLeftX+width-1, topLeftY+1, offset_width, height-2, srcdc, srcTopLeft.x+width-1, srcTopLeft.y+1, SRCCOPY ); // Draw bottom edge (extra height for clean resizing) BitBlt( hdc, topLeftX, topLeftY+height-1, width, offset_height, srcdc, srcTopLeft.x, srcTopLeft.y+height-1, SRCCOPY ); } else { HBRUSH bgbrush, oldbrush; HPEN edge, oldpen; COLORREF backgroundcolor = colours[258]; bgbrush = CreateSolidBrush(backgroundcolor); edge = CreatePen(PS_SOLID, 0, backgroundcolor); oldbrush = SelectObject(hdc, bgbrush); oldpen = SelectObject(hdc, edge); // // * Jordan Russell reports that this apparently // * ineffectual IntersectClipRect() call masks a // * Windows NT/2K bug causing strange display // * problems when the PuTTY window is taller than // * the primary monitor. It seems harmless enough... IntersectClipRect(hdc, paint_left, paint_top, paint_right, paint_bottom); ExcludeClipRect(hdc, offset_width, offset_height, offset_width+font_width*(term->cols), offset_height+font_height*(term->rows)); //debug_log("3: %d %d %d %d %d %d %d\n",resizing,paint_left, paint_top, paint_right, paint_bottom,offset_width,offset_height ) ; //debug_log("4: %d %d %d %d\n",size_before.top,size_before.bottom,size_before.left,size_before.right) ; //debug_log("5: %d %d %d %d %d %d\n",paint_top,paint_bottom,paint_left,paint_right,term->cols,term->rows); Rectangle(hdc, paint_left, paint_top, paint_right, paint_bottom); SelectObject(hdc, oldpen); DeleteObject(edge); SelectObject(hdc, oldbrush); DeleteObject(bgbrush); } } */ void clean_bg(void) { DeleteDC(textdc);textdc=NULL; DeleteObject(textbm);textbm=NULL; //DeleteObject(colorinpixel); //DeleteDC(colorinpixeldc); //DeleteObject(colorinpixelbm); DeleteDC(backgrounddc);backgrounddc=NULL; DeleteObject(backgroundbm);backgroundbm=NULL; DeleteDC(backgroundblenddc);backgroundblenddc=NULL; DeleteObject(backgroundblendbm);backgroundblendbm=NULL; } void RedrawBackground( HWND hwnd ) { if( 1 && // On inhibe cette fonction a cause du probleme de fuite memoire due a l'image de fond !!! , mais probleme de rafraichissement ? (get_param("BACKGROUNDIMAGE"))&&(!get_param("PUTTY"))&&(conf_get_int(conf,CONF_bg_type) != 0) ) { clean_bg() ; load_bg_bmp(); // Apparement c'est ça qui faisait la fuite memoire !!! } /* InvalidateRect(hwnd, NULL, true) ; RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN); */ RedrawWindow( hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_UPDATENOW ) ; } #ifdef MOD_STARTBUTTON /* * Patch permettant de gerer le probleme de chargement de l'image de fond arrive avec putty 0.61 */ void BackgroundImagePatch( int num ) { int key=0x47 ; if( num == 1 ) { // Double-clic sur une session, on fait ALT-G + Down + ALT-O key = 0x47 ; /* VK_G 71 */ keybd_event(VK_LMENU , 0, 0, 0) ; keybd_event( key, 0, 0, 0); keybd_event( key, 0, KEYEVENTF_KEYUP, 0) ; keybd_event(VK_LMENU, 0, KEYEVENTF_KEYUP, 0) ; keybd_event(VK_DOWN, 0, 0, 0) ; keybd_event(VK_DOWN, 0, KEYEVENTF_KEYUP, 0) ; key=0x4F ; /* VK_O */ keybd_event(VK_LMENU , 0, 0, 0) ; keybd_event( key, 0, 0, 0); keybd_event( key, 0, KEYEVENTF_KEYUP, 0) ; keybd_event(VK_LMENU, 0, KEYEVENTF_KEYUP, 0) ; } } #endif #endif HBITMAP HWND_to_HBITMAP(HWND hWnd) { RECT r; HDC hdcMem, hdcScr; HBITMAP hbmMem, hbmOld; GetWindowRect(hWnd, &r); hdcScr = GetWindowDC(hWnd); hdcMem = CreateCompatibleDC(hdcScr); hbmMem = CreateCompatibleBitmap(hdcScr, r.right -= r.left, r.bottom -= r.top) ; hbmOld = (HBITMAP)SelectObject(hdcMem, hbmMem); BitBlt(hdcMem, 0, 0, r.right, r.bottom, hdcScr, 0, 0, SRCCOPY); SelectObject(hdcMem, hbmOld); ReleaseDC(hWnd, hdcScr); DeleteDC(hdcMem); return hbmMem; } BOOL HBITMAP_to_JPG(HBITMAP hbm, LPCTSTR jpgfile, int quality) { BITMAP bm; BITMAPINFO bi; BYTE *pPixels; JSAMPROW jrows[1], jrow; HDC hdcScr, hdcMem1, hdcMem2; HBITMAP hbmMem, hbmOld1, hbmOld2; FILE *fp = fopen(jpgfile, "wb"); struct jpeg_compress_struct jpeg; struct jpeg_error_mgr jerr; if(!hbm) return 0; if(!GetObject(hbm, sizeof(bm), &bm)) return 0; if(!fp) return 0; ZeroMemory(&bi, sizeof(bi)); bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi.bmiHeader.biWidth = bm.bmWidth; bi.bmiHeader.biHeight = bm.bmHeight; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 24; bi.bmiHeader.biCompression = BI_RGB; hdcScr = GetDC(0); hdcMem1 = CreateCompatibleDC(hdcScr); hbmOld1 = (HBITMAP)SelectObject(hdcMem1,hbm); hdcMem2 = CreateCompatibleDC(hdcScr); hbmMem = CreateDIBSection(hdcScr, &bi, DIB_RGB_COLORS, (VOID **)&pPixels, 0, 0); hbmOld2 = (HBITMAP)SelectObject(hdcMem2, hbmMem); BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem1, 0, 0, SRCCOPY); SelectObject(hdcMem1, hbmOld1); SelectObject(hdcMem2, hbmOld2); ReleaseDC(0, hdcScr); DeleteDC(hdcMem1); DeleteDC(hdcMem2); jpeg.err = jpeg_std_error(&jerr); jpeg_create_compress(&jpeg); jpeg_stdio_dest(&jpeg, fp); jpeg.image_width = bm.bmWidth; jpeg.image_height = bm.bmHeight; jpeg.input_components = 3; jpeg.in_color_space = JCS_RGB; jpeg.dct_method = JDCT_FLOAT; jpeg_set_defaults(&jpeg); jpeg_set_quality(&jpeg, (quality < 0 || quality > 100) ? 100 : quality, TRUE); jpeg_start_compress(&jpeg, TRUE); char *comment=NULL ; if( comment ) { jpeg_write_marker(&jpeg, JPEG_COM, (const JOCTET*)comment, strlen(comment)); } while(jpeg.next_scanline < jpeg.image_height) { unsigned int i, j, tmp; jrow = &pPixels[(jpeg.image_height - jpeg.next_scanline - 1) * ((((bm.bmWidth * 24) + 31) / 32) * 4)]; for(i = 0; i < jpeg.image_width; i++) { j = i * 3; tmp = jrow[j]; jrow[j] = jrow[j + 2]; jrow[j + 2] = tmp; } jrows[0] = jrow; jpeg_write_scanlines(&jpeg, jrows, 1); } jpeg_finish_compress(&jpeg); jpeg_destroy_compress(&jpeg); DeleteObject(hbmMem); fclose(fp); return 1; } void MakeScreenShot() { HBITMAP hbm = HWND_to_HBITMAP(GetDesktopWindow()); if(hbm) { HBITMAP_to_JPG(hbm, "screenshot.jpg", 85) ; DeleteObject(hbm); } } int screenCapturePart(int x, int y, int w, int h, LPCSTR fname,int quality) { int return_code = 0 ; HDC hdcSource = GetDC(NULL); HDC hdcMemory = CreateCompatibleDC(hdcSource); //int capX = GetDeviceCaps(hdcSource, HORZRES); //int capY = GetDeviceCaps(hdcSource, VERTRES); HBITMAP hBitmap = CreateCompatibleBitmap(hdcSource, w, h); HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcMemory, hBitmap); BitBlt(hdcMemory, 0, 0, w, h, hdcSource, x, y, SRCCOPY); hBitmap = (HBITMAP)SelectObject(hdcMemory, hBitmapOld); DeleteDC(hdcSource); DeleteDC(hdcMemory); //HPALETTE hpal = NULL; if( HBITMAP_to_JPG( hBitmap,fname, quality) ) { return_code = 1 ; } DeleteObject(hBitmap); return return_code ; } int screenCaptureClientRect( HWND hwnd, LPCSTR fname, int quality ) { RECT rc; POINT p; GetClientRect(hwnd, &rc); p.x=rc.left; p.y=rc.top, ClientToScreen(hwnd,&p); rc.left=p.x;rc.top=p.y; return screenCapturePart(rc.left,rc.top,rc.right,rc.bottom,fname,quality) ; } int screenCaptureWinRect( HWND hwnd, LPCSTR fname, int quality ) { RECT r; GetWindowRect(hwnd, &r); return screenCapturePart(r.left,r.top,r.right-r.left,r.bottom-r.top,fname,quality) ; } int screenCaptureAll( LPCSTR fname, int quality ) { return screenCapturePart(0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics (SM_CYSCREEN),fname,quality) ; }