Rev 76910 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** GraphApp - Cross-Platform Graphics Programming Library.** File: bitmaps.c -- functions for creating a detroying bitmaps.* Platform: Windows Version: 2.40 Date: 1998/05/05** Version: 1.00 Changes: Original version by Lachlan Patrick.* Version: 2.00 Changes: New object class system implemented.* Version: 2.15 Changes: Improved bitmap data formats.* Version: 2.30 Changes: Now uses bitmap_base.* Version: 2.40 Changes: Fast image to bitmap conversion.*//* Copyright (C) 1993-1998 Lachlan PatrickThis file is part of GraphApp, a cross-platform C graphics library.GraphApp is free software; you can redistribute it and/or modify itunder the terms of the GNU Library General Public License.GraphApp is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY.See the file COPYLIB.TXT for details.*/#include "internal.h"/** Internal bitmap deletion function.*/static void private_delbitmap(bitmap obj){if (obj->handle)DeleteObject((HBITMAP) obj->handle);}/** Create/return the base bitmap object.*/static object get_bitmap_base(void){static object bitmap_base = NULL;if (! bitmap_base)bitmap_base = new_object(BaseObject, 0, NULL);return bitmap_base;}/** Create a white bitmap.*/bitmap newbitmap(int width, int height, int depth){BITMAP bm;HBITMAP hb, old;HDC dc, screendc;screendc = GetDC(0); /* get screen dc */if (depth == 1) /* monochrome bitmap required */{hb = CreateBitmap(width, height, 1, 1, 0);}else /* colour bitmap required */{hb = CreateCompatibleBitmap(screendc, width, height);}if (! hb) {ReleaseDC(0, screendc);return NULL;}dc = CreateCompatibleDC(screendc);old = SelectObject(dc, hb);PatBlt(dc, 0, 0, width, height, WHITENESS);SelectObject(dc, old);DeleteDC(dc);ReleaseDC(0, screendc);GetObject(hb, sizeof(BITMAP), (LPSTR) &bm);bitmap obj = new_object(BitmapObject, hb, get_bitmap_base());if (! obj) {DeleteObject(hb);return NULL;}obj->rect = rect(0,0,width,height);obj->depth = (bm.bmPlanes * bm.bmBitsPixel);obj->die = private_delbitmap;return obj;}/** Check an image to see if there are any transparent pixels.* Return 1 as soon as a transparent pixel is found, 0 if none are.*/PROTECTEDint has_transparent_pixels(image img){int i, width, height, total;rgb *palette;GAbyte *pixel8;rgb *pixel32;rgb col;if (! img)return 0;width = getwidth(img);height = getheight(img);total = width * height;palette = getpalette(img);pixel8 = getpixels(img);pixel32 = (rgb *) pixel8;if (getdepth(img) == 8) {for (i=0; i < total; i++) {col = pixel8[i];col = palette[col];if (getalpha(col) > 0x7F)return 1;}}else {for (i=0; i < total; i++) {col = pixel32[i];if (getalpha(col) > 0x7F)return 1;}}return 0;}/** Create a bitmap version of an image.*/// See also http://msdn.microsoft.com/en-us/library/dd183353%28v=VS.85%29.aspxbitmap imagetobitmap(image img){unsigned row_bytes;unsigned size;if (!img) return NULL;/* remember some facts about the image */int width = getwidth(img), height = getheight(img);int depth = getdepth(img);rgb *palette = getpalette(img);int palsize = getpalettesize(img);GAbyte *pixel8 = getpixels(img);rgb *pixel32 = (rgb *) pixel8;/* create DIB info in memory */size = sizeof(BITMAPINFOHEADER) + 4; /* Why + 4 ? */size += (sizeof(RGBQUAD) * palsize);/* rows need to be whole (4-byte) words */if (depth == 8) row_bytes = ((width + 3) / 4) * 4;else if (depth == 24) row_bytes = (((width * 3) + 3) / 4) * 4;else row_bytes = 4 * width;size += (row_bytes * height);/* create the block, align on LONG boundarymalloc will have done the alignment, which needs tobe for pointers.*/GAbyte *block = array(size, GAbyte);BITMAPINFO *bmi = (BITMAPINFO *) block;/* assign header info */bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);bmi->bmiHeader.biWidth = width;bmi->bmiHeader.biHeight = -height; // use negative value to flipbmi->bmiHeader.biPlanes = 1;bmi->bmiHeader.biBitCount = depth;bmi->bmiHeader.biCompression = BI_RGB;bmi->bmiHeader.biClrUsed = palsize;/* assign colour table */for (int i = 0; i < palsize; i++) {rgb colour = palette[i];GAbyte *data = (GAbyte *) (& bmi->bmiColors[i]);data[0] = getblue(colour);data[1] = getgreen(colour);data[2] = getred(colour);data[3] = 0;}/* assign the bitmap data itself */GAbyte *data = (GAbyte *) (&bmi->bmiColors[palsize]);if (depth == 8)for (unsigned y = 0; y < height; y++) {// memcpy(data + y * row_bytes, pixel8 + y * width, width);for (unsigned x = 0; x < width; x++)data[y * row_bytes + x] = pixel8[y * width + x];}else if (depth == 24)for (unsigned y = 0; y < height; y++) {for (unsigned x = 0; x < width; x++) {rgb colour = pixel32[y * width + x];int i = y * row_bytes + 3*x;data[i] = getblue(colour);data[i+1] = getgreen(colour);data[i+2] = getred(colour);}}else memcpy(data, pixel32, 4*height*width);/* Create the bitmap from the DIB data.Could also use CreateDIBsection */HDC screendc = GetDC(0);HBITMAP hb = CreateDIBitmap(screendc, &bmi->bmiHeader, CBM_INIT,data, bmi, DIB_RGB_COLORS);ReleaseDC(0, screendc);/* tidy up */discard(block);/* create the bitmap */bitmap obj = new_object(BitmapObject, hb, get_bitmap_base());if (!obj) {DeleteObject(hb);return NULL;}obj->rect = rect(0, 0, width, height);obj->depth = depth;obj->die = private_delbitmap;return obj;}#ifdef UNUSED/** The loadicon function returns a HBITMAP of an ICON from resources.*/static bitmap loadicon(const char *name){HICON i;HDC dc;HBITMAP old;bitmap obj;if (this_instance == 0)return NULL;if ((i = LoadIcon(this_instance, name)) == 0)return NULL;if ((obj = newbitmap(32, 32, 0)) == NULL)return NULL;dc = CreateCompatibleDC(0);old = SelectObject(dc, (HBITMAP)obj->handle);DrawIcon(dc, 0, 0, i);SelectObject(dc, old);DeleteDC(dc);DestroyIcon(i);return obj;}/** The loadpict function returns BITMAP resources.*/static bitmap loadpict(const char *name){BITMAP bm;HBITMAP hb;bitmap obj;if (this_instance == 0)return NULL;hb = LoadBitmap(this_instance, name);GetObject(hb, sizeof(BITMAP), (LPSTR) &bm);obj = new_object(BitmapObject, hb, get_bitmap_base());if (obj) {obj->rect = rect(0, 0, bm.bmWidth, bm.bmHeight);obj->depth = (bm.bmPlanes * bm.bmBitsPixel);obj->die = private_delbitmap;}return obj;}/** The loadbitmap function finds and returns bitmaps from resources,* or from an image file.*/bitmap loadbitmap(const char *name){bitmap obj;if ((obj = loadpict(name)) != NULL)return obj;if ((obj = loadicon(name)) != NULL)return obj;if ((obj = imagetobitmap(loadimage(name))) != NULL)return obj;return NULL;}/** The following functions are obsolete from version 2.4.*/void setbitmapdata(bitmap obj, unsigned char *data){rect r;int depth, size, row_bytes;int x, y;unsigned char *newdata = NULL;r = obj->rect;depth = obj->depth;/* Calculate source row bytes. */row_bytes = ((depth * r.width) + 7) / 8;/* Each row must be a multiple of 16 bits wide. */if (row_bytes % 2) {/* Odd number of bytes, must assign into new array. */size = (row_bytes+1) * r.height;newdata = array (size, GAbyte);if (! newdata)return;for (y=0; y<r.height; y++) {for (x=0; x<row_bytes; x++) {newdata[y*(row_bytes+1)+x] =data[y*row_bytes+x];}}SetBitmapBits((HBITMAP)obj->handle, size,(LPSTR)newdata);discard(newdata);} else {/* Correct format already! */size = row_bytes * r.height;SetBitmapBits((HBITMAP)obj->handle, size, (LPSTR)data);}}void getbitmapdata(bitmap obj, unsigned char *data){rect r;int depth, size, row_bytes;int x, y;unsigned char *newdata = NULL;r = obj->rect;depth = obj->depth;/* Calculate destination row bytes. */row_bytes = ((depth * r.width) + 7) / 8;/* Each row must be a multiple of 16 bits wide. */if (row_bytes % 2) {/* Odd number of bytes, must assign into new array. */size = (row_bytes+1) * r.height;newdata = array (size, GAbyte);if (! newdata)return;GetBitmapBits((HBITMAP)obj->handle, size,(LPSTR)newdata);for (y=0; y<r.height; y++) {for (x=0; x<row_bytes; x++) {data[y*row_bytes+x] =newdata[y*(row_bytes+1)+x];}}discard(newdata);} else {/* Correct format already! */size = row_bytes * r.height;GetBitmapBits((HBITMAP)obj->handle, size, (LPSTR)data);}}bitmap createbitmap(int width, int height, int depth, unsigned char *data){bitmap obj;if ((obj = newbitmap(width, height, depth)) == NULL)return NULL;if (data)setbitmapdata(obj, data);return obj;}#endifvoid getbitmapdata2(bitmap obj, unsigned char **data){rect r = obj->rect;int depth = 32, size, ret;BITMAPINFO bmi;bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);bmi.bmiHeader.biWidth = r.width;bmi.bmiHeader.biHeight = -r.height;bmi.bmiHeader.biPlanes = 1;bmi.bmiHeader.biBitCount = depth;bmi.bmiHeader.biCompression = BI_RGB;bmi.bmiHeader.biClrUsed = 0;size = 4 * r.width * r.height;*data = (unsigned char *) malloc(size);if(*data) {ret = GetDIBits(get_context(obj), (HBITMAP)obj->handle,0, r.height, (LPSTR)*data, &bmi, DIB_RGB_COLORS);if(!ret) {free(*data);*data = NULL;}}}