00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "bitmap.h"
00017 #include <assert.h>
00018 #include <stdlib.h>
00019 #include <stdio.h>
00020 #include <mem.h>
00021
00022
00026 static BM_BlitFunc *blitFuncs[] = {
00027 NULL, BM_Blit_Nor, BM_Blit_NotAnd, BM_Blit_NotCopy,
00028 BM_Blit_AndNot, NULL, BM_Blit_Xor, BM_Blit_Nand,
00029 BM_Blit_And, BM_Blit_Nexor, NULL, BM_Blit_NotOr,
00030 BM_Blit_Copy, BM_Blit_OrNot, BM_Blit_Or, NULL
00031 };
00032
00033
00044 Bitmap *BM_Alloc(int w, int h)
00045 {
00046 unsigned size = w*((h+7)>>3);
00047 size += size & 1;
00048
00049 Bitmap *bm = (Bitmap*)malloc(sizeof(Bitmap)+size);
00050 if (!bm)
00051 return NULL;
00052
00053 bm->width = w;
00054 bm->height = h;
00055 bm->bmBitsSize = size;
00056 return bm;
00057 }
00058
00059
00066 Bitmap *BM_Copy(Bitmap *bm)
00067 {
00068 Bitmap *copy = BM_Alloc(bm->width, bm->height);
00069 if (!copy)
00070 return NULL;
00071
00072 memcpy(copy->bmBits, bm->bmBits, copy->bmBitsSize);
00073 return copy;
00074 }
00075
00076
00077
00087 void BM_Free(Bitmap *bm)
00088 {
00089 if (bm) {
00090 bm->width = 0;
00091 bm->height = 0;
00092 bm->bmBitsSize = 0;
00093 free(bm);
00094 }
00095 }
00096
00097
00104 void BM_Clear(Bitmap *bm, char pattern)
00105 {
00106 memset(bm->bmBits, pattern, bm->bmBitsSize);
00107 }
00108
00109
00115 void BM_Invert(Bitmap *bm)
00116 {
00117 char *bits = bm->bmBits;
00118 unsigned size = bm->bmBitsSize;
00119
00120 asm {
00121 pushf
00122 push ax
00123 push cx
00124 push si
00125 push di
00126 push ds
00127 push es
00128 cld
00129
00130 lds si, bits
00131 les di, bits
00132
00133 mov cx, size
00134 shr cx, 1
00135 l1: lodsw
00136 not ax
00137 stosw
00138 loop l1
00139
00140 pop es
00141 pop ds
00142 pop di
00143 pop si
00144 pop cx
00145 pop ax
00146 popf
00147 }
00148 }
00149
00150
00161 void BM_Scroll(Bitmap *bm, int dx, int dy)
00162 {
00163 Bitmap *tmp = BM_Copy(bm);
00164 assert(tmp != NULL);
00165
00166 BM_Clear(bm);
00167 BM_Blit(bm, -dx, -dy, tmp);
00168 BM_Free(tmp);
00169 }
00170
00171
00183 Bitmap *BM_Load(char *fn)
00184 {
00185 printf("loading \"%s\".. ", fn);
00186
00187 FILE *f = fopen( fn, "rb" );
00188 if (!f) {
00189 perror("");
00190 return NULL;
00191 }
00192
00193 BitmapFileHeader bmfh = {0};
00194 fread(&bmfh, 1, sizeof(bmfh), f);
00195
00196 if (bmfh.bfType != 0x4D42 ||
00197 bmfh.biPlanes != 1 ||
00198 bmfh.biBitCount != 1 ||
00199 bmfh.biCompression != 0 )
00200 {
00201 printf( "invalid format.\n" );
00202 fclose(f);
00203 return NULL;
00204 }
00205
00206 fseek(f, bmfh.bfOffBits, SEEK_SET);
00207
00208 Bitmap *bm = BM_Alloc(bmfh.biWidth, abs(bmfh.biHeight));
00209 if (!bm) {
00210 printf("can't alloc bitmap.\n");
00211 fclose(f);
00212 return NULL;
00213 }
00214 BM_Clear(bm);
00215
00216 char pad[4];
00217 int padBytes = (4-(bmfh.biWidth+7)>>3) & 3;
00218
00219 for (int y=abs(bmfh.biHeight)-1; y>=0; y--) {
00220 unsigned char *dst = bm->bmBits + (y>>3)*bm->width;
00221 unsigned char ymask = 1<<(y&7), xmask = 0, src;
00222
00223 for (int x=0; x<bm->width; x++) {
00224 if (!xmask) {
00225 src = ~fgetc(f);
00226 xmask = 0x80;
00227 }
00228 if (src & xmask)
00229 *dst |= ymask;
00230 xmask >>= 1;
00231 dst++;
00232 }
00233 fread(pad, 1, padBytes, f);
00234 }
00235
00236 fclose(f);
00237 printf( "%dx%d (%u bytes).\n", bm->width,
00238 bm->height, bm->bmBitsSize);
00239 return bm;
00240 }
00241
00242
00252 void BM_Save(Bitmap *bm, char *fn)
00253 {
00254 BitmapFileHeader bmfh;
00255
00256 int imagesize = (((bm->width+31)>>5)<<2) * bm->height;
00257
00258 bmfh.bfType = 0x4D42;
00259 bmfh.bfSize = sizeof(bmfh) + imagesize;
00260 bmfh.bfReserved1 = 0;
00261 bmfh.bfReserved2 = 0;
00262 bmfh.bfOffBits = sizeof(bmfh);
00263
00264 bmfh.biSize = 40;
00265 bmfh.biWidth = bm->width;
00266 bmfh.biHeight = bm->height;
00267 bmfh.biPlanes = 1;
00268 bmfh.biBitCount = 1;
00269 bmfh.biCompression = 0;
00270 bmfh.biSizeImage = imagesize;
00271
00272 bmfh.biXPelsPerMeter = DPI2PPM(72);
00273 bmfh.biYPelsPerMeter = DPI2PPM(72);
00274 bmfh.biClrUsed = 2;
00275 bmfh.biClrImportant = 2;
00276
00277 bmfh.color0 = BMP_BGCOLOR;
00278 bmfh.color1 = BMP_FGCOLOR;
00279
00280 printf("saving \"%s\".. ", fn);
00281 FILE *f = fopen(fn, "wb");
00282 if (!f) {
00283 perror("");
00284 return;
00285 }
00286
00287 fwrite(&bmfh, sizeof(bmfh), 1, f);
00288
00289 char pad[4] = {0};
00290 int padlen = (4-(bm->width+7)>>3) & 3;
00291
00292 for (int y=bm->height-1; y>=0; y--) {
00293 unsigned char *src = &bm->bmBits[(y>>3)*bm->width];
00294 unsigned char ymask = 1<<(y&7), xmask = 0x80, c=0;
00295
00296 for (int x=0; x<bm->width; x++) {
00297 if (*src++ & ymask)
00298 c |= xmask;
00299 xmask >>= 1;
00300 if (!xmask) {
00301 fputc(c, f);
00302 c = 0;
00303 xmask = 0x80;
00304 }
00305 }
00306 if (xmask != 0x80)
00307 fputc(c, f);
00308
00309 fwrite(pad, padlen, 1, f);
00310 }
00311
00312 fclose(f);
00313 printf("ok.\n");
00314 }
00315
00316
00335 void BM_Blit( Bitmap *dst, int x, int y, Bitmap *src, int u, int v,
00336 int w, int h, int mode )
00337 {
00338 if (w==-1) w = src->width;
00339 if (h==-1) h = src->height;
00340
00341
00342
00343 if (x<0) {
00344 u += -x;
00345 w -= -x;
00346 x = 0;
00347 }
00348 if (x+w >= dst->width)
00349 w -= (x+w)-dst->width;
00350
00351 if (u<0) {
00352 x += -u;
00353 w -= -u;
00354 u = 0;
00355 }
00356 if (u+w >= src->width)
00357 w -= (u+w)-src->width;
00358
00359 if (w<=0)
00360 return;
00361
00362
00363
00364 if (y<0)
00365 v += -y, h -= -y, y = 0;
00366 if (y+h >= dst->height)
00367 h -= (y+h)-dst->height;
00368
00369 if (v<0)
00370 y += -v, h -= -v, v = 0;
00371 if (v+h >= src->height)
00372 h -= (v+h) - src->height;
00373
00374 if (h<=0)
00375 return;
00376
00377 BM_FastBlit(dst, x, y, src, u, v, w, h, mode);
00378 }
00379
00380
00398 void BM_FastBlit(Bitmap *dst, int x, int y, Bitmap *src, int u, int v,
00399 int w, int h, int mode)
00400 {
00401 if (w==-1) w = src->width;
00402 if (h==-1) h = src->height;
00403
00404
00405
00406 unsigned char fbm, lbm;
00407 fbm = 0xff << ( y & 7);
00408 lbm = 0xff >> (-y-h & 7);
00409
00410
00411
00412 int pages = ((y+h+7)>>3) - (y>>3);
00413 if (pages == 1)
00414 fbm &= lbm;
00415
00416
00417
00418 int shift = (v&7)-(y&7);
00419 if (shift < 0) {
00420 v -= 8;
00421 shift &= 7;
00422 }
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433 BM_BlitFunc *blitter = blitFuncs[mode & 15];
00434 if (blitter)
00435 blitter( &dst->bmBits[x+(y>>3)*dst->width], dst->width,
00436 &src->bmBits[u+(v>>3)*src->width], src->width,
00437 w, pages, shift, fbm, lbm );
00438 }