/* * image.c * Yet Another Osuwari Multi for X11 * (Create Image Module) */ #include #include #include #include #include #include /* マシン固有価の定義、CARDPtrなど */ /* 一般的な返り値(未定義なことがある) */ #ifndef EXIT_SUCCESS #define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE #define EXIT_FAILURE 1 #endif /******** External Value ********/ extern Display *Disp; extern Colormap MyColorMap; /******** Functions Prototype ********/ unsigned int GetXDepth( ); XImage *CreateMyImage( ); static void CopyImageFromData32( ); static void CopyImageFromData16( ); static void CopyImageFromData8( ); static void PalettePix32( ); static void PalettePix16( ); static void PalettePix8( ); static int PickNearColor( ); Cursor CreateMyCursor( ); /******** GetXDepth ******** * X端末のカラーモードを得る */ unsigned int GetXDepth( disp ) Display *disp; { return DefaultDepth(disp, 0); XVisualInfo xvi_template; XVisualInfo *p_xvi; int n_item, i; int depth = 0; /**** Visual Class 一覧 **** * #define StaticGray 0 * #define GrayScale 1 * #define StaticColor 2 * #define PseudoColor 3 * #define TrueColor 4 * #define DirectColor 5 ****/ memset( &xvi_template, 0, sizeof(XVisualInfo) ); /* xvi_template.depth = 8; /**/ /* xvi_template.depth = PseudoColor; /**/ p_xvi = XGetVisualInfo( disp, VisualNoMask, &xvi_template, &n_item ); for( i=0; idata = (char*)malloc( image->bytes_per_line * height ); if( image->data == NULL ) { fprintf( stderr, "ERROR: Can't allocate memory for image data.\n" ); return NULL; } } pixel_size = image->bytes_per_line / width; padding = image->bytes_per_line - (width * pixel_size); /* data -> image->data にコピー */ if( pixel_size >= 4 ) { CopyImageFromData32( image->data, data, width, height, padding ); } else if( pixel_size >= 2 ) { CopyImageFromData16( image->data, data, width, height, padding ); } else { CopyImageFromData8( image->data, data, width, height, padding ); } /* 色(カラーセル)の確保 */ color_tbl = (XColor*)malloc( sizeof(XColor) * ncolor ); if( color_tbl == NULL ) { fprintf( stderr, "ERROR: Can't allocate memory for XColor.\n" ); return NULL; } for( index = 0; index < ncolor; index++ ) { color_tbl[ index ].red = palette[ index * 3 ] << 8; color_tbl[ index ].green = palette[ index * 3 + 1 ] << 8; color_tbl[ index ].blue = palette[ index * 3 + 2 ] << 8; if( XAllocColor( Disp, MyColorMap, &color_tbl[index] ) == 0 ) { /* 色(カラーセル)の確保に失敗した! */ /* printf( "INFO: Not enough ColorCell, using Near Color.\n" ); /* DEBUG */ if( PickNearColor( &palette[index], &color_tbl[index] ) != EXIT_SUCCESS ) { fprintf( stderr, "ERROR: Internal Color Allocate Error!\n" ); } } } /* ピクセルデータを XAllocColor したピクセル番号に書き換える */ if( pixel_size >= 4 ) { PalettePix32( image->data, color_tbl, width, height, padding ); } else if( pixel_size >= 2 ) { PalettePix16( image->data, color_tbl, width, height, padding ); } else { PalettePix8( image->data, color_tbl, width, height, padding ); } /* あとしまつ */ free( (char*)color_tbl ); return( image ); } /******** CopyImageFromData ******** * data -> image->data にコピー * 8, 16, 32bit の3種類 * もとになる画像データは16色 (4bit) */ static void CopyImageFromData32( dst_data, src_data, width, height, pad ) CARD32 *dst_data; unsigned char *src_data; int width; int height; int pad; { int x, y; Bool lower = 0; for( y=0 ; y> 4); }else { *dst_data++ = *src_data & 0x0F; src_data++; } lower ^= 0x01; #endif } dst_data = (CARD32*)( (char*)dst_data + pad ); } } static void CopyImageFromData16( dst_data, src_data, width, height, pad ) CARD16 *dst_data; unsigned char *src_data; int width; int height; int pad; { int x, y; Bool lower = 0; for( y=0 ; y> 4); }else { *dst_data++ = *src_data & 0x0F; src_data++; } lower ^= 0x01; #endif } dst_data = (CARD16*)( (char*)dst_data + pad ); } } static void CopyImageFromData8( dst_data, src_data, width, height, pad ) CARD8 *dst_data; unsigned char *src_data; int width; int height; int pad; { int x, y; Bool lower = 0; for( y=0 ; y> 4); }else { *dst_data++ = *src_data & 0x0F; src_data++; } lower ^= 0x01; #endif } dst_data = (char*)dst_data + pad ; } } /******** PalettePix ******** * ピクセルデータを XAllocColor したピクセル番号に書き換える * 8, 16, 32bit の3種類 */ static void PalettePix32( dst_data, color_tbl, width, height, pad ) CARD32 *dst_data; XColor *color_tbl; int width; int height; int pad; { int x, y; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { *dst_data = color_tbl[ (CARD8)*dst_data ].pixel; dst_data++; } dst_data = (CARD32*)( (char*)dst_data + pad ); } } static void PalettePix16( dst_data, color_tbl, width, height, pad ) CARD16 *dst_data; XColor *color_tbl; int width; int height; int pad; { int x, y; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { *dst_data = color_tbl[ (CARD8)*dst_data ].pixel; dst_data++; } dst_data = (CARD16*)( (char*)dst_data + pad ); } } static void PalettePix8( dst_data, color_tbl, width, height, pad ) CARD8 *dst_data; XColor *color_tbl; int width; int height; int pad; { int x, y; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { *dst_data = color_tbl[ (CARD8)*dst_data ].pixel; dst_data++; } dst_data = (char*)dst_data + pad ; } } /******** PickNearColor ******** * カラーマップにある最も近い色を得る * 色(カラーセル)の確保に失敗した場合の処理 */ static int PickNearColor( palette, color_return ) unsigned char *palette; XColor *color_return; { XColor color_tbl[ 256 ]; int n_cmap_color; long dist, nearest; int nearest_index; int red_dist, green_dist, blue_dist; int i; /* 現行のカラーマップ上の色を取り出す */ { int dCells = DisplayCells( Disp, DefaultScreen(Disp) ); n_cmap_color = (dCells < 256) ? dCells : 256 ; } for( i = 0; i < n_cmap_color; i++ ) { color_tbl[i].pixel = (unsigned long) i; } XQueryColors( Disp, MyColorMap, color_tbl, n_cmap_color ); /* 距離的に最も近い色のピクセル値を拾う */ nearest = 0xFF * 0xFF * 3 + 1; nearest_index = -1; for( i=0; i< n_cmap_color; i++ ) { red_dist = palette[ 0 ] - (color_tbl[i].red >> 8); green_dist = palette[ 1 ] - (color_tbl[i].green >> 8); blue_dist = palette[ 2 ] - (color_tbl[i].blue >> 8); dist = (red_dist * red_dist) + (green_dist * green_dist) + (blue_dist * blue_dist); if( dist < nearest ) { nearest = dist; nearest_index = i; } } if( nearest_index < 0 ) { return EXIT_FAILURE ; } color_return->pixel = color_tbl[ nearest_index ].pixel; color_return->red = color_tbl[ nearest_index ].red; color_return->green = color_tbl[ nearest_index ].green; color_return->blue = color_tbl[ nearest_index ].blue; return EXIT_SUCCESS ; } /******** CreateMyCursor ******* * ビットマップデータからカーソルを生成する * (サイズは32x32固定) */ Cursor CreateMyCursor( win, f_bits, b_bits ) Window win; unsigned char *f_bits; unsigned char *b_bits; { Cursor cur; Pixmap front; Pixmap mask; XColor c1, c2, cc; #define CURSOR_SIZE 32 XAllocNamedColor( Disp, MyColorMap, "black", &c1, &cc ); XAllocNamedColor( Disp, MyColorMap, "white", &c2, &cc ); front = XCreateBitmapFromData( Disp, win, f_bits, CURSOR_SIZE, CURSOR_SIZE ); mask = XCreateBitmapFromData( Disp, win, b_bits, CURSOR_SIZE, CURSOR_SIZE ); cur = XCreatePixmapCursor( Disp, front, mask, &c1, &c2, 0, 0 ); XFreePixmap( Disp, front ); XFreePixmap( Disp, mask ); return cur; } /******** End of File ********/