00001 #include "vuFixelMap.h"
00002 #include <stddef.h>
00003 #include <fstream.h>
00004 #include <GL/gl.h>
00005 #include "vuFixelType.h"
00006 #include "math.h"
00007
00008 template <int S, class T>
00009 vuFixelMap<S,T>::vuFixelMap()
00010 {
00011 m_buffer = NULL;
00012 m_width = 0;
00013 m_height = 0;
00014 m_isBufferNewed = true;
00015 }
00016
00017 template <int S, class T>
00018 vuFixelMap<S,T>::vuFixelMap(dword width, dword height)
00019 {
00020 m_buffer = NULL;
00021 m_width = 0;
00022 m_height = 0;
00023 m_isBufferNewed = true;
00024 _ensureBuffer(width, height);
00025 }
00026
00027 template <int S, class T>
00028 vuFixelMap<S,T>::~vuFixelMap()
00029 {
00030 if((m_buffer != NULL) && m_isBufferNewed) delete m_buffer;
00031 m_isBufferNewed = true;
00032 m_buffer = NULL;
00033 }
00034
00035 template <int S, class T>
00036 vuFixelMap<S,T>::vuFixelMap(const vuFixelMap &other)
00037 {
00038
00039 m_buffer = NULL;
00040 m_width = 0;
00041 m_height = 0;
00042 m_isBufferNewed = true;
00043
00044 _ensureBuffer(other.m_width, other.m_height, other.getBuffer());
00045 }
00046
00047 template <int S, class T>
00048 void vuFixelMap<S,T>::setWidthAndHeight(const dword sizx, const dword sizy)
00049 {
00050 _ensureBuffer(sizx, sizy);
00051 }
00052
00053 template <int S, class T>
00054 dword vuFixelMap<S,T>::getWidth() const
00055 {
00056 return m_width;
00057 }
00058
00059 template <int S, class T>
00060 dword vuFixelMap<S,T>::getHeight() const
00061 {
00062 return m_height;
00063 }
00064
00065 template <int S, class T>
00066 void vuFixelMap<S,T>::setFixel(dword x, dword y, const vuFixel<S,T> &fixel)
00067 {
00068 T *pix = &m_buffer[(m_width*y+x)*S];
00069 for (dword i=0; i<S; i++) pix[i] = fixel[i];
00070 }
00071
00072 template <int S, class T>
00073 vuFixel<S,T> vuFixelMap<S,T>::getFixel(dword x, dword y)
00074 {
00075 T *ptr = m_buffer+((m_width*y+x)*S);
00076 return vuFixel<S,T>(ptr);
00077 }
00078
00079 template <int S, class T>
00080 const T* vuFixelMap<S,T>::getBuffer() const
00081 {
00082 return m_buffer;
00083 }
00084
00085 template <int S, class T>
00086 T* vuFixelMap<S,T>::getBuffer()
00087 {
00088 return m_buffer;
00089 }
00090
00091
00092
00093
00094
00095 template <int S, class T>
00096 void vuFixelMap<S,T>::initOpenGL(void)
00097 {
00098 glDisable(GL_LIGHTING);
00099 }
00100
00101 template <int S, class T>
00102 void vuFixelMap<S,T>::glResize(dword width, dword height)
00103 {
00104 if (m_width == 0 || m_height == 0)
00105 cerr << "WARNING: vuFixelMap.glResize(): width or height is 0." << endl;
00106 glPixelZoom((float)width/m_width,(float)height/m_height);
00107 }
00108
00109 template <int S, class T>
00110 void vuFixelMap<S,T>::glRender()
00111 {
00112 if (vuFixelType<T>::isByte()) {
00113 if (S == 1) {
00114 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00115 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_width);
00116
00117 glDrawPixels(m_width,m_height,GL_LUMINANCE,GL_UNSIGNED_BYTE,m_buffer);
00118 }
00119 else if (S == 2) {
00120 glDrawPixels(m_width, m_height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, m_buffer);
00121 }
00122 else if (S == 3) {
00123 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00124 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_width);
00125 glDrawPixels(m_width, m_height, GL_RGB, GL_UNSIGNED_BYTE, m_buffer);
00126 }
00127 else {
00128 cerr << "WARNING: vuFixelMap.glRender():: case not implemented yet";
00129 cerr << " (S=" << S << ")" << endl;
00130 }
00131 }
00132 else if (vuFixelType<T>::isFloat()) {
00133 if (S == 1) {
00134 glDrawPixels(m_width, m_height, GL_LUMINANCE, GL_FLOAT, m_buffer);
00135 }
00136 else if (S == 2) {
00137 glDrawPixels(m_width, m_height, GL_LUMINANCE_ALPHA, GL_FLOAT, m_buffer);
00138 }
00139 else if (S == 3) {
00140 glDrawPixels(m_width, m_height, GL_RGB, GL_FLOAT, m_buffer);
00141 }
00142 else {
00143 cerr << "WARNING: vuFixelMap.glRender():: case not implemented yet";
00144 cerr << " (S=" << S << ")" << endl;
00145 }
00146 }
00147 else {
00148 cerr << "WARNING: vuFixelMap.glRender():: case not implemented yet";
00149 cerr << " (T unknown)" << endl;
00150 }
00151 }
00152
00153 template <int S, class T>
00154 vuFixelMap<S,T> &vuFixelMap<S,T>::operator=(const vuFixelMap<S,T> &other)
00155 {
00156 if (this == &other) return *this;
00157 _ensureBuffer(other.m_width, other.m_height, other.getBuffer());
00158 return *this;
00159 }
00160
00161 template <int S, class T>
00162 vuFixelMap<S,T> &vuFixelMap<S,T>::operator=(const vuFixel<S,T> &fixel)
00163 {
00164 dword len = getWidth() * getHeight();
00165 T *ptr = getBuffer();
00166
00167 for (;len>0;len--) {
00168 for (dword i=0; i<S; i++,ptr++) *ptr = fixel[i];
00169 }
00170
00171 return *this;
00172 }
00173
00174 template <int S, class T>
00175 vuFixelMap<S,T> &vuFixelMap<S,T>::operator+=(vuFixelMap<S,T> &other)
00176 {
00177 if (m_width != other.getWidth() || m_height != other.getHeight()) {
00178 cerr << "Warning: vuFixelMap::operator+= width or height are not equal!";
00179 cerr << endl;
00180 return *this;
00181 }
00182
00183 dword len = getWidth() * getHeight() * S;
00184 T *dest = getBuffer();
00185 T *src = other.getBuffer();
00186
00187 for (;len>0;len--) *(dest++) += *(src++);
00188
00189 return *this;
00190 }
00191
00192 template <int S, class T>
00193 vuFixelMap<S,T> &vuFixelMap<S,T>::operator+=(float bias)
00194 {
00195 dword len = getWidth() * getHeight() * S;
00196 T *dest = getBuffer();
00197
00198 float minValue = vuFixelType<T>::getMinValue();
00199 float maxValue = vuFixelType<T>::getMaxValue();
00200
00201 for (;len>0;len--) {
00202 register float tmp = (*dest + bias);
00203
00204 if (tmp > maxValue)
00205 tmp = maxValue;
00206 else if (tmp < minValue)
00207 tmp = minValue;
00208
00209 *dest = (T)tmp;
00210 }
00211
00212 return *this;
00213 }
00214
00215 template <int S, class T>
00216 vuFixelMap<S,T> &vuFixelMap<S,T>::operator-=(float bias)
00217 {
00218 dword len = getWidth() * getHeight() * S;
00219 T *dest = getBuffer();
00220
00221 float minValue = vuFixelType<T>::getMinValue();
00222 float maxValue = vuFixelType<T>::getMaxValue();
00223
00224 for (;len>0;len--) {
00225 register float tmp = (*dest - bias);
00226
00227 if (tmp > maxValue)
00228 tmp = maxValue;
00229 else if (tmp < minValue)
00230 tmp = minValue;
00231
00232 *(dest++) = (T)tmp;
00233 }
00234
00235 return *this;
00236 }
00237
00238
00239
00240 template <int S, class T>
00241 vuFixelMap<S,T> &vuFixelMap<S,T>::operator-=(vuFixelMap<S,T> &other)
00242 {
00243 if (m_width != other.getWidth() || m_height != other.getHeight()) {
00244 cerr << "Warning: vuFixelMap::operator-= width or height are not equal!";
00245 cerr << endl;
00246 return *this;
00247 }
00248
00249 dword len = getWidth() * getHeight() * S;
00250 T *dest = getBuffer();
00251 T *src = other.getBuffer();
00252
00253 for (;len>0;len--) *(dest++) -= *(src++);
00254
00255 return *this;
00256 }
00257
00258
00259 template <int S, class T>
00260 vuFixelMap<S,T> &vuFixelMap<S,T>::operator*=(float scale)
00261 {
00262 T *ptr = getBuffer();
00263 dword len = getWidth() * getHeight() * S;
00264
00265 float minValue = vuFixelType<T>::getMinValue();
00266 float maxValue = vuFixelType<T>::getMaxValue();
00267
00268 for (;len>0;len--,ptr++) {
00269 register float tmp = (*ptr * scale);
00270
00271 if (tmp > maxValue)
00272 tmp = maxValue;
00273 else if (tmp < minValue)
00274 tmp = minValue;
00275
00276 *ptr = (T)tmp;
00277 }
00278
00279 return *this;
00280 }
00281
00282 template <int S, class T>
00283 vuFixelMap<S,T> &vuFixelMap<S,T>::operator/=(float scale)
00284 {
00285 T *ptr = getBuffer();
00286 dword len = getWidth() * getHeight() * S;
00287
00288 float minValue = vuFixelType<T>::getMinValue();
00289 float maxValue = vuFixelType<T>::getMaxValue();
00290
00291 for (;len>0;len--,ptr++) {
00292 register float tmp = (*ptr / scale);
00293
00294 if (tmp > maxValue)
00295 tmp = maxValue;
00296 else if (tmp < minValue)
00297 tmp = minValue;
00298
00299 *ptr = (T)tmp;
00300 }
00301
00302 return *this;
00303 }
00304
00305 template <int S, class T>
00306 bool vuFixelMap<S,T>::writeToFileStream(ostream *out)
00307 {
00308 dword size = m_width * m_height * S;
00309
00310 if (out && (size > 0) && m_buffer) {
00311 out->write((const char *)m_buffer, size * sizeof(T));
00312 return !out->bad();
00313 }
00314 return false;
00315 }
00316
00317 template <int S, class T>
00318 bool vuFixelMap<S,T>::readFromFileStream(istream *in, dword width, dword height)
00319 {
00320 dword size = width * height * S;
00321
00322 if (in && (size > 0)) {
00323 if (m_isBufferNewed) CHECKNDELETE (m_buffer);
00324
00325 T *buffer = new T[size];
00326 in->read((char *)buffer, size * sizeof(T));
00327 if (in->bad()) return false;
00328 _ensureBuffer(width, height, buffer);
00329 return true;
00330 }
00331 return false;
00332 }
00333
00334 template <int S, class T>
00335 void vuFixelMap<S,T>::assignBuffer(T *buffer, dword width, dword height)
00336 {
00337 if (buffer != NULL) {
00338 if ((m_buffer != NULL) && m_isBufferNewed) delete m_buffer;
00339 m_buffer = buffer;
00340 m_isBufferNewed = false;
00341 m_width = width;
00342 m_height = height;
00343 }
00344 }
00345
00346 template <int S, class T>
00347 void vuFixelMap<S,T>::writeBufferToFile(FILE *file)
00348 {
00349 fwrite(m_buffer, sizeof(T), S * m_width * m_height, file);
00350 }
00351
00352
00353
00354
00355
00356 template <int S, class T>
00357 void vuFixelMap<S,T>::getMinAndMaxValue(T &minValue, T &maxValue)
00358 {
00359 T minVal, maxVal;
00360
00361 minValue = vuFixelType<T>::getPosInfinity();
00362 maxValue = vuFixelType<T>::getNegInfinity();
00363
00364 for (int i=0; i<S; i++) {
00365
00366 getMinAndMaxValue(minVal, maxVal, i);
00367
00368 if (minValue > minVal) minValue = minVal;
00369 if (maxValue < maxVal) maxValue = maxVal;
00370 }
00371 }
00372
00373 template <int S, class T>
00374 void vuFixelMap<S,T>::getMinAndMaxValue(T &minValue, T &maxValue, word channel)
00375 {
00376 T *ptr = getBuffer();
00377 dword cnt = getWidth() * getHeight();
00378
00379
00380 minValue = vuFixelType<T>::getPosInfinity();
00381 maxValue = vuFixelType<T>::getNegInfinity();
00382
00383 for (dword i=0; i<cnt; i++) {
00384 register T tmp = ptr[channel];
00385
00386 if (minValue > tmp) minValue = tmp;
00387 if (maxValue < tmp) maxValue = tmp;
00388 ptr += S;
00389 }
00390 }
00391
00392
00393
00394
00395
00396 template <int S, class T>
00397 void vuFixelMap<S,T>::scaleAndBias(float scale, T bias)
00398 {
00399 T *ptr = getBuffer();
00400 dword len = getWidth() * getHeight() * S;
00401 float minValue = vuFixelType<T>::getMinValue();
00402 float maxValue = vuFixelType<T>::getMaxValue();
00403
00404 for (;len>0;len--,ptr++) {
00405 register float tmp = (float)(*ptr * scale) + (float)bias;
00406 if (tmp < minValue)
00407 tmp = (T)minValue;
00408 else if (tmp > maxValue)
00409 tmp = (T)maxValue;
00410 *ptr = (T)tmp;
00411 }
00412 }
00413
00414 template <int S, class T>
00415 void vuFixelMap<S,T>::copyMapToChannel(vuFixelMap<1,T> *map, word channel)
00416 {
00417 if (channel>=S) {
00418 cerr << "Warning: vuFixelMap::copyMapToChannel: channel>= SIZE" << endl;
00419 return;
00420 }
00421 T *dest = getBuffer();
00422 T *src = map->getBuffer();
00423 dword cnt = getWidth() * getHeight();
00424
00425 for (dword i=0; i<cnt; i++) {
00426 dest[channel] = *(src++);
00427 dest += S;
00428 }
00429 }
00430
00431 template <int S, class T>
00432 void vuFixelMap<S,T>::getChannel(vuFixelMap<1,T>* &map, word channel)
00433 {
00434 if (channel>=S) {
00435 cerr << "Warning: vuFixelMap::getChannel: channel>= SIZE" << endl;
00436 return;
00437 }
00438
00439 if (map == NULL) map = new vuFixelMap<1,T>(getWidth(), getHeight());
00440
00441 T *dest = map->getBuffer();
00442 T *src = getBuffer();
00443 dword cnt = getWidth() * getHeight();
00444
00445 for (dword i=0; i<cnt; i++) {
00446 *(dest++) = src[channel];
00447 src += S;
00448 }
00449 }
00450
00451 template <int S, class T>
00452 void vuFixelMap<S,T>::clear(vuFixel<S,T> clearColour)
00453 {
00454 T *ptr = getBuffer();
00455 dword len = getWidth() * getHeight();
00456
00457 for (;len>0;len--,ptr++) {
00458 for (int i=0; i<S; i++) {
00459 ptr[i] = clearColour[i];
00460 }
00461 }
00462 }
00463
00464 template <int S, class T>
00465 bool vuFixelMap<S,T>::hasSameDimensions(vuFixelMap_ST *other)
00466 {
00467 if (other == NULL)
00468 return false;
00469 else if (this->getWidth() != other->getWidth())
00470 return false;
00471 else if (this->getHeight() != other->getHeight())
00472 return false;
00473
00474 return true;
00475 }
00476
00477
00478
00479
00480
00481
00482
00483 template <int S, class T>
00484 ostream &vuFixelMap<S,T>::write(ostream& os)
00485 {
00486 T *ptr = getBuffer();
00487 dword len = getWidth() * getHeight() * S;
00488
00489 for (;len>0;len--,ptr++) {
00490 os << (*ptr) << " ";
00491 }
00492 return os;
00493 }
00494
00495 template <int S, class T>
00496 istream &vuFixelMap<S,T>::read(istream& is)
00497 {
00498 T *ptr = getBuffer();
00499 dword len = getWidth() * getHeight() * S;
00500
00501 for (;len>0;len--,ptr++) {
00502 is >> *ptr;
00503 }
00504 return is;
00505 }
00506
00507 template <int S, class T>
00508 void vuFixelMap<S,T>::_ensureBuffer(dword sizx, dword sizy, const T* source)
00509 {
00510 if (m_buffer == NULL) m_isBufferNewed = true;
00511
00512 if (!m_isBufferNewed && (sizx != m_width || sizy != m_height)) {
00513 cerr << "ERROR: vuFixelMap._ensureBuffer(): can't change buffer size";
00514 cerr << " , since an external buffer is used" << endl;
00515 throw "vuFixelMap._ensureBuffer(): can't change buffer size, since"
00516 "an external buffer is used";
00517 return;
00518 }
00519
00520 if ((sizx != m_width) || (sizy != m_height)) {
00521 m_width=sizx;
00522 m_height=sizy;
00523 if ((m_buffer != NULL) && m_isBufferNewed) {
00524 delete m_buffer;
00525 m_buffer = NULL;
00526 }
00527 }
00528
00529 if ((m_width == 0) || (m_height == 0)) return;
00530
00531 if(m_buffer == NULL) {
00532 m_buffer = new T[m_width*m_height*S];
00533 m_isBufferNewed = true;
00534 }
00535
00536 if (source == NULL) {
00537 T *ptr = m_buffer;
00538 dword len = m_width*m_height*S;
00539
00540 for(;len>0;len--,ptr++) *ptr = 0;
00541 }
00542 else {
00543 T *dest = m_buffer;
00544 const T *src = source;
00545 dword len = m_width*m_height*S;
00546
00547 for(;len>0;len--,dest++,src++) *dest= *src;
00548 }
00549 }
00550
00551
00552
00553
00554
00555
00556 template <int S,class T>
00557 void vuFixelMap<S,T>::_shearX(float shear, vuFixelMap<S,T>* inMap,
00558 vuFixelMap<S,T>* &outMap)
00559 {
00560 if (inMap == NULL) return;
00561
00562 dword inHeight = inMap->getHeight();
00563 dword inWidth = inMap->getWidth();
00564 dword outHeight = inHeight;
00565 dword outWidth = (dword)(inHeight * fabs(shear)) + inWidth;
00566
00567 if (outMap == NULL) {
00568 outMap = new vuFixelMap<S,T>(outWidth, outHeight);
00569 }
00570 else if (outMap->getWidth()!=outWidth || outMap->getHeight()!=outHeight) {
00571 CHECKNDELETE(outMap);
00572 outMap = new vuFixelMap<S,T>(outWidth, outHeight);
00573 }
00574 *outMap = (T)0;
00575
00576 T left[S];
00577 T oldLeft[S];
00578 T *inBuffer = inMap->getBuffer();
00579
00580 for (dword j=0; j<inHeight; j++) {
00581 float skew = shear * j;
00582 int skewi = (int)(skew);
00583 float skewf = skew - skewi;
00584
00585 for (int k=0; k<S; k++) oldLeft[k] = 0;
00586
00587 dword idx = (shear >= 0) ? skewi : outWidth + skewi - inWidth;
00588 T *outBuffer = outMap->getBuffer();
00589
00590 outBuffer += (j*outWidth + idx) * S;
00591 for (dword i=0; i<inWidth; i++) {
00592 for (int k=0; k<S; k++) {
00593 register T fixel = *(inBuffer++);
00594 register float tmp = fixel * skewf;
00595
00596 if (tmp < 0.0f) tmp = 0.0f;
00597 else if (tmp > 255.0f) tmp = 255.0f;
00598
00599 left[k] = (T)tmp;
00600 fixel = fixel - left[k] + oldLeft[k];
00601 *(outBuffer++) = fixel;
00602 oldLeft[k] = left[k];
00603 }
00604 }
00605 }
00606 }
00607
00608 template <int S, class T>
00609 void vuFixelMap<S,T>::_shearY(float shear, vuFixelMap<S,T>* inMap,
00610 vuFixelMap<S,T>* &outMap)
00611 {
00612 if (inMap == NULL) return;
00613
00614 dword inHeight = inMap->getHeight();
00615 dword inWidth = inMap->getWidth();
00616 dword outHeight = (dword)(inWidth * fabs(shear)) + inHeight;
00617 dword outWidth = inWidth;
00618
00619 if (outMap == NULL) {
00620 outMap = new vuFixelMap<S,T>(outWidth, outHeight);
00621 }
00622 else if (outMap->getWidth() != outWidth || outMap->getHeight() != outHeight){
00623 CHECKNDELETE(outMap);
00624 outMap = new vuFixelMap<S,T>(outWidth, outHeight);
00625 }
00626 *outMap = (T)0;
00627
00628 T old[S];
00629 T *inBuffer = inMap->getBuffer();
00630 T *outBuffer = outMap->getBuffer();
00631
00632 for (dword j=0; j<inWidth; j++) {
00633 float skew = shear * j;
00634 int skewi = (int)(skew);
00635 float skewf = skew - skewi;
00636
00637 for (int k=0; k<S; k++) old[k] = 0;
00638
00639 dword idx = (shear >= 0) ? skewi : outHeight + skewi - inHeight;
00640 for (dword i=0; i<inHeight; i++) {
00641 dword idx1 = (j+(i*inWidth)) * S;
00642 dword idx2 = (j+(idx+i)*outWidth) * S;
00643
00644 for (int k=0; k<S; k++) {
00645 register T fixel = inBuffer[idx1];
00646 register float valF = fixel * skewf;
00647
00648 if (valF < 0.0f) valF = 0.0f;
00649 else if (valF > 255.0f) valF = 255.0f;
00650
00651 register T valT = (T)valF;
00652
00653 fixel = fixel - valT + old[k];
00654 outBuffer[idx2] = fixel;
00655 old[k] = valT;
00656 idx1++;
00657 idx2++;
00658 }
00659 }
00660 }
00661 }
00662
00663 template <int S, class T>
00664 void vuFixelMap<S,T>::rotate90()
00665 {
00666 if (m_width != m_height) {
00667 cerr << "rotate90(): width != height, case not implemented!!!" << endl;
00668 throw "rotate90(): width != height, case not implemented!!!";
00669 }
00670
00671 dword y_step = m_width * S;
00672 T *buffer = getBuffer();
00673
00674 vuFixelMap<S,T> *myMap = new vuFixelMap<S,T>(m_width, m_height);
00675 *myMap = *this;
00676 T *ptr = myMap->getBuffer();
00677 *this = (T)0;
00678
00679 for (dword j=0; j<m_height; j++) {
00680 T *s_ptr = ptr;
00681 T *d_ptr = buffer + (m_width - j) * S;
00682 for (dword i=0; i<m_width; i++) {
00683 for (int k=0; k<S; k++) {
00684 *(d_ptr++) = *(s_ptr++);
00685 }
00686 d_ptr += y_step - S;
00687 }
00688 ptr += y_step;
00689 }
00690 CHECKNDELETE(myMap);
00691 }
00692
00693 template <int S, class T>
00694 void vuFixelMap<S,T>::rotate180()
00695 {
00696 dword count = m_width * m_height;
00697 T *d_ptr = getBuffer();
00698 T *s_ptr = getBuffer();
00699 d_ptr += (count - 1) * S;
00700
00701 count = count / 2;
00702
00703 for (dword i=0; i<count; i++) {
00704 for (dword j=0; j<S; j++) {
00705 T tmp = *s_ptr;
00706 *(s_ptr++) = *d_ptr;
00707 *(d_ptr++) = tmp;
00708 }
00709 d_ptr -= S+S;
00710 }
00711 }
00712
00713 template <int S, class T>
00714 void vuFixelMap<S,T>::rotate270()
00715 {
00716 rotate180();
00717 rotate90();
00718 }
00719
00720
00721 template <int S, class T>
00722 void vuFixelMap<S,T>::rotate(float angle)
00723 {
00724 if (angle == 0) return;
00725
00726 vuFixelMap<S,T> *map1 = NULL;
00727 vuFixelMap<S,T> *map2 = NULL;
00728
00729 while (angle > 360) angle -= 360;
00730 while (angle < 0) angle += 360;
00731
00732 if (angle >= 315)
00733 angle -= 360;
00734 else if (angle >= 225) {
00735 angle -= 270;
00736 rotate270();
00737 }
00738 else if (angle >= 135) {
00739 angle -= 180;
00740 rotate180();
00741 }
00742 else if (angle >= 45) {
00743 angle -= 90;
00744 rotate90();
00745 }
00746
00747 angle *= M_PI / 180;
00748
00749 float alpha = -tan(angle/2);
00750 float beta = sin(angle);
00751
00752
00753 _shearX(alpha, this, map1);
00754 _shearY(beta, map1, map2);
00755 CHECKNDELETE(map1);
00756 _shearX(alpha, map2, map1);
00757 CHECKNDELETE(map2);
00758
00759
00760 dword outWidth = map1->getWidth();
00761 dword outHeight = map1->getHeight();
00762 dword deltaX = (outWidth - m_width) / 2;
00763 dword deltaY = (outHeight - m_height) / 2;
00764 dword y_step = outWidth * S;
00765
00766 T *s_ptr = map1->getBuffer() + y_step * deltaY + deltaX * S;
00767 T *d_ptr = getBuffer();
00768
00769 for (dword j=0; j<m_height; j++) {
00770 T *ptr = s_ptr;
00771 for (dword i=0; i<m_width; i++) {
00772 for (int k=0; k<S; k++) {
00773 *(d_ptr++) = *(ptr++);
00774 }
00775 }
00776 s_ptr += y_step;
00777 }
00778 CHECKNDELETE(map1);
00779 }