Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

provider_targa.cpp

Go to the documentation of this file.
00001 /*
00002         $Id: provider_targa.cpp,v 1.1 2001/03/06 15:09:22 mbn Exp $
00003 
00004         ------------------------------------------------------------------------
00005         ClanLib, the platform independent game SDK.
00006 
00007         This library is distributed under the GNU LIBRARY GENERAL PUBLIC LICENSE
00008         version 2. See COPYING for details.
00009 
00010         For a total list of contributers see CREDITS.
00011 
00012         ------------------------------------------------------------------------
00013 
00014         File purpose:
00015                 .TGA reader and surfaceprovider
00016 
00017 */
00018 
00019 #include "Core/precomp.h"
00020 #include <iostream>
00021 #include <stdio.h>
00022 #include "API/Display/SurfaceProviders/provider_targa.h"
00023 #include "API/Core/IOData/cl_endian.h"
00024 #include "API/Core/System/error.h"
00025 #include "API/Core/System/cl_assert.h"
00026 #include "API/Display/Display/res_surface.h"
00027 #include "API/Core/Resources/resourceoptions.h"
00028 
00029 
00030 /*
00031   Generic info about using alphachannel/transparanty
00032 
00033   Apparently the code works in this way (as far as I can understand):
00034 
00035   ==============================================================
00036   The blit code "only" looks at rgb & alpha. 
00037 
00038   If alpha = 0 then a pixel is transparant
00039   If alpha = 255 then a pixel is "fully" visible. 
00040   All values in between are used for alphablending
00041 
00042   ==============================================================
00043   The *Loading* code works as follows:
00044 
00045   0) you can turn nothing on (or everything off :)
00046   1) you can turn on transparant pixels
00047   2) you can set to ignore the alphachannel (turn it off)
00048   
00049   ad 0) the alphachannel is just copied from the input file format 
00050                 (or set to 255 if unavailable) and we don't care about 
00051                 any pixels marked as transparant by color.
00052 
00053   ad 1) If you choose to turn on transparant pixels, then all pixels 
00054                 are traversed and for the pixels matching the "transparant color", 
00055                 the alpha value is set to 0 (transparant).
00056 
00057   ad 2) If you choose to ignore the alphachannel, then the alphachannel 
00058                 for ALL pixels is set to 255 UNLESS you also specified to use 
00059                 transparant pixels (wich means that some pixels might get aplha=0).
00060 
00061   note: if you have transparant pixels & alphachannel on then pixels
00062   with an alphavalue of 0 will be reset to the "transparant pixel color"
00063   ==============================================================
00064 */
00065 
00066 
00067 CL_Surface *CL_TargaProvider::create(
00068         std::string file,
00069         CL_InputSourceProvider *provider, 
00070         bool transparent,
00071         bool ignore_alphachannel,
00072         unsigned char trans_red, 
00073         unsigned char trans_green, 
00074         unsigned char trans_blue)
00075 {
00076         return CL_Surface::create(
00077                 new CL_TargaProvider(
00078                         file,
00079                         provider, 
00080                         transparent,
00081                         ignore_alphachannel, 
00082                         trans_red,
00083                         trans_green,
00084                         trans_blue),
00085                 true);
00086 }
00087 
00088 CL_TargaProvider::CL_TargaProvider(
00089         std::string name,
00090         CL_InputSourceProvider *_provider,
00091         bool _transparent,
00092         bool _ignore_alphachannel,
00093         unsigned char trans_red, 
00094         unsigned char trans_green, 
00095         unsigned char trans_blue)
00096 {
00097         if (_provider == NULL)
00098         {
00099                 provider = CL_InputSourceProvider::create_file_provider(".");
00100         }
00101         else
00102         {
00103                 provider = _provider->clone();
00104         }
00105 
00106         ignore_alphachannel = _ignore_alphachannel;
00107         transparent = _transparent;
00108         use_alphapixels = transparent && !ignore_alphachannel;
00109         trans_redcol = trans_red;
00110         trans_greencol = trans_green;
00111         trans_bluecol = trans_blue;
00112 
00113         if (transparent)
00114         {
00115                 trans_col = (((unsigned int) trans_redcol) << 24) +
00116                         (((unsigned int) trans_greencol)<<16) +
00117                         (((unsigned int) trans_bluecol) << 8);
00118         }
00119         else
00120         {
00121                 trans_col = -1;
00122         }
00123 
00124         locked = false;
00125         filename = name;
00126         file = image = color_map = NULL;
00127 }
00128 
00129 CL_TargaProvider::~CL_TargaProvider()
00130 {
00131         perform_unlock();
00132         delete provider;
00133 }
00134 
00135 /*
00136         Read the file data - a .TGA file can exist in several
00137         different formats - not all formats are supported by
00138         this surfaceprovider.
00139 */
00140 void CL_TargaProvider::read_data()
00141 {
00142         datatype = file[2];
00143 
00144         switch (datatype)
00145         {
00146         case 1:
00147                 read_colormapped();
00148                 return;
00149                 break;
00150         case 2:
00151                 read_uncompressed_rgb();
00152                 return;
00153                 break;
00154         case 9:
00155                 // this format is not tested (but I think it works)
00156                 read_runlength_encoded_colormapped_rgb();
00157                 return;
00158                 break;
00159         case 10:
00160                 read_runlength_encoded_rgb();
00161                 return;
00162                 break;
00163         }
00164 
00165         std::string err("CL_TargaProvider Fatal Error: Unsupported TGA filetype encountered");
00166         throw CL_Error(err);
00167 //      cl_assert(false);
00168 }
00169 
00170 /*
00171         Reads the .TGA header - this header is relatively equal
00172         between subformats - except for whether the colormap
00173         is interesting.
00174 */
00175 void CL_TargaProvider::read_header(bool read_colormap)
00176 {
00177         unsigned char idlength = file[0];
00178         unsigned char colormaptype = file[1];
00179 
00180         pos = 18;
00181 
00182         // Skip the id-string (if any)
00183         if (idlength != 0)
00184         {
00185                 pos += idlength;
00186         }
00187 
00188         bpp = file[16];
00189 
00190         // read or skip the colormap (rgb-palette)
00191         if (colormaptype == 1)
00192         {
00193                 map_length = *((unsigned short *) &file[5]);
00194                 SWAP_IF_BIG(map_length);
00195                 unsigned char map_size = file[7]>>3;
00196 
00197                 if (!read_colormap)
00198                 {
00199                         // Skip colormap - we dont need it
00200                         pos += map_length*map_size;
00201                 }
00202                 else
00203                 {
00204                         // Read the colormap
00205                         color_map = new unsigned char[map_length * 4];
00206                         
00207                         // read color depending on bytes-pr-pixel
00208                         for (unsigned int i=0;i<map_length;i++)
00209                         {
00210                                 switch (bpp)
00211                                 {
00212                                 case 16:
00213                                         read_rgb_16(&color_map[i*4+0],
00214                                                          &color_map[i*4+1],
00215                                                          &color_map[i*4+2],
00216                                                          &color_map[i*4+3]);
00217                                         break;
00218                                 case 24:
00219                                         read_rgb_24(&color_map[i*4+0],
00220                                                          &color_map[i*4+1],
00221                                                          &color_map[i*4+2],
00222                                                          &color_map[i*4+3]);
00223                                         break;
00224                                 case 32:
00225                                         read_rgb_32(&color_map[i*4+0],
00226                                                          &color_map[i*4+1],
00227                                                          &color_map[i*4+2],
00228                                                          &color_map[i*4+3]);
00229                                         break;
00230                                 default:
00231                                         {
00232                                                 char aBuf[500];
00233                                                 sprintf(aBuf, "Unsupported bit-depth in targafile '%s'", filename.c_str());
00234                                                 cl_info(1, aBuf);
00235                                         }
00236                                 }
00237                         }
00238                 }
00239         }
00240 
00241         // read pitch, height and bits-pr-pixel
00242         pitch = *((unsigned short *) &file[12]);
00243         SWAP_IF_BIG(pitch);
00244         bounding_left = pitch;
00245         bounding_right = 0;
00246 
00247         height = *((unsigned short *) &file[14]);
00248         SWAP_IF_BIG(height);
00249         bounding_top = height;
00250         bounding_bottom = 0;
00251 
00252         map_direction_x = (file[17] & 0x10) == 0 ? 1 : -1;
00253         map_direction_y = (file[17] & 0x20) == 0 ? -1 : 1;
00254 }
00255 
00256 /*
00257         Read and convert a rgb-color from the current position
00258         in the file.
00259 */
00260 inline bool CL_TargaProvider::read_rgb_16(
00261         unsigned char *a, 
00262         unsigned char *b, 
00263         unsigned char *g, 
00264         unsigned char *r)
00265 {
00266         bool ret = true;
00267 
00268         if (pos >= filesize)
00269                 throw CL_Error("Invalid targa file!?");
00270 
00271         // In 16 bits pr pixel the individual color-intensities are
00272         // described in two bytes:
00273         // ARRRRRGG      GGGBBBBB
00274         // A = ATTRIBUTE
00275         // R = RED
00276         // G = GREEN
00277         // B = BLUE
00278         // These two bytes are in reality read backwards (last byte first)
00279 
00280         *a = (int(file[pos+1]&128)>>7)*255;
00281         // Transparent pixel
00282         if (use_alphapixels && !(*a))
00283         {
00284                 *r = trans_redcol;
00285                 *g = trans_greencol;
00286                 *b = trans_bluecol;
00287                 ret = false;
00288         }
00289         else
00290         {
00291                 *r = ((file[pos+1]>>2) & 0x1f)<<3;
00292                 *g = (((file[pos+1] & 0x03)<<3) + 
00293                          ((file[pos]>>5) & 0x7))<<3;
00294                 *b = (file[pos] & 0x1f)<<3;
00295                 
00296                 if (transparent &&
00297                         *r == trans_redcol &&
00298                         *g == trans_greencol &&
00299                         *b == trans_bluecol)
00300                 {
00301                         *a = 0;
00302                         ret = false;
00303                 }
00304 //
00305                 else
00306                 if (ignore_alphachannel) 
00307                 {
00308                         // else if we're not using any alphapixels at all, then alpha should be 255
00309                         *a = 255;
00310                 }
00311 //
00312         }
00313 
00314         pos += 2;
00315 
00316         return ret;
00317 }
00318 
00319 inline bool CL_TargaProvider::read_rgb_24(
00320         unsigned char *a, 
00321         unsigned char *b, 
00322         unsigned char *g, 
00323         unsigned char *r)
00324 {
00325         bool ret = true;
00326 
00327         if (pos >= filesize)
00328                 throw CL_Error("Invalid targa file!?");
00329 
00330         *b = file[pos];
00331         *g = file[pos+1];
00332         *r = file[pos+2];
00333         *a = 255;
00334 
00335         if (transparent && 
00336                 *r == trans_redcol &&
00337                 *g == trans_greencol &&
00338                 *b == trans_bluecol)
00339         {
00340                 *a = 0;
00341                 ret = false;
00342         }
00343 
00344 
00345         pos += 3;
00346 
00347         return ret;
00348 }
00349 
00350 inline bool CL_TargaProvider::read_rgb_32(
00351         unsigned char *a, 
00352         unsigned char *b, 
00353         unsigned char *g, 
00354         unsigned char *r)
00355 {
00356         bool ret = true;
00357 
00358         if (pos >= filesize)
00359                 throw CL_Error("Invalid targa file!?");
00360 
00361         *a = file[pos+3];
00362         if (use_alphapixels && !(*a))
00363         {
00364                 *r = trans_redcol;
00365                 *g = trans_greencol;
00366                 *b = trans_bluecol;
00367 
00368                 ret = false;
00369         }
00370         else
00371         {
00372                 *b = file[pos];
00373                 *g = file[pos+1];
00374                 *r = file[pos+2];
00375                 
00376                 if (transparent && 
00377                         *r == trans_redcol &&
00378                         *g == trans_greencol &&
00379                         *b == trans_bluecol)
00380                 {
00381                         // if using transparant and we have matching transparant pixel, alpha should be 0
00382                         *a = 0;
00383                         ret = false;
00384                 }
00385 //
00386                 else
00387                 if (ignore_alphachannel) 
00388                 {
00389                         // else if we're not using any alphapixels at all, then alpha should be 255
00390                         *a = 255;
00391                 }
00392 //
00393         }
00394 
00395         pos += 4;
00396 
00397         return ret;
00398 }
00399 
00400 inline bool CL_TargaProvider::read_rgb(
00401         unsigned char *a, 
00402         unsigned char *b, 
00403         unsigned char *g, 
00404         unsigned char *r)
00405 {
00406         bool ret = true;
00407 
00408         if (pos >= filesize)
00409                 throw CL_Error("Invalid targa file!?");
00410 
00411         switch (bpp)
00412         {
00413         case 16:
00414                 // In 16 bits pr pixel the individual color-intensities are
00415                 // described in two bytes:
00416                 // ARRRRRGG      GGGBBBBB
00417                 // A = ATTRIBUTE
00418                 // R = RED
00419                 // G = GREEN
00420                 // B = BLUE
00421                 // These two bytes are in reality read backwards (last byte first)
00422 
00423                 *a = (int(file[pos+1]&128)>>7)*255;
00424                 // Transparent pixel
00425                 if (use_alphapixels && !(*a))
00426                 {
00427                         *r = trans_redcol;
00428                         *g = trans_greencol;
00429                         *b = trans_bluecol;
00430                         ret = false;
00431                 }
00432                 else
00433                 {
00434                         *r = ((file[pos+1]>>2) & 0x1f)<<3;
00435                         *g = (((file[pos+1] & 0x03)<<3) + 
00436                                  ((file[pos]>>5) & 0x7))<<3;
00437                         *b = (file[pos] & 0x1f)<<3;
00438                         
00439                         if (transparent &&
00440                                 *r == trans_redcol &&
00441                                 *g == trans_greencol &&
00442                                 *b == trans_bluecol)
00443                         {
00444                                 *a = 0;
00445                                 ret = false;
00446                         }
00447 //
00448                         else
00449                         if (ignore_alphachannel) 
00450                         {
00451                                 // else if we're not using any alphapixels at all, then alpha should be 255
00452                                 *a = 255;
00453                         }
00454 //
00455                 }
00456 
00457                 pos += 2;
00458                 break;
00459 
00460         case 24:
00461                 *b = file[pos];
00462                 *g = file[pos+1];
00463                 *r = file[pos+2];
00464                 *a = 255;
00465 
00466                 if (transparent && 
00467                         *r == trans_redcol &&
00468                         *g == trans_greencol &&
00469                         *b == trans_bluecol)
00470                 {
00471                         *a = 0;
00472                         ret = false;
00473                 }
00474 
00475                 pos += 3;
00476                 break;
00477 
00478         case 32:
00479                 *a = file[pos+3];
00480                 if (use_alphapixels && !(*a))
00481                 {
00482                         *r = trans_redcol;
00483                         *g = trans_greencol;
00484                         *b = trans_bluecol;
00485 
00486                         ret = false;
00487                 }
00488                 else
00489                 {
00490                         *b = file[pos];
00491                         *g = file[pos+1];
00492                         *r = file[pos+2];
00493                         
00494                         if (transparent && 
00495                                 *r == trans_redcol &&
00496                                 *g == trans_greencol &&
00497                                 *b == trans_bluecol)
00498                         {
00499                                 *a = 0;
00500                                 ret = false;
00501                         }
00502 //
00503                         else
00504                         if (ignore_alphachannel) 
00505                         {
00506                                 // else if we're not using any alphapixels at all, then alpha should be 255
00507                                 *a = 255;
00508                         }
00509 //
00510                 }
00511 
00512                 pos += 4;
00513                 break;
00514         }
00515 
00516         return ret;
00517 }
00518 
00519 /*
00520         Read and convert a colormap-index into an rgba-color.
00521         This function speculates in an index to exist in the 
00522         file directly at the current position.
00523 */
00524 void CL_TargaProvider::read_from_colormap(
00525         unsigned char *a,
00526         unsigned char *b,
00527         unsigned char *g,
00528         unsigned char *r)
00529 {
00530 //      cl_assert(pos < filesize);
00531         if (pos >= filesize)
00532                 throw CL_Error("Invalid targa file!?");
00533 
00534         // if the colormap is <= 256 entries large, the
00535         // index will be contained in a byte - 
00536         // otherwise in a short
00537         int entry;
00538         if (map_length <= 256)
00539         {
00540                 entry = file[pos++];
00541         }
00542         else
00543         {
00544                 entry = *((unsigned short *) &file[pos]);
00545                 SWAP_IF_BIG(entry);
00546                 pos += 2;
00547         }
00548 
00549 //      cl_assert(entry >= 0 && entry < map_length);
00550         if (entry < 0 || entry >= map_length)
00551                 throw CL_Error("Invalid targa file!?");
00552 
00553         // convert index-value to rgba-values using the colormap
00554         *r = color_map[entry*4+0];
00555         *g = color_map[entry*4+1];
00556         *b = color_map[entry*4+2];
00557         *a = color_map[entry*4+3];
00558 }
00559 
00560 /*
00561         CODE FOR DECODING TYPE 1 TARGA FILES
00562 */
00563 void CL_TargaProvider::read_colormapped()
00564 {
00565         read_header(true);
00566 
00567         image = new unsigned char[pitch * height * 4];
00568 
00569         int ystart = map_direction_y == 1 ? 0 : height-1;
00570         int xstart = map_direction_x == 1 ? 0 : pitch-1;
00571 
00572         for (int y = ystart;y>=0&&y<height;y+=map_direction_y)
00573         {
00574                 for (int x = xstart; x>=0 && x<pitch;x+=map_direction_x)
00575                 {
00576                         read_from_colormap(&image[(x+y*pitch)*4],
00577                                                                  &image[(x+y*pitch)*4+1],
00578                                                                  &image[(x+y*pitch)*4+2],
00579                                                                  &image[(x+y*pitch)*4+3]);
00580                 }
00581         }
00582 }
00583 
00584 /*
00585         CODE FOR DECODING TYPE 2 TARGA FILES
00586 */
00587 void CL_TargaProvider::read_uncompressed_rgb()
00588 {
00589         read_header(false);
00590 
00591         int ystart = map_direction_y == 1 ? 0 : height-1;
00592         int xstart = map_direction_x == 1 ? 0 : pitch-1;
00593 
00594         image = new unsigned char[pitch * height * 4];
00595         switch (bpp)
00596         {
00597         case 16:
00598                 {
00599                         for (int y = ystart;y>=0&&y<height;y+=map_direction_y)
00600                         {
00601                                 for (int x = xstart; x>=0 && x<pitch;x+=map_direction_x)
00602                                 {
00603                                         bool v = read_rgb_16(&image[(x+y*pitch)*4+0], 
00604                                                                                 &image[(x+y*pitch)*4+1],
00605                                                                                 &image[(x+y*pitch)*4+2],
00606                                                                                 &image[(x+y*pitch)*4+3]);
00607                                         if (v)
00608                                         {
00609                                                 if (x < bounding_left) bounding_left = x;
00610                                                 if (y < bounding_top) bounding_top = y;
00611                                                 if (x > bounding_right) bounding_right = x;
00612                                                 if (y > bounding_bottom) bounding_bottom = y;
00613                                         }
00614                                 }
00615                         }
00616                 }
00617                 break;
00618         
00619         case 24:
00620                 {
00621                         for (int y = ystart;y>=0&&y<height;y+=map_direction_y)
00622                         {
00623                                 for (int x = xstart; x>=0 && x<pitch;x+=map_direction_x)
00624                                 {
00625                                         bool v = read_rgb_24(&image[(x+y*pitch)*4+0], 
00626                                                                                                 &image[(x+y*pitch)*4+1],
00627                                                                                                 &image[(x+y*pitch)*4+2],
00628                                                                                                 &image[(x+y*pitch)*4+3]);
00629                                         if (v)
00630                                         {
00631                                                 if (x < bounding_left) bounding_left = x;
00632                                                 if (y < bounding_top) bounding_top = y;
00633                                                 if (x > bounding_right) bounding_right = x;
00634                                                 if (y > bounding_bottom) bounding_bottom = y;
00635                                         }
00636 
00637                                 }
00638                         }
00639                 }
00640                 break;
00641 
00642         case 32:
00643                 {
00644                         for (int y = ystart;y>=0&&y<height;y+=map_direction_y)
00645                         {
00646                                 for (int x = xstart; x>=0 && x<pitch;x+=map_direction_x)
00647                                 {
00648                                         bool v = read_rgb_32(&image[(x+y*pitch)*4+0], 
00649                                                                                 &image[(x+y*pitch)*4+1],
00650                                                                                 &image[(x+y*pitch)*4+2],
00651                                                                                 &image[(x+y*pitch)*4+3]);
00652                                         if (v)
00653                                         {
00654                                                 if (x < bounding_left) bounding_left = x;
00655                                                 if (y < bounding_top) bounding_top = y;
00656                                                 if (x > bounding_right) bounding_right = x;
00657                                                 if (y > bounding_bottom) bounding_bottom = y;
00658                                         }
00659                                 }
00660                         }
00661                 }
00662                 break;
00663 
00664         default: 
00665                 std::cout << "Unknown bpp!" << std::endl;
00666                 cl_assert(false);
00667         }
00668 }
00669 
00670 /*
00671         CODE FOR DECODING TYPE 9 TARGA FILES
00672 */
00673 
00674 void CL_TargaProvider::read_runlength_encoded_colormapped_rgb()
00675 {
00676         read_header(true);
00677 
00678         image = new unsigned char[pitch * height * 4];
00679         
00680         int ystart = map_direction_y == 1 ? 0 : height-1;
00681         int xstart = map_direction_x == 1 ? 0 : pitch-1;
00682 
00683         int line = ystart;
00684         int xpos = xstart;
00685         while (line >= 0 && line < height)
00686         {
00687                 unsigned char head = file[pos++];
00688                 unsigned char type = (head & 128)>>7;
00689                 unsigned char repcount = (head & 127)+1;
00690 
00691                 switch (type)
00692                 {
00693                 // RAW PACKET
00694                 case 0:
00695                         for (;repcount>0;repcount--)
00696                         {
00697                                 read_from_colormap(&image[(xpos+line*pitch)*4],
00698                                                                          &image[(xpos+line*pitch)*4+1],
00699                                                                          &image[(xpos+line*pitch)*4+2],
00700                                                                          &image[(xpos+line*pitch)*4+3]);
00701 
00702                                 xpos+=map_direction_x;
00703                                 if (xpos < 0 || xpos >= pitch)
00704                                 {
00705                                         xpos = xstart;
00706                                         line += map_direction_y;
00707                                 }
00708                         }
00709                         break;
00710 
00711                 // RUNLENGTH ENCODED PACKET
00712                 case 1:
00713                         {
00714                                 unsigned char r, g, b, a;
00715                                 read_from_colormap(&r, &g, &b, &a);
00716                                 
00717                                 for (;repcount>0;repcount--)
00718                                 {
00719                                         image[((line*pitch+xpos)*4)+0] = r;
00720                                         image[((line*pitch+xpos)*4)+1] = g;
00721                                         image[((line*pitch+xpos)*4)+2] = b;
00722                                         image[((line*pitch+xpos)*4)+3] = a;
00723 
00724                                         xpos+=map_direction_x;
00725                                         if (xpos < 0 || xpos >= pitch)
00726                                         {
00727                                                 xpos = xstart;
00728                                                 line += map_direction_y;
00729                                         }
00730                                 }
00731                         }
00732                         break;
00733                 }
00734         }
00735 }
00736 
00737 /*
00738         CODE FOR DECODING TYPE 10 TARGA FILES
00739 */
00740 void CL_TargaProvider::read_runlength_encoded_rgb()
00741 {
00742         read_header(false);
00743 
00744         image = new unsigned char[pitch * height * 4];
00745 
00746         int ystart = map_direction_y == 1 ? 0 : height-1;
00747         int xstart = map_direction_x == 1 ? 0 : pitch-1;
00748 
00749         int line = ystart;
00750         int xpos = xstart;
00751         while (line >= 0 && line < height)
00752         {
00753                 unsigned char head = file[pos++];
00754                 unsigned char type = (head & 128)>>7;
00755                 unsigned char repcount = (head & 127)+1;
00756 
00757                 switch (type)
00758                 {
00759                 // RAW PACKET
00760                 case 0:
00761                         for (;repcount>0;repcount--)
00762                         {
00763                                 bool v = read_rgb(&image[((line*pitch+xpos)*4)+0], 
00764                                                                         &image[((line*pitch+xpos)*4)+1],
00765                                                                         &image[((line*pitch+xpos)*4)+2],
00766                                                                         &image[((line*pitch+xpos)*4)+3]);
00767                                 if (v)
00768                                 {
00769                                         if (xpos < bounding_left) bounding_left = xpos;
00770                                         if (line < bounding_top) bounding_top = line;
00771                                         if (xpos > bounding_right) bounding_right = xpos;
00772                                         if (line > bounding_bottom) bounding_bottom = line;
00773                                 }
00774 
00775                                 xpos+=map_direction_x;
00776                                 if (xpos < 0 || xpos >= pitch)
00777                                 {
00778                                         xpos = xstart;
00779                                         line += map_direction_y;
00780                                 }
00781                         }
00782                         break;
00783 
00784                 // RUNLENGTH ENCODED PACKET
00785                 case 1:
00786                         {
00787                                 unsigned char r, g, b, a;
00788                                 bool v = read_rgb(&r, &g, &b, &a);
00789                                 
00790                                 for (;repcount>0;repcount--)
00791                                 {
00792                                         image[((line*pitch+xpos)*4)+0] = r;
00793                                         image[((line*pitch+xpos)*4)+1] = g;
00794                                         image[((line*pitch+xpos)*4)+2] = b;
00795                                         image[((line*pitch+xpos)*4)+3] = a;
00796 
00797                                         if (v)
00798                                         {
00799                                                 if (xpos < bounding_left) bounding_left = xpos;
00800                                                 if (line < bounding_top) bounding_top = line;
00801                                                 if (xpos > bounding_right) bounding_right = xpos;
00802                                                 if (line > bounding_bottom) bounding_bottom = line;
00803                                         }
00804 
00805                                         xpos+=map_direction_x;
00806                                         if (xpos < 0 || xpos >= pitch)
00807                                         {
00808                                                 xpos = xstart;
00809                                                 line += map_direction_y;
00810                                         }
00811                                 }
00812                         }
00813                         break;
00814                 }
00815         }
00816 }
00817 
00818 void *CL_TargaProvider::get_data() const
00819 {
00820         return image+bounding_left*4+bounding_top*pitch*4;
00821 }
00822 
00823 /*
00824         Lock the surfaceprovider - which basically means open the file
00825         and read the image into a temporary memory buffer - until
00826         unlock() is called.
00827 */
00828 void CL_TargaProvider::perform_lock()
00829 {
00830         if (locked) return;
00831 
00832         cl_assert(provider != NULL);
00833         input_source = provider->open_source(filename.c_str());
00834         cl_assert(input_source!=NULL);
00835 
00836         no_sprs = 1;
00837 
00838         filesize = input_source->size();
00839         file = new unsigned char[filesize];
00840         cl_assert(file != NULL);
00841 
00842         int num_bytes_read = input_source->read(file, filesize);
00843         cl_assert(num_bytes_read == ((int) filesize));
00844 
00845         // read the data
00846         read_data();
00847 
00848         if (bounding_left > bounding_right) bounding_left = bounding_right;
00849         if (bounding_top > bounding_bottom) bounding_top = bounding_bottom;
00850 
00851         delete[] file;
00852         delete input_source;
00853         file = NULL;
00854 
00855         locked = true;
00856 }
00857 
00858 void CL_TargaProvider::perform_unlock()
00859 {
00860         locked = false;
00861         delete[] color_map;
00862         delete[] image;
00863 
00864         image = color_map = NULL;
00865 }

Generated at Wed Apr 4 19:54:02 2001 for ClanLib by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001