home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / xloadimg.zip / xloadimage.4.1 / merge.c < prev    next >
C/C++ Source or Header  |  1993-10-21  |  7KB  |  276 lines

  1. /* merge.c:
  2.  *
  3.  * merge two images
  4.  *
  5.  * jim frost 09.27.89
  6.  *
  7.  * Copyright 1989, 1990, 1991 Jim Frost.
  8.  * See included file "copyright.h" for complete copyright information.
  9.  */
  10.  
  11. #include "copyright.h"
  12. #include "image.h"
  13.  
  14. /* if merging bitmaps they don't have to be converted to
  15.  * 24-bit.  this saves a lot of space.
  16.  */
  17.  
  18. static Image *bitmapToBitmap(src, dest, atx, aty, clipw, cliph, verbose)
  19.      Image        *src, *dest;
  20.      unsigned int  atx, aty, clipw, cliph;
  21.      unsigned int  verbose;
  22. { unsigned int  destlinelen, srclinelen;
  23.   unsigned int  deststart;
  24.   unsigned int  flip;
  25.   unsigned int  x, y;
  26.   byte         *destline, *srcline;
  27.   byte          deststartmask;
  28.   byte          destmask, srcmask;
  29.   byte         *destpixel, *srcpixel;
  30.  
  31.   destlinelen= (dest->width / 8) + (dest->width % 8 ? 1 : 0);
  32.   srclinelen= (src->width / 8) + (src->width % 8 ? 1 : 0);
  33.   destline= dest->data + (aty * destlinelen);
  34.   srcline= src->data;
  35.   deststart= atx / 8;
  36.   deststartmask= 0x80 >> (atx % 8);
  37.   flip= ((*dest->rgb.red == *(src->rgb.red + 1)) &&
  38.      (*dest->rgb.green == *(src->rgb.green + 1)) &&
  39.      (*dest->rgb.blue == *(src->rgb.blue + 1)));
  40.   for (y= 0; y < cliph; y++) {
  41.     destpixel= destline + deststart;
  42.     srcpixel= srcline;
  43.     destmask= deststartmask;
  44.     srcmask= 0x80;
  45.     for (x= 0; x < clipw; x++) {
  46.       if (flip)
  47.     if (*srcpixel & srcmask)
  48.       *destpixel &= ~destmask;
  49.     else
  50.       *destpixel |= destmask;
  51.       else
  52.     if (*srcpixel & srcmask)
  53.       *destpixel |= destmask;
  54.     else
  55.       *destpixel &= ~destmask;
  56.       destmask >>= 1;
  57.       srcmask >>= 1;
  58.       if (destmask == 0) {
  59.     destmask= 0x80;
  60.     destpixel++;
  61.       }
  62.       if (srcmask == 0) {
  63.     srcmask= 0x80;
  64.     srcpixel++;
  65.       }
  66.     }
  67.     destline += destlinelen;
  68.     srcline += srclinelen;
  69.   }
  70.   if (verbose)
  71.     printf("done\n");
  72.   return(dest);
  73. }
  74.  
  75. static Image *anyToTrue(src, dest, atx, aty, clipw, cliph, verbose)
  76.      Image        *src, *dest;
  77.      unsigned int  atx, aty, clipw, cliph;
  78.      unsigned int  verbose;
  79. { Pixel         fg, bg;
  80.   unsigned int  destlinelen, srclinelen;
  81.   unsigned int  deststart;
  82.   unsigned int  x, y;
  83.   byte         *destline, *srcline;
  84.   byte         *destpixel, *srcpixel;
  85.   byte          srcmask;
  86.   Pixel         pixval;
  87.  
  88.   if (!TRUEP(dest))
  89.     dest= expand(dest);
  90.  
  91.   switch (src->type) {
  92.   case IBITMAP:
  93.     fg= RGB_TO_TRUE(src->rgb.red[1], src->rgb.green[1], src->rgb.blue[1]);
  94.     bg= RGB_TO_TRUE(src->rgb.red[0], src->rgb.green[0], src->rgb.blue[0]);
  95.     destlinelen= dest->width * dest->pixlen;
  96.     srclinelen= (src->width / 8) + (src->width % 8 ? 1 : 0);
  97.     destline= dest->data + (aty * destlinelen);
  98.     srcline= src->data;
  99.     deststart= atx * dest->pixlen;
  100.     for (y= 0; y < cliph; y++) {
  101.       destpixel= destline + deststart;
  102.       srcpixel= srcline;
  103.       srcmask= 0x80;
  104.       for (x= 0; x < clipw; x++) {
  105.     valToMem((*srcpixel & srcmask ? fg : bg), destpixel, 3);
  106.     destpixel += 3;
  107.     srcmask >>= 1;
  108.     if (srcmask == 0) {
  109.       srcpixel++;
  110.       srcmask= 0x80;
  111.     }
  112.       }
  113.       destline += destlinelen;
  114.       srcline += srclinelen;
  115.     }
  116.     break;
  117.   
  118.   case IRGB:
  119.     destlinelen= dest->width * dest->pixlen;
  120.     srclinelen= src->width * src->pixlen;
  121.     deststart= atx * dest->pixlen;
  122.     destline= dest->data + (aty * destlinelen);
  123.     srcline= src->data;
  124.  
  125.     for (y= 0; y < cliph; y++) {
  126.       destpixel= destline + deststart;
  127.       srcpixel= srcline;
  128.       for (x= 0; x < clipw; x++) {
  129.     pixval= memToVal(srcpixel, src->pixlen);
  130.     *(destpixel++)= src->rgb.red[pixval] >> 8;
  131.     *(destpixel++)= src->rgb.green[pixval] >> 8;
  132.     *(destpixel++)= src->rgb.blue[pixval] >> 8;
  133.     srcpixel += src->pixlen;
  134.       }
  135.       destline += destlinelen;
  136.       srcline += srclinelen;
  137.     }
  138.     break;
  139.  
  140.   case ITRUE:
  141.     destlinelen= dest->width * dest->pixlen;
  142.     srclinelen= src->width * src->pixlen;
  143.     deststart= atx * dest->pixlen;
  144.     destline= dest->data + (aty * destlinelen);
  145.     srcline= src->data;
  146.  
  147.     for (y= 0; y < cliph; y++) {
  148.       destpixel= destline + deststart;
  149.       srcpixel= srcline;
  150.       for (x= 0; x < clipw; x++) {
  151.     *(destpixel++)= *(srcpixel++);
  152.     *(destpixel++)= *(srcpixel++);
  153.     *(destpixel++)= *(srcpixel++);
  154.       }
  155.       destline += destlinelen;
  156.       srcline += srclinelen;
  157.     }
  158.     break;
  159.   }
  160.   if (verbose)
  161.     printf("done\n");
  162.   return(dest);
  163. }
  164.  
  165. /* put src image on dest image
  166.  */
  167.  
  168. Image *merge(dest, src, atx, aty, verbose)
  169.      Image        *dest;
  170.      Image        *src;
  171.      int           atx, aty;
  172.      unsigned int  verbose;
  173. { int clipw, cliph;
  174.   int clipped = 0;
  175.   Image *newimage;
  176.  
  177.   goodImage(dest, "merge");
  178.   goodImage(src, "merge");
  179.  
  180.   if (verbose) {
  181.     printf("  Merging...");
  182.     fflush(stdout);
  183.   }
  184.  
  185.   /* adjust clipping of src to fit within dest
  186.    */
  187.  
  188.   clipw= src->width;
  189.   cliph= src->height;
  190.   if ((atx + clipw < 0) || (aty + cliph < 0) ||
  191.       (atx >= (int)dest->width) ||
  192.       (aty >= (int)dest->height)) { /* not on dest, ignore */
  193.     if (verbose)
  194.       printf("not on destination\n");
  195.     return(dest);
  196.   }
  197.  
  198.   if (atx + clipw > dest->width)
  199.     clipw = dest->width - atx;
  200.   if (aty + cliph > dest->height)
  201.     cliph = dest->height - aty;
  202.  
  203.   /* extra clipping required for negative offsets
  204.    */
  205.  
  206.   if ( atx < 0 || aty < 0 ) {
  207.     int clipx, clipy;
  208.  
  209.     if ( atx < 0 ) {
  210.       clipx = -atx;
  211.       clipw += atx;
  212.       atx = 0;
  213.     }
  214.     else
  215.       clipx = 0;
  216.     
  217.     if ( aty < 0 ) {
  218.       clipy = -aty;
  219.       cliph += aty;
  220.       aty = 0;
  221.     }
  222.     else
  223.       clipy = 0;
  224.     
  225.     clipped = 1;
  226.     src = clip(src, clipx, clipy, clipw, cliph, verbose);
  227.   }
  228.  
  229.   if (BITMAPP(dest) && BITMAPP(src))
  230.     newimage= bitmapToBitmap(src, dest, (unsigned int)atx, (unsigned int)aty,
  231.                  clipw, cliph, verbose);
  232.   else
  233.     newimage= anyToTrue(src, dest, (unsigned int)atx, (unsigned int)aty,
  234.             clipw, cliph, verbose);
  235.   if (clipped)
  236.     freeImage(src);
  237.   return(newimage);
  238. }
  239.  
  240. /* this creates an image of the specified size by tiling a base image
  241.  */
  242. Image *tile(image, x, y, width, height, verbose)
  243.      Image *image;
  244.      int x, y;
  245.      unsigned int width, height, verbose;
  246. { Image *base, *tmp;
  247.  
  248.   if (verbose) {
  249.     printf("  Tiling...");
  250.     fflush(stdout);
  251.   }
  252.  
  253.   /* if the image is a bitmap merge onto a bitmap image (so we don't
  254.    * need do dither on some displays).  otherwise promote to truecolor
  255.    * since that's what merge() will do anyway.
  256.    */
  257.   if (BITMAPP(image))
  258.     base = newBitImage(width, height);
  259.   else
  260.     base = newTrueImage(width, height);
  261.  
  262.   while (x < base->width) {
  263.     while(y < base->height) {
  264.       tmp = merge(base, image, x, y, 0);
  265.       if (tmp != base) {
  266.     freeImage(base);
  267.     base = tmp;
  268.       }
  269.       y += image->width;
  270.     }
  271.     x += image->width;
  272.   }
  273.   printf("done.\n");
  274.   return(base);
  275. }
  276.