PointScaler.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2005 The Pentagram Team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #include "pent_include.h"
00020 #include "PointScaler.h"
00021 #include "Manips.h"
00022 
00023 namespace Pentagram {
00024 
00025 // Very very simple point scaler
00026 template<class uintX, class Manip, class uintS=uintX> class PointScalerInternal
00027 {
00028 public:
00029         static bool Scale( Texture *tex , sint32 sx, sint32 sy, sint32 sw, sint32 sh, 
00030                                                 uint8* pixel, sint32 dw, sint32 dh, sint32 pitch, bool clamp_src)
00031         {
00032                 // Source buffer pointers
00033                 uintS *texel = reinterpret_cast<uintS*>(tex->buffer) + (sy * tex->width + sx);
00034                 int tpitch = tex->width;
00035                 uintS *tline_end = texel + sw;
00036                 uintS *tex_end = texel + sh*tex->width;
00037                 int tex_diff = tex->width - sw;
00038 
00039 
00040                 // First detect integer up scalings, since they are 'easy'
00041                 bool x_intscale = ((dw / sw) * sw) == dw;
00042                 bool y_intscale = ((dh / sh) * sh) == dh;
00043 
00044                 //
00045                 // 2x 
00046                 //
00047                 if ((sw*2 == dw) && (sh*2 == dh))
00048                 {
00049                         uint8 *pixel2 = pixel+pitch;
00050                         int p_diff    = (pitch*2)-(dw*sizeof(uintX));
00051 
00052                         // Src Loop Y
00053                         do {
00054                                 // Src Loop X
00055                                 do {
00056                                         uintX p = Manip::copy(*texel);
00057 
00058                                         *(reinterpret_cast<uintX*>(pixel+0)) = p;
00059                                         *(reinterpret_cast<uintX*>(pixel+sizeof(uintX))) = p;
00060                                         *(reinterpret_cast<uintX*>(pixel2+0)) = p;
00061                                         *(reinterpret_cast<uintX*>(pixel2+sizeof(uintX))) = p;
00062                                         pixel  += sizeof(uintX)*2;
00063                                         pixel2 += sizeof(uintX)*2;
00064                                         texel++;
00065                                 } while (texel != tline_end);
00066 
00067                                 pixel  += p_diff;
00068                                 pixel2 += p_diff;
00069 
00070                                 texel += tex_diff;
00071                                 tline_end += tpitch;
00072                         } while (texel != tex_end);
00073 
00074                 }
00075                 //
00076                 // Integer scaling, x and y
00077                 //
00078                 else if (x_intscale && y_intscale)
00079                 {
00080                         int xf = dw/sw;
00081                         int yf = dh/sh;
00082 
00083                         uint8 *px_end = pixel + xf*sizeof(uintX);
00084                         uint8 *py_end = pixel + yf*pitch;
00085 
00086                         int block_w = xf*sizeof(uintX);
00087                         int block_h = pitch*yf;
00088                         int block_xdiff = pitch - block_w;
00089                         int p_diff = block_h - dw*sizeof(uintX);
00090 
00091                         // Src Loop Y
00092                         do {
00093                                 // Src Loop X
00094                                 do {
00095                                         uintX p = Manip::copy(*texel);
00096 
00097                                         //
00098                                         // Inner loops
00099                                         //
00100 
00101                                         // Dest Loop Y
00102                                         do {
00103                                                 // Dest Loop X
00104                                                 do {
00105                                                         *(reinterpret_cast<uintX*>(pixel)) = p;
00106                                                         pixel+=sizeof(uintX);
00107                                                 } while (pixel != px_end);
00108 
00109                                                 pixel+=block_xdiff;
00110                                                 px_end+=pitch;
00111                                         } while (pixel != py_end);
00112 
00113                                         pixel  += block_w-block_h;
00114                                         px_end += block_w-block_h;
00115                                         py_end += block_w;
00116                                         texel++;
00117                                 } while (texel != tline_end);
00118 
00119                                 pixel += p_diff;
00120                                 py_end += p_diff;
00121                                 px_end += p_diff;
00122 
00123                                 texel += tex_diff;
00124                                 tline_end += tpitch;
00125                         } while (texel != tex_end);
00126 
00127                 }
00128                 //
00129                 // 2x X and Arbitrary Upscaled Y 
00130                 // Specifically to handle 320x200 -> 640x480
00131                 //
00132                 else if ((sw*2 == dw) && (dh >= sh))
00133                 {
00134                         uint32 pos_y;
00135                         uint32 end_y = dh;
00136                         uint32 dst_y = 0;
00137                         uint8* next_block = 0;
00138 
00139                         // Src Loop Y
00140                         do 
00141                         {
00142                                 next_block = pixel;
00143 
00144                                 // Src Loop X
00145                                 do
00146                                 {
00147                                         pos_y = dst_y;
00148 
00149                                         uintX p = Manip::copy(*texel);
00150 
00151                                         //
00152                                         // Inner loops
00153                                         //
00154                                         pixel = next_block;
00155                                         next_block = next_block+sizeof(uintX)*2;
00156 
00157                                         // Dest Loop Y
00158                                         do
00159                                         {
00160                                                 *(reinterpret_cast<uintX*>(pixel+0)) = p;
00161                                                 *(reinterpret_cast<uintX*>(pixel+sizeof(uintX))) = p;
00162                                                 pixel += pitch;
00163                                                 pos_y += sh;
00164                                         } while (pos_y < end_y);
00165 
00166                                         texel++;
00167                                 } while (texel != tline_end);
00168 
00169                                 pixel -= sizeof(uintX)*(dw-2);
00170                                 dst_y = pos_y;
00171                                 end_y += dh;
00172 
00173                                 texel += tex_diff;
00174                                 tline_end += tpitch;
00175                         } while (texel != tex_end);
00176                 }
00177                 //
00178                 // 1x X and Arbitrary Upscaled Y 
00179                 // Specifically to handle 640x400 -> 640x480
00180                 //
00181                 else if ((sw == dw) && (dh >= sh))
00182                 {
00183                         uint32 pos_y;
00184                         uint32 end_y = dh;
00185                         uint32 dst_y = 0;
00186                         uint8* next_block = 0;
00187 
00188                         // Src Loop Y
00189                         do 
00190                         {
00191                                 next_block = pixel;
00192 
00193                                 // Src Loop X
00194                                 do
00195                                 {
00196                                         pos_y = dst_y;
00197 
00198                                         uintX p = Manip::copy(*texel);
00199 
00200                                         //
00201                                         // Inner loops
00202                                         //
00203                                         pixel = next_block;
00204                                         next_block = next_block+sizeof(uintX);
00205 
00206                                         // Dest Loop Y
00207                                         do
00208                                         {
00209                                                 *(reinterpret_cast<uintX*>(pixel)) = p;
00210                                                 pixel += pitch;
00211                                                 pos_y += sh;
00212                                         } while (pos_y < end_y);
00213 
00214                                         texel++;
00215                                 } while (texel != tline_end);
00216 
00217                                 pixel -= sizeof(uintX)*(dw-1);
00218                                 dst_y = pos_y;
00219                                 end_y += dh;
00220 
00221                                 texel += tex_diff;
00222                                 tline_end += tpitch;
00223                         } while (texel != tex_end);
00224                 }
00225                 //
00226                 // Arbitrary scaling X and Y (optimized for upscaling)
00227                 //
00228                 else
00229                 {
00230                         uint32 pos_y, pos_x;
00231                         uint32 end_y = dh;
00232                         uint32 dst_y = 0;
00233                         uint8* blockline_start = 0;
00234                         uint8* next_block = 0;
00235 
00236                         // Src Loop Y
00237                         do 
00238                         {
00239                                 uint32 end_x = dw;
00240                                 uint32 dst_x = 0;
00241 
00242                                 next_block = pixel;
00243 
00244                                 // Src Loop X
00245                                 do
00246                                 {
00247                                         pos_y = dst_y;
00248 
00249                                         uintX p = Manip::copy(*texel);
00250 
00251                                         //
00252                                         // Inner loops
00253                                         //
00254                                         blockline_start = next_block;
00255                                         next_block = 0;
00256 
00257                                         // Dest Loop Y
00258                                         while (pos_y < end_y)
00259                                         {
00260                                                 pos_x = dst_x;
00261                                                 pixel = blockline_start;
00262 
00263                                                 // Dest Loop X
00264                                                 while (pos_x < end_x)
00265                                                 {
00266                                                         *(reinterpret_cast<uintX*>(pixel)) = p;
00267 
00268                                                         pixel+=sizeof(uintX);
00269                                                         pos_x += sw;
00270                                                 }
00271                                                 if (!next_block) next_block = pixel;
00272 
00273                                                 blockline_start += pitch;
00274 
00275                                                 pos_y += sh;
00276                                         }
00277 
00278                                         dst_x = pos_x;
00279                                         end_x += dw;
00280                                         texel++;
00281                                 } while (texel != tline_end);
00282 
00283                                 pixel += pitch - sizeof(uintX)*(dw);
00284 
00285                                 dst_y = pos_y;
00286                                 end_y += dh;
00287 
00288                                 texel += tex_diff;
00289                                 tline_end += tpitch;
00290                         } while (texel != tex_end);
00291                 }
00292 
00293                 return true;
00294         }
00295 
00296 };
00297 
00298 
00299 PointScaler::PointScaler() : Scaler()
00300 {
00301         Scale16Nat = PointScalerInternal<uint16, Manip_Nat2Nat_16, uint16>::Scale;
00302         Scale16Sta = PointScalerInternal<uint16, Manip_Sta2Nat_16, uint32>::Scale;
00303 
00304         Scale32Nat = PointScalerInternal<uint32, Manip_Nat2Nat_32, uint32>::Scale;
00305         Scale32Sta = PointScalerInternal<uint32, Manip_Sta2Nat_32, uint32>::Scale;
00306         Scale32_A888 = PointScalerInternal<uint32, Manip_32_A888, uint32>::Scale;
00307         Scale32_888A = PointScalerInternal<uint32, Manip_32_888A, uint32>::Scale;
00308 }
00309 
00310 const uint32 PointScaler::ScaleBits() const { return 0xFFFFFFFF; }
00311 const bool PointScaler::ScaleArbitrary() const { return true; }
00312 
00313 const char *PointScaler::ScalerName() const { return "point"; }
00314 const char *PointScaler::ScalerDesc() const { return "Fast Simple Point Scaler"; }
00315 const char *PointScaler::ScalerCopyright() const { return "Copyright (C) 2005 The Pentagram Team"; }
00316 
00317 const PointScaler point_scaler;
00318 
00319 };

Generated on Fri Jul 27 22:27:30 2007 for pentagram by  doxygen 1.4.7