/** \file * \brief Image Resource. * * See Copyright Notice in "iup.h" */ #include #include #include #include #include "iup.h" #include "iup_object.h" #include "iup_attrib.h" #include "iup_str.h" #include "iup_image.h" #include "iupwin_drv.h" /* RGB in RGBA DIBs are pre-multiplied by alpha to AlphaBlend usage. */ #define iupALPHAPRE(_src, _alpha) (((_src)*(_alpha))/255) static int winDibNumColors(BITMAPINFOHEADER* bmih) { if (bmih->biBitCount > 8) { if (bmih->biCompression == BI_BITFIELDS) return 3; else return 0; } else { if (bmih->biClrUsed != 0) return bmih->biClrUsed; else return 1 << bmih->biBitCount; } } void iupdrvImageGetRawData(void* handle, unsigned char* imgdata) { int x, y, w, h, bpp, bmp_line_size, bits_size; BYTE* bits; HANDLE hHandle = (HANDLE)handle; void* dib = GlobalLock(hHandle); BITMAPINFOHEADER* bmih = (BITMAPINFOHEADER*)dib; w = bmih->biWidth; h = abs(bmih->biHeight); bpp = iupImageNormBpp(bmih->biBitCount); bmp_line_size = ((w * bmih->biBitCount + 31) / 32) * 4; /* DWORD aligned, 4 bytes boundary in a N bpp image */ bits_size = bmp_line_size*h; bits = ((BYTE*)dib) + sizeof(BITMAPINFOHEADER) + winDibNumColors(bmih)*sizeof(RGBQUAD); /* windows bitmaps are bottom up */ /* imgdata is bottom up */ if (bmih->biHeight < 0) bits = bits + (bits_size - bmp_line_size); /* start of last line */ if (bpp == 8) { for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { switch (bmih->biBitCount) { case 1: *imgdata++ = (unsigned char)((bits[x / 8] >> (7 - x % 8)) & 0x01); break; case 4: *imgdata++ = (unsigned char)((bits[x / 2] >> ((1 - x % 2) * 4)) & 0x0F); break; case 8: *imgdata++ = bits[x]; break; } } if (bmih->biHeight < 0) bits -= bmp_line_size; else bits += bmp_line_size; } } else { int offset, planesize; unsigned short color; unsigned int rmask = 0, gmask = 0, bmask = 0, roff = 0, goff = 0, boff = 0; /* pixel bit mask control when reading 16 and 32 bpp images */ unsigned char *red, *green, *blue, *alpha; planesize = w*h; red = imgdata; green = imgdata+planesize; blue = imgdata+2*planesize; alpha = imgdata+3*planesize; if (bmih->biBitCount == 16) offset = bmp_line_size; /* do not increment for each pixel, jump line */ else offset = bmp_line_size - (w*bmih->biBitCount)/8; /* increment for each pixel, jump pad */ if (bmih->biCompression == BI_BITFIELDS) { unsigned int Mask; unsigned int* palette = (unsigned int*)(((BYTE*)bmih) + sizeof(BITMAPINFOHEADER)); rmask = Mask = palette[0]; while (!(Mask & 0x01)) {Mask >>= 1; roff++;} gmask = Mask = palette[1]; while (!(Mask & 0x01)) {Mask >>= 1; goff++;} bmask = Mask = palette[2]; while (!(Mask & 0x01)) {Mask >>= 1; boff++;} } else if (bmih->biBitCount == 16) { bmask = 0x001F; gmask = 0x03E0; rmask = 0x7C00; boff = 0; goff = 5; roff = 10; } for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { if (bmih->biBitCount == 16) { color = ((unsigned short*)bits)[x]; *red++ = (unsigned char)((((rmask & color) >> roff) * 255) / (rmask >> roff)); *green++ = (unsigned char)((((gmask & color) >> goff) * 255) / (gmask >> goff)); *blue++ = (unsigned char)((((bmask & color) >> boff) * 255) / (bmask >> boff)); } else { *blue++ = *bits++; *green++ = *bits++; *red++ = *bits++; if (bmih->biBitCount == 32) { if (alpha) *alpha++ = *bits++; else bits++; } } } bits += offset; if (bmih->biHeight < 0) bits -= 2*bmp_line_size; } } GlobalUnlock(hHandle); } void* iupdrvImageCreateImageRaw(int width, int height, int bpp, iupColor* colors, int colors_count, unsigned char *imgdata) { int y,x,bmp_line_size,channels,bits_size,header_size; HANDLE hHandle; BYTE* bits; /* DIB bitmap bits, created in CreateDIBSection and filled here */ void* dib; BITMAPINFOHEADER* bmih; bmp_line_size = ((width * bpp + 31) / 32) * 4; /* DWORD aligned, 4 bytes boundary in a N bpp image */ bits_size = bmp_line_size*height; header_size = sizeof(BITMAPINFOHEADER) + colors_count*sizeof(RGBQUAD); hHandle = GlobalAlloc(GMEM_MOVEABLE, header_size+bits_size); if (!hHandle) return NULL; dib = GlobalLock(hHandle); bits = ((BYTE*)dib) + header_size; bmih = (BITMAPINFOHEADER*)dib; memset(bmih, 0, sizeof(BITMAPINFOHEADER)); bmih->biSize = sizeof(BITMAPINFOHEADER); bmih->biWidth = width; bmih->biHeight = height; bmih->biPlanes = 1; /* not the same as PLANES */ bmih->biBitCount = (WORD)bpp; bmih->biCompression = BI_RGB; bmih->biClrUsed = colors_count; if (colors_count) { RGBQUAD* bitmap_colors = (RGBQUAD*)(((BYTE*)dib) + sizeof(BITMAPINFOHEADER)); int i; for (i=0;ibiWidth; if (h) *h = abs(bmih->biHeight); if (bpp) *bpp = iupImageNormBpp(bmih->biBitCount); if (bmih->biBitCount <= 8) { RGBQUAD* bitmap_colors = (RGBQUAD*)(((BYTE*)bmih) + sizeof(BITMAPINFOHEADER)); int i; if (bmih->biClrUsed != 0) *colors_count = bmih->biClrUsed; else *colors_count = 1 << bmih->biBitCount; for (i=0;i<*colors_count;i++) { colors[i].r = bitmap_colors[i].rgbRed; colors[i].g = bitmap_colors[i].rgbGreen; colors[i].b = bitmap_colors[i].rgbBlue; } } GlobalUnlock(hHandle); return 1; } static int winImageInitDibColors(iupColor* colors, RGBQUAD* bmpcolors, int colors_count, unsigned char bg_r, unsigned char bg_g, unsigned char bg_b, int make_inactive) { int i, ret = 0; for (i=0;ibiSize = sizeof(BITMAPINFOHEADER); bmih->biWidth = width; bmih->biHeight = height; bmih->biPlanes = 1; /* not the same as PLANES */ bmih->biBitCount = (WORD)bpp; bmih->biCompression = BI_RGB; bmih->biClrUsed = colors_count; if (colors_count) { /* since colors are only passed to the CreateDIBSection here, must update BGCOLOR and inactive here */ RGBQUAD* bitmap_colors = (RGBQUAD*)(((BYTE*)bmih) + sizeof(BITMAPINFOHEADER)); if (winImageInitDibColors(colors, bitmap_colors, colors_count, bg_r, bg_g, bg_b, make_inactive)) iupAttribSetStr(ih, "_IUP_BGCOLOR_DEPEND", "1"); } hDC = GetDC(NULL); hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)bmih, DIB_RGB_COLORS, (void**)bits, NULL, 0x0); ReleaseDC(NULL, hDC); free(bmih); return hBitmap; } void* iupdrvImageCreateImage(Ihandle *ih, const char* bgcolor, int make_inactive) { unsigned char bg_r = 0, bg_g = 0, bg_b = 0; int y,x,bmp_line_size,data_line_size, width = ih->currentwidth, height = ih->currentheight, channels = iupAttribGetInt(ih, "CHANNELS"), flat_alpha = iupAttribGetBoolean(ih, "FLAT_ALPHA"), bpp = iupAttribGetInt(ih, "BPP"); unsigned char *imgdata = (unsigned char*)iupAttribGetStr(ih, "WID"); HBITMAP hBitmap; BYTE* bits; /* DIB bitmap bits, created in CreateDIBSection and filled here */ iupStrToRGB(bgcolor, &bg_r, &bg_g, &bg_b); hBitmap = winImageCreateBitmap(ih, width, height, bpp, &bits, bg_r, bg_g, bg_b, make_inactive); if (!hBitmap) return NULL; bmp_line_size = ((width * bpp + 31) / 32) * 4; /* DWORD aligned, 4 bytes boundary in a N bpp image */ data_line_size = width*channels; /* windows bitmaps are bottom up */ imgdata += (height-1)*data_line_size; /* iupimage is top down */ for (y=0; ycurrentwidth, height = ih->currentheight, channels = iupAttribGetInt(ih, "CHANNELS"), bpp = iupAttribGetInt(ih, "BPP"); unsigned char *imgdata = (unsigned char*)iupAttribGetStr(ih, "WID"); HBITMAP hBitmap; BYTE* bitmask, *bitmask_ptr; iupColor colors[256]; if (bpp == 8) iupImageInitColorTable(ih, colors, &colors_count); mask_line_size = ((width + 15) / 16) * 2; /* WORD aligned, 2 bytes boundary in a 1 bpp image */ data_line_size = width*channels; bitmask = malloc(height * mask_line_size); memset(bitmask, 0, height * mask_line_size); /* opaque */ /* mask and iupimage are top down */ bitmask_ptr = bitmask; for (y=0; y