00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00040
00041
00042 void Image_buffer8::copy
00043 (
00044 int srcx, int srcy,
00045 int srcw, int srch,
00046 int destx, int desty
00047 )
00048 {
00049 int ynext, yfrom, yto;
00050 if (srcy >= desty)
00051 {
00052 ynext = line_width;
00053 yfrom = srcy;
00054 yto = desty;
00055 }
00056 else
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
00065 while (srch--)
00066 {
00067 std::memmove((char *) to, (char *) from, srcw);
00068 to += ynext;
00069 from += ynext;
00070 }
00071 }
00072
00073
00074
00075
00076
00077 void Image_buffer8::get
00078 (
00079 Image_buffer *dest,
00080 int srcx, int srcy
00081 )
00082 {
00083 int srcw = dest->width, srch = dest->height;
00084 int destx = 0, desty = 0;
00085
00086
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
00093 int to_next = dest->line_width - srcw;
00094 int from_next = line_width - srcw;
00095 while (srch--)
00096 {
00097 for (int cnt = srcw; cnt; cnt--)
00098 *to++ = *from++;
00099 to += to_next;
00100 from += from_next;
00101 }
00102 }
00103
00104
00105
00106
00107
00108 void Image_buffer8::put
00109 (
00110 Image_buffer *src,
00111 int destx, int desty
00112 )
00113 {
00114 Image_buffer8::copy8((unsigned char *) src->bits,
00115 src->get_width(), src->get_height(), destx, desty);
00116 }
00117
00118
00119
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
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
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
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;
00166 while (srch--)
00167 {
00168 for (int cnt = srcw; cnt; cnt--)
00169 *pixels++ = pix;
00170 pixels += to_next;
00171 }
00172 }
00173
00174
00175
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
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
00196
00197
00198 void Image_buffer8::copy8
00199 (
00200 unsigned char *src_pixels,
00201 int srcw, int srch,
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;
00214
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;
00222 int from_next = src_width - srcw;
00223
00224
00225 int end_align = srcw%4;
00226
00227 int aligned = srcw/4;
00228
00229 uint8 *to8;
00230 uint8 *from8;
00231
00232 while (srch--)
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
00259
00260
00261 void Image_buffer8::copy_line8
00262 (
00263 unsigned char *src_pixels,
00264 int srcw,
00265 int destx, int desty
00266 )
00267 {
00268 int srcx = 0;
00269
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
00279
00280
00281 void Image_buffer8::copy_line_translucent8
00282 (
00283 unsigned char *src_pixels,
00284 int srcw,
00285 int destx, int desty,
00286 int first_translucent,
00287 int last_translucent,
00288 Xform_palette *xforms
00289
00290
00291 )
00292 {
00293 int srcx = 0;
00294
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
00302 unsigned char c = *from++;
00303 if (c >= first_translucent && c <= last_translucent)
00304
00305 c = xforms[c - first_translucent][*to];
00306 *to++ = c;
00307 }
00308 }
00309
00310
00311
00312
00313
00314 void Image_buffer8::fill_line_translucent8
00315 (
00316 unsigned char val,
00317 int srcw,
00318 int destx, int desty,
00319 Xform_palette& xform
00320 )
00321 {
00322 int srcx = 0;
00323
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
00337
00338
00339 void Image_buffer8::fill_translucent8
00340 (
00341 unsigned char ,
00342 int srcw, int srch,
00343 int destx, int desty,
00344 Xform_palette& xform
00345 )
00346 {
00347 int srcx = 0, srcy = 0;
00348
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;
00354 while (srch--)
00355 {
00356 for (int cnt = srcw; cnt; cnt--, pixels++)
00357 *pixels = xform[*pixels];
00358 pixels += to_next;
00359 }
00360 }
00361
00362
00363
00364
00365
00366
00367 void Image_buffer8::copy_transparent8
00368 (
00369 unsigned char *src_pixels,
00370 int srcw, int srch,
00371 int destx, int desty
00372 )
00373 {
00374 int srcx = 0, srcy = 0;
00375 int src_width = srcw;
00376
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;
00382 int from_next = src_width - srcw;
00383 while (srch--)
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
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
00407 int encoded = scanlen&1;
00408 scanlen = scanlen>>1;
00409 int scanx = xoff + (sint16) Read2(in);
00410 int scany = yoff + (sint16) Read2(in);
00411
00412
00413 bool on_screen = true;
00414 if (scanx >= right || scany >= bottom || scany < clipy || scanx+scanlen < clipx)
00415 on_screen = false;
00416
00417 if (!encoded)
00418 {
00419
00420 if (on_screen)
00421 {
00422
00423 if (scanx < clipx)
00424 {
00425 const int delta = clipx-scanx;
00426 in += delta;
00427 scanlen -= delta;
00428 scanx = clipx;
00429 }
00430
00431
00432 int skip = scanx+scanlen - right;
00433 if (skip < 0) skip = 0;
00434
00435
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
00449 {
00450 unsigned char *dest = bits + scany*line_width + scanx;
00451
00452 while (scanlen)
00453 {
00454 unsigned char bcnt = *in++;
00455
00456 int repeat = bcnt&1;
00457 bcnt = bcnt>>1;
00458
00459
00460 if (on_screen && scanx < right && scanx+bcnt > clipx)
00461 {
00462 if (repeat)
00463 {
00464
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
00475 int skip = scanx+bcnt - right;
00476 if (skip < 0) skip = 0;
00477
00478
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
00486 scanx += bcnt;
00487 scanlen -= bcnt;
00488 continue;
00489 }
00490
00491
00492
00493
00494
00495 scanx += bcnt;
00496 scanlen -= bcnt;
00497 ++in;
00498 continue;
00499 }
00500 else
00501 {
00502
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
00514 int skip = scanx+bcnt - right;
00515 if (skip < 0) skip = 0;
00516
00517
00518 if (skip < bcnt)
00519 {
00520 unsigned char *end = dest+bcnt-skip;
00521 while (dest < end) *dest++ = *in++;
00522
00523 in += skip;
00524 scanx += bcnt;
00525 scanlen -= bcnt;
00526 continue;
00527 }
00528
00529
00530
00531
00532
00533 scanx += bcnt;
00534 scanlen -= bcnt;
00535 in += bcnt;
00536 continue;
00537 }
00538 }
00539
00540
00541
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
00556
00557
00558 unsigned char *Image_buffer8::rgba
00559 (
00560 unsigned char *pal,
00561 unsigned char transp,
00562 int first_translucent,
00563 int last_translucent,
00564 Xform_palette *xforms
00565
00566
00567 )
00568 {
00569 int cnt = line_width*height;
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)
00577 {
00578 *ptr32++ = 0;
00579 continue;
00580 }
00581 unsigned char r,g,b,a;
00582 if (pix >= first_translucent && pix <= last_translucent)
00583 {
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 }