Main Page Data Structures File List Data Fields Globals Related Pages

# bitmap.cpp

Go to the documentation of this file.

    00001 /*  Bitmap functions
    00002
    00003     27.06.2001: tk, initial implementation.
    00004
    00005     Copyright (c)2000 by Thomas Kindler, thomas.kindler@gmx.de
    00006
    00007     This program is free software; you can redistribute it and/or
    00008     modify it under the terms of the GNU General Public License as
    00009     published by the Free Software Foundation; either version 2 of
    00010     the License, or (at your option) any later version. Read the
    00011     full License at http://www.gnu.org/copyleft for more details.
    00012 */
    00013
    00014 // include files -----
    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;   // make size a multiple of two.
    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   // clip x/u coordinates
    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   // clip y/v coordinates
    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   // calculate destination masks
    00405   //
    00406   unsigned char fbm, lbm;
    00407   fbm = 0xff << (   y & 7);
    00408   lbm = 0xff >> (-y-h & 7);
    00409
    00410   // calculate number of pages
    00411   //
    00412   int pages = ((y+h+7)>>3) - (y>>3);
    00413   if (pages == 1)
    00414     fbm &= lbm;
    00415
    00416   // calculate pixel shift
    00417   //
    00418   int shift = (v&7)-(y&7);
    00419   if (shift < 0) {
    00420     v     -= 8;
    00421     shift &= 7;
    00422   }
    00423
    00424 /*
    00425   printf("dst: "); BM_Info(dst);
    00426   printf("src: "); BM_Info(src);
    00427   printf(
    00428     "  %p, x=%d, y=%d, %p, u=%d, v=%d,\n"
    00429     "  w=%d, pages=%d, shift=%d, fbm=%02x, lbm=%02x, mode=%d\n",
    00430     dst, x, y, src, u, v, w, pages, shift, fbm, lbm, mode
    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 }