Добрый день! Написал класс для загрузки изображения и обрезки окна по этому изображению... Но возникли две проблемы:
1. При наложении рисунка на обрезанное окно рисунок смещается на 1 пиксель вправо и вниз...
2. При создании окна по рисунку с нечетными размерами(например: 30х30, 50х50 и т.д.) происходит искажение
А вот, собственно, и реализация класса:
// TYPES //////////////////////////////////////////////////////
typedef struct BITMAP_FILE_TYPE
{
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
PALETTEENTRY palette[256];
UCHAR *buffer;
}BITMAP_FILE, *BITMAP_FILE_PTR;
typedef struct BITMAP_IMAGE_TYPE
{
COORD pos; // координаты изображения
int width; // размер изображения по горизонтали
int height; // размер изображения по вертикали
int sizeImage; // размер изображения в байтах
COLORREF color_key; // прозрачный цвет
int byte_pixel; // байт на пиксел
int **buffer; // изображение
}BITMAP_IMAGE, *BITMAP_IMAGE_PTR;
///////////////////////////////////////////
//классы
class CControlUser
{
private:
BITMAP_IMAGE_PTR image;
public:
CControlUser();
~CControlUser();
int LoadBitmapImage(char*, COLORREF, int=0, int=0);
HRGN CreateWindowOnBitmap(HRGN);
void FlipBitmap(BITMAP_FILE_PTR);
void DrawBitmap(HDC);
};
Загрузка изображения
int CControlUser::LoadBitmapImage(char *filename, COLORREF color_key, int x, int y)
{
FILE *file;
BITMAP_FILE_PTR bitmap = new BITMAP_FILE;
if((file = fopen(filename, "rb")) == NULL)
return 0;
fread(&bitmap->bfh, sizeof(BITMAPFILEHEADER), 1, file);
if(bitmap->bfh.bfType != BITMAP_ID)
{
fclose(file);
return -1;
}
fread(&bitmap->bih, sizeof(BITMAPINFOHEADER), 1, file);
fseek(file, -(int)(bitmap->bih.biSizeImage), SEEK_END);
if(bitmap->bih.biBitCount == 24)
{
if(!(bitmap->buffer = new UCHAR[bitmap->bih.biSizeImage]))
{
fclose(file);
return -2;
}
fread(bitmap->buffer, bitmap->bih.biSizeImage, 1, file);
}
else
{
fclose(file);
return -3;
}
FlipBitmap(bitmap);
fclose(file);
image->height = bitmap->bih.biHeight;
image->width = bitmap->bih.biWidth;
image->sizeImage = bitmap->bih.biSizeImage;
image->pos.X = x;
image->pos.Y = y;
image->color_key = color_key;
image->byte_pixel = bitmap->bih.biBitCount/8;
image->buffer = new int*[bitmap->bih.biHeight];
for(int pos = 0; pos < bitmap->bih.biHeight; pos++)
image->buffer[pos] = new int[bitmap->bih.biWidth];
int red, green, blue;
for(int pos_y = 0; pos_y < bitmap->bih.biHeight; pos_y++)
{
for(int pos_x = 0; pos_x < bitmap->bih.biWidth; pos_x++)
{
int index = pos_y*(bitmap->bih.biWidth*image->byte_pixel)+pos_x*image->byte_pixel;
red = bitmap->buffer[index];
green = bitmap->buffer[index+1];
blue = bitmap->buffer[index+2];
image->buffer[pos_y][pos_x] = RGB_24(red,green,blue);
}
}
return 1;
}
Создание региона по изображению
HRGN CControlUser::CreateWindowOnBitmap(HRGN rgn)
{
HRGN temp_rgn;
int left_pos; // начало строки с непрозрачными пикселами
int red;
int green;
int blue;
rgn = CreateRectRgn(0,0,0,0);
for (int pos_y = 0; pos_y < image->height; pos_y++)
{
left_pos = -1;
for (int pos_x = 0; pos_x < image->width; pos_x++)
{
if (image->buffer[pos_y][pos_x] != image->color_key)
{
if (left_pos < 0)
{
left_pos = pos_x;
}
else
if (pos_x == (image->width - 1))
{
temp_rgn = CreateRectRgn(left_pos, pos_y, pos_x, pos_y+1);
CombineRgn( rgn, rgn, temp_rgn, RGN_OR);
left_pos = -1;
}
}
else
if (left_pos >= 0)
{
temp_rgn = CreateRectRgn(left_pos, pos_y, pos_x, pos_y+1);
CombineRgn( rgn, rgn, temp_rgn, RGN_OR);
left_pos = -1;
}
}
}
return rgn;
}
Зеркальное отображение изображения
void CControlUser::FlipBitmap(BITMAP_FILE_PTR bitmap)
{
int red, green, blue;
int s_bitmap = bitmap->bih.biSizeImage;
int width = (bitmap->bih.biWidth*3);
int height = bitmap->bih.biHeight;
for(int index = 0; index < height/2; index++)
{
int left_pos_begin = index*width;
int left_pos_end = (index+1)*width+2;
for(int pos = 0; pos < width; pos += 3)
{
red = bitmap->buffer[(left_pos_begin+pos)+2];
green = bitmap->buffer[(left_pos_begin+pos)+1];
blue = bitmap->buffer[(left_pos_begin+pos)];
bitmap->buffer[(left_pos_begin+pos)] = bitmap->buffer[((s_bitmap-left_pos_end)+pos)+2];
bitmap->buffer[(left_pos_begin+pos)+1] = bitmap->buffer[((s_bitmap-left_pos_end)+pos)+1];
bitmap->buffer[(left_pos_begin+pos)+2] = bitmap->buffer[((s_bitmap-left_pos_end)+pos)];
bitmap->buffer[((s_bitmap-left_pos_end)+pos)] = red;
bitmap->buffer[((s_bitmap-left_pos_end)+pos)+1] = green;
bitmap->buffer[((s_bitmap-left_pos_end)+pos)+2] = blue;
}
}
}
Вывод на экран изображения
void CControlUser::DrawBitmap(HDC hdc)
{
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hBitmapMem = CreateCompatibleBitmap(hdc, image->width, image->height);
SelectObject(hdcMem, hBitmapMem);
for(int pos_y = 0; pos_y < image->height; pos_y++)
{
for(int pos_x = 0; pos_x < image->width; pos_x++)
{
if((image->buffer[pos_y][pos_x]) != image->color_key)
SetPixel(hdcMem,(image->pos.X+pos_x),(image->pos.Y+pos_y),(COLORREF)image->buffer[pos_y][pos_x]);
}
}
BitBlt(hdc,0, 0, image->width, image->height, hdcMem, 0, 0, SRCCOPY);
}