ibuf8.cc

Go to the documentation of this file.
00001 /*
00002  *  ibuf8.cc - 8-bit image buffer.
00003  *
00004  *  Copyright (C) 1998-1999  Jeffrey S. Freedman
00005  *  Copyright (C) 2000-2002  The Exult Team
00006  *
00007  *  This program is free software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License as published by
00009  *  the Free Software Foundation; either version 2 of the License, or
00010  *  (at your option) any later version.
00011  *
00012  *  This program is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *  GNU General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU General Public License
00018  *  along with this program; if not, write to the Free Software
00019  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00020  */
00021 
00022 #ifdef HAVE_CONFIG_H
00023 #  include <config.h>
00024 #endif
00025 
00026 #include "ibuf8.h"
00027 #ifndef ALPHA_LINUX_CXX
00028 #  include <string>
00029 #  include <iostream>
00030 #endif
00031 
00032 #include "exult_types.h"
00033 #include "utils.h"
00034 
00035 using std::cerr;
00036 using std::endl;
00037 
00038 /*
00039  *  Copy an area of the image within itself.
00040  */
00041 
00042 void Image_buffer8::copy
00043   (
00044   int srcx, int srcy,   // Where to start.
00045   int srcw, int srch,   // Dimensions to copy.
00046   int destx, int desty    // Where to copy to.
00047   )
00048   {
00049   int ynext, yfrom, yto;    // Figure y stuff.
00050   if (srcy >= desty)    // Moving up?
00051     {
00052     ynext = line_width;
00053     yfrom = srcy;
00054     yto = desty;
00055     }
00056   else        // Moving down.
00057     {
00058     ynext = -line_width;
00059     yfrom = srcy + srch - 1;
00060     yto = desty + srch - 1;
00061     }
00062   unsigned char *to = bits + yto*line_width + destx;
00063   unsigned char *from = bits + yfrom*line_width + srcx;
00064           // Go through lines.
00065   while (srch--)
00066     {
00067     std::memmove((char *) to, (char *) from, srcw);
00068     to += ynext;
00069     from += ynext;
00070     }
00071   }
00072 
00073 /*
00074  *  Get a rectangle from here into another Image_buffer.
00075  */
00076 
00077 void Image_buffer8::get
00078   (
00079   Image_buffer *dest,   // Copy to here.
00080   int srcx, int srcy    // Upper-left corner of source rect.
00081   )
00082   {
00083   int srcw = dest->width, srch = dest->height;
00084   int destx = 0, desty = 0;
00085           // Constrain to window's space. (Note
00086           //   convoluted use of clip().)
00087   if (!clip(destx, desty, srcw, srch, srcx, srcy))
00088     return;
00089   unsigned char *to = (unsigned char *) dest->bits + 
00090         desty*dest->line_width + destx;
00091   unsigned char *from = (unsigned char *) bits + srcy*line_width + srcx;
00092           // Figure # pixels to next line.
00093   int to_next = dest->line_width - srcw;
00094   int from_next = line_width - srcw;
00095   while (srch--)      // Do each line.
00096     {
00097     for (int cnt = srcw; cnt; cnt--)
00098       *to++ = *from++;
00099     to += to_next;
00100     from += from_next;
00101     }
00102   }
00103 
00104 /*
00105  *  Retrieve data from another buffer.
00106  */
00107 
00108 void Image_buffer8::put
00109   (
00110   Image_buffer *src,    // Copy from here.
00111   int destx, int desty    // Copy to here.
00112   )
00113   {
00114   Image_buffer8::copy8((unsigned char *) src->bits,
00115     src->get_width(), src->get_height(), destx, desty);
00116   }
00117 
00118 /*
00119  * Fill buffer with random static
00120  */
00121 void Image_buffer8::fill_static(int black, int gray, int white)
00122 {
00123   unsigned char *p = bits;
00124   for (int i = width*height; i > 0; --i) {
00125     switch (std::rand()%5) {
00126       case 0: case 1: *p++ = black; break;
00127       case 2: case 3: *p++ = gray; break;
00128       case 4: *p++ = white; break;
00129     }
00130   }
00131 }
00132 
00133 /*
00134  *  Fill with a given 8-bit value.
00135  */
00136 
00137 void Image_buffer8::fill8
00138   (
00139   unsigned char pix
00140   )
00141   {
00142   unsigned char *pixels = bits;
00143   int cnt = line_width*height;
00144   for (int i = 0; i < cnt; i++)
00145     *pixels++ = pix;
00146   }
00147 
00148 /*
00149  *  Fill a rectangle with an 8-bit value.
00150  */
00151 
00152 void Image_buffer8::fill8
00153   (
00154   unsigned char pix,
00155   int srcw, int srch,
00156   int destx, int desty
00157   )
00158   {
00159   int srcx = 0, srcy = 0;
00160           // Constrain to window's space.
00161   if (!clip(srcx, srcy, srcw, srch, destx, desty))
00162     return;
00163   unsigned char *pixels = (unsigned char *) bits + 
00164             desty*line_width + destx;
00165   int to_next = line_width - srcw;// # pixels to next line.
00166   while (srch--)      // Do each line.
00167     {
00168     for (int cnt = srcw; cnt; cnt--)
00169       *pixels++ = pix;
00170     pixels += to_next;  // Get to start of next line.
00171     }
00172   }
00173 
00174 /*
00175  *  Fill a line with a given 8-bit value.
00176  */
00177 
00178 void Image_buffer8::fill_line8
00179   (
00180   unsigned char pix,
00181   int srcw,
00182   int destx, int desty
00183   )
00184   {
00185   int srcx = 0;
00186           // Constrain to window's space.
00187   if (!clip_x(srcx, srcw, destx, desty))
00188     return;
00189   unsigned char *pixels = (unsigned char *) bits + 
00190             desty*line_width + destx;
00191   std::memset(pixels, pix, srcw);
00192   }
00193 
00194 /*
00195  *  Copy another rectangle into this one.
00196  */
00197 
00198 void Image_buffer8::copy8
00199   (
00200   unsigned char *src_pixels,  // Source rectangle pixels.
00201   int srcw, int srch,   // Dimensions of source.
00202   int destx, int desty
00203   )
00204 {
00205 
00206   if (!src_pixels)
00207   {
00208     cerr << "WTF! src_pixels in Image_buffer8::copy8 was 0!" << endl;
00209     return;
00210   }
00211 
00212   int srcx = 0, srcy = 0;
00213   int src_width = srcw;   // Save full source width.
00214           // Constrain to window's space.
00215   if (!clip(srcx, srcy, srcw, srch, destx, desty))
00216     return;
00217 
00218 #if !(defined(__sparc__) || defined(__zaurus__))
00219   uint32 *to = (uint32*) (bits + desty*line_width + destx);
00220   uint32 *from = (uint32*) (src_pixels + srcy*src_width + srcx);
00221   int to_next = line_width - srcw;// # pixels to next line.
00222   int from_next = src_width - srcw;
00223 
00224   // Need to know if we end dword alligned
00225   int end_align = srcw%4;
00226   // The actual aligned width in dwords
00227   int aligned = srcw/4;
00228 
00229   uint8 *to8;
00230   uint8 *from8;
00231 
00232   while (srch--)      // Do each line.
00233   {
00234     int counter = aligned;
00235     while (counter--) *to++ = *from++;
00236 
00237     to8 = (uint8*) to;
00238     from8 = (uint8*) from;
00239 
00240     counter = end_align;
00241     while (counter--) *to8++ = *from8++;
00242 
00243     to = (uint32*) (to8+to_next);
00244     from = (uint32*) (from8+from_next);
00245   }
00246 #else
00247   uint8 *to = bits + desty*line_width + destx;
00248   uint8 *from = src_pixels + srcy*src_width + srcx;
00249   while (srch--) {
00250     std::memcpy(to, from, srcw);
00251     from += src_width;
00252     to += line_width; 
00253   }
00254 #endif
00255 }
00256 
00257 /*
00258  *  Copy a line into this buffer.
00259  */
00260 
00261 void Image_buffer8::copy_line8
00262   (
00263   unsigned char *src_pixels,  // Source rectangle pixels.
00264   int srcw,     // Width to copy.
00265   int destx, int desty
00266   )
00267   {
00268   int srcx = 0;
00269           // Constrain to window's space.
00270   if (!clip_x(srcx, srcw, destx, desty))
00271     return;
00272   unsigned char *to = bits + desty*line_width + destx;
00273   unsigned char *from = src_pixels + srcx;
00274   std::memcpy(to, from, srcw);
00275   }
00276 
00277 /*
00278  *  Copy a line into this buffer where some of the colors are translucent.
00279  */
00280 
00281 void Image_buffer8::copy_line_translucent8
00282   (
00283   unsigned char *src_pixels,  // Source rectangle pixels.
00284   int srcw,     // Width to copy.
00285   int destx, int desty,
00286   int first_translucent,    // Palette index of 1st trans. color.
00287   int last_translucent,   // Index of last trans. color.
00288   Xform_palette *xforms   // Transformers.  Need same # as
00289           //   (last_translucent - 
00290           //    first_translucent + 1).
00291   )
00292   {
00293   int srcx = 0;
00294           // Constrain to window's space.
00295   if (!clip_x(srcx, srcw, destx, desty))
00296     return;
00297   unsigned char *to = (unsigned char *) bits + desty*line_width + destx;
00298   unsigned char *from = src_pixels + srcx;
00299   for (int i = srcw; i; i--)
00300     {
00301           // Get char., and transform.
00302     unsigned char c = *from++;
00303     if (c >= first_translucent && c <= last_translucent)
00304           // Use table to shift existing pixel.
00305       c = xforms[c - first_translucent][*to];
00306     *to++ = c;
00307     }
00308   }
00309 
00310 /*
00311  *  Apply a translucency table to a line.
00312  */
00313 
00314 void Image_buffer8::fill_line_translucent8
00315   (
00316   unsigned char val,    // Ignored for this method.
00317   int srcw,
00318   int destx, int desty,
00319   Xform_palette& xform    // Transform table.
00320   )
00321   {
00322   int srcx = 0;
00323           // Constrain to window's space.
00324   if (!clip_x(srcx, srcw, destx, desty))
00325     return;
00326   unsigned char *pixels = (unsigned char *) bits + 
00327             desty*line_width + destx;
00328   while (srcw--)
00329     {
00330     *pixels = xform[*pixels];
00331     pixels++;
00332     }
00333   }
00334 
00335 /*
00336  *  Apply a translucency table to a rectangle.
00337  */
00338 
00339 void Image_buffer8::fill_translucent8
00340   (
00341   unsigned char /* val */,  // Not used.
00342   int srcw, int srch,
00343   int destx, int desty,
00344   Xform_palette& xform    // Transform table.
00345   )
00346   {
00347   int srcx = 0, srcy = 0;
00348           // Constrain to window's space.
00349   if (!clip(srcx, srcy, srcw, srch, destx, desty))
00350     return;
00351   unsigned char *pixels = (unsigned char *) bits + 
00352             desty*line_width + destx;
00353   int to_next = line_width - srcw;// # pixels to next line.
00354   while (srch--)      // Do each line.
00355     {
00356     for (int cnt = srcw; cnt; cnt--, pixels++)
00357       *pixels = xform[*pixels];
00358     pixels += to_next;  // Get to start of next line.
00359     }
00360   }
00361 
00362 /*
00363  *  Copy another rectangle into this one, with 0 being the transparent
00364  *  color.
00365  */
00366 
00367 void Image_buffer8::copy_transparent8
00368   (
00369   unsigned char *src_pixels,  // Source rectangle pixels.
00370   int srcw, int srch,   // Dimensions of source.
00371   int destx, int desty
00372   )
00373   {
00374   int srcx = 0, srcy = 0;
00375   int src_width = srcw;   // Save full source width.
00376           // Constrain to window's space.
00377   if (!clip(srcx, srcy, srcw, srch, destx, desty))
00378     return;
00379   unsigned char *to = bits + desty*line_width + destx;
00380   unsigned char *from = src_pixels + srcy*src_width + srcx;
00381   int to_next = line_width - srcw;// # pixels to next line.
00382   int from_next = src_width - srcw;
00383   while (srch--)      // Do each line.
00384     {
00385     for (int cnt = srcw; cnt; cnt--, to++)
00386       {
00387       register int chr = *from++;
00388       if (chr)
00389         *to = chr;
00390       }
00391     to += to_next;
00392     from += from_next;
00393     }
00394   }
00395 
00396 // Slightly Optimized RLE Painter
00397 void Image_buffer8::paint_rle (int xoff, int yoff, unsigned char *inptr)
00398 {
00399   uint8* in = inptr;
00400   int scanlen;
00401   const int right = clipx+clipw;
00402   const int bottom = clipy+cliph;
00403 
00404   while ((scanlen = Read2(in)) != 0)
00405   {
00406           // Get length of scan line.
00407     int encoded = scanlen&1;// Is it encoded?
00408     scanlen = scanlen>>1;
00409     int scanx = xoff + (sint16) Read2(in);
00410     int scany = yoff + (sint16) Read2(in);
00411 
00412     // Is there somthing on screen?
00413     bool on_screen = true;
00414     if (scanx >= right || scany >= bottom || scany < clipy || scanx+scanlen < clipx)
00415       on_screen = false;
00416 
00417     if (!encoded) // Raw data?
00418     {
00419       // Only do the complex calcs if we think it could be on screen
00420       if (on_screen)
00421       {
00422         // Do we need to skip pixels at the start?
00423         if (scanx < clipx)
00424         {
00425           const int delta = clipx-scanx;
00426           in += delta;
00427           scanlen -= delta;
00428           scanx = clipx;
00429         }
00430 
00431         // Do we need to skip pixels at the end?
00432         int skip = scanx+scanlen - right;
00433         if (skip < 0) skip = 0;
00434 
00435         // Is there anything to put on the screen?
00436         if (skip < scanlen)
00437         {
00438           unsigned char *dest = bits + scany*line_width + scanx;
00439           unsigned char *end = in+scanlen-skip;
00440           while (in < end) *dest++ = *in++;
00441           in += skip;
00442           continue;
00443         }
00444       }
00445       in += scanlen;
00446       continue;
00447     }
00448     else  // Encoded
00449     {
00450       unsigned char *dest = bits + scany*line_width + scanx;
00451 
00452       while (scanlen)
00453       {
00454         unsigned char bcnt = *in++;
00455             // Repeat next char. if odd.
00456         int repeat = bcnt&1;
00457         bcnt = bcnt>>1; // Get count.
00458 
00459         // Only do the complex calcs if we think it could be on screen
00460         if (on_screen && scanx < right && scanx+bcnt > clipx)
00461         {
00462           if (repeat) // Const Colour
00463           {
00464             // Do we need to skip pixels at the start?
00465             if (scanx < clipx)
00466             {
00467               const int delta = clipx-scanx;
00468               dest += delta;
00469               bcnt -= delta;
00470               scanlen -= delta;
00471               scanx = clipx;
00472             }
00473 
00474             // Do we need to skip pixels at the end?
00475             int skip = scanx+bcnt - right;
00476             if (skip < 0) skip = 0;
00477 
00478             // Is there anything to put on the screen?
00479             if (skip < bcnt)
00480             {
00481               unsigned char col = *in++;
00482               unsigned char *end = dest+bcnt-skip;
00483               while (dest < end) *dest++ = col;
00484 
00485               // dest += skip; - Don't need it
00486               scanx += bcnt;
00487               scanlen -= bcnt;
00488               continue;
00489             }
00490 
00491             // Make sure all the required values get
00492             // properly updated
00493 
00494             // dest += bcnt; - Don't need it
00495             scanx += bcnt;
00496             scanlen -= bcnt;
00497             ++in;
00498             continue;
00499           }
00500           else
00501           {
00502             // Do we need to skip pixels at the start?
00503             if (scanx < clipx)
00504             {
00505               const int delta = clipx-scanx;
00506               dest += delta;
00507               in += delta;
00508               bcnt -= delta;
00509               scanlen -= delta;
00510               scanx = clipx;
00511             }
00512 
00513             // Do we need to skip pixels at the end?
00514             int skip = scanx+bcnt - right;
00515             if (skip < 0) skip = 0;
00516 
00517             // Is there anything to put on the screen?
00518             if (skip < bcnt)
00519             {
00520               unsigned char *end = dest+bcnt-skip;
00521               while (dest < end) *dest++ = *in++;
00522               // dest += skip; - Don't need it
00523               in += skip;
00524               scanx += bcnt;
00525               scanlen -= bcnt;
00526               continue;
00527             }
00528 
00529             // Make sure all the required values get
00530             // properly updated
00531 
00532             // dest += skip; - Don't need it
00533             scanx += bcnt;
00534             scanlen -= bcnt;
00535             in += bcnt;
00536             continue;
00537           }
00538         }
00539 
00540         // Make sure all the required values get
00541         // properly updated
00542 
00543         dest += bcnt;
00544         scanx += bcnt;
00545         scanlen -= bcnt;
00546         if (!repeat) in += bcnt;
00547         else ++in;
00548         continue;
00549       }
00550     }
00551   }
00552 }
00553 
00554 /*
00555  *  Convert this image to 32-bit RGBA and return the allocated buffer.
00556  */
00557 
00558 unsigned char *Image_buffer8::rgba
00559   (
00560   unsigned char *pal,   // 3*256 bytes (rgbrgbrgb...).
00561   unsigned char transp,   // Transparent value.
00562   int first_translucent,    // Palette index of 1st trans. color.
00563   int last_translucent,   // Index of last trans. color.
00564   Xform_palette *xforms   // Transformers.  Need same # as
00565           //   (last_translucent - 
00566           //    first_translucent + 1).
00567   )
00568   {
00569   int cnt = line_width*height;  // Allocate destination buffer.
00570   uint32 *buf32 = new uint32[cnt];
00571   uint32 *ptr32 = buf32;
00572   unsigned char *pixels = bits;
00573   for (int i = 0; i < cnt; i++)
00574     {
00575     unsigned char pix = *pixels++;
00576     if (pix == transp)  // Transparent?  Store Alpha=0.
00577       {
00578       *ptr32++ = 0;
00579       continue;
00580       }
00581     unsigned char r,g,b,a;  // Pieces of the color.
00582     if (pix >= first_translucent && pix <= last_translucent)
00583       {   // Get actual color & alpha from tbl.
00584       Xform_palette& xf = xforms[pix - first_translucent];
00585       r = xf.r; g = xf.g; b = xf.b; a = xf.a;
00586       }
00587     else
00588       {
00589       r = pal[3*pix]; g = pal[3*pix+1]; b = pal[3*pix + 2];
00590       a = 255;
00591       }
00592     *ptr32++ =  (static_cast<uint32>(r)<<0) +
00593         (static_cast<uint32>(g) << 8) +
00594         (static_cast<uint32>(b) << 16) +
00595         (static_cast<uint32>(a) << 24);
00596     }
00597   return reinterpret_cast<unsigned char *>(buf32);
00598   }

Generated on Mon Jul 9 14:42:47 2007 for ExultEngine by  doxygen 1.5.1