Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

729 lines
16 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include <tier0/platform.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <math.h>
  10. #include <stdlib.h>
  11. #include "bitmap/float_bm.h"
  12. #include <tier2/tier2.h>
  13. #include "bitmap/imageformat.h"
  14. #include "bitmap/tgaloader.h"
  15. #include "tier1/strtools.h"
  16. #include "filesystem.h"
  17. #define SQ(x) ((x)*(x))
  18. // linear interpolate between 2 control points (L,R)
  19. inline float LinInterp(float frac, float L, float R)
  20. {
  21. return (((R-L) * frac) + L);
  22. }
  23. // bilinear interpolate between 4 control points (UL,UR,LL,LR)
  24. inline float BiLinInterp(float Xfrac, float Yfrac, float UL, float UR, float LL, float LR)
  25. {
  26. float iu = LinInterp(Xfrac, UL, UR);
  27. float il = LinInterp(Xfrac, LL, LR);
  28. return( LinInterp(Yfrac, iu, il) );
  29. }
  30. FloatBitMap_t::FloatBitMap_t(int width, int height)
  31. {
  32. RGBAData=0;
  33. AllocateRGB(width,height);
  34. }
  35. FloatBitMap_t::FloatBitMap_t(FloatBitMap_t const *orig)
  36. {
  37. RGBAData=0;
  38. AllocateRGB(orig->Width,orig->Height);
  39. memcpy(RGBAData,orig->RGBAData,Width*Height*sizeof(float)*4);
  40. }
  41. static char GetChar(FileHandle_t &f)
  42. {
  43. char a;
  44. g_pFullFileSystem->Read(&a,1,f);
  45. return a;
  46. }
  47. static int GetInt(FileHandle_t &f)
  48. {
  49. char buf[100];
  50. char *bout=buf;
  51. for(;;)
  52. {
  53. char c=GetChar(f);
  54. if ((c<'0') || (c>'9'))
  55. break;
  56. *(bout++)=c;
  57. }
  58. *(bout++)=0;
  59. return atoi(buf);
  60. }
  61. #define PFM_MAX_XSIZE 2048
  62. bool FloatBitMap_t::LoadFromPFM(char const *fname)
  63. {
  64. FileHandle_t f = g_pFullFileSystem->Open(fname, "rb");
  65. if (f)
  66. {
  67. if( ( GetChar(f) == 'P' ) && (GetChar(f) == 'F' ) && ( GetChar(f) == '\n' ))
  68. {
  69. Width=GetInt(f);
  70. Height=GetInt(f);
  71. // eat crap until the next newline
  72. while( GetChar(f) != '\n')
  73. {
  74. }
  75. // printf("file %s w=%d h=%d\n",fname,Width,Height);
  76. AllocateRGB(Width,Height);
  77. for( int y = Height-1; y >= 0; y-- )
  78. {
  79. float linebuffer[PFM_MAX_XSIZE*3];
  80. g_pFullFileSystem->Read(linebuffer,3*Width*sizeof(float),f);
  81. for(int x=0;x<Width;x++)
  82. {
  83. for(int c=0;c<3;c++)
  84. {
  85. Pixel(x,y,c)=linebuffer[x*3+c];
  86. }
  87. }
  88. }
  89. }
  90. g_pFullFileSystem->Close( f ); // close file after reading
  91. }
  92. return (RGBAData!=0);
  93. }
  94. bool FloatBitMap_t::WritePFM(char const *fname)
  95. {
  96. FileHandle_t f = g_pFullFileSystem->Open(fname, "wb");
  97. if ( f )
  98. {
  99. g_pFullFileSystem->FPrintf(f,"PF\n%d %d\n-1.000000\n",Width,Height);
  100. for( int y = Height-1; y >= 0; y-- )
  101. {
  102. float linebuffer[PFM_MAX_XSIZE*3];
  103. for(int x=0;x<Width;x++)
  104. {
  105. for(int c=0;c<3;c++)
  106. {
  107. linebuffer[x*3+c]=Pixel(x,y,c);
  108. }
  109. }
  110. g_pFullFileSystem->Write(linebuffer,3*Width*sizeof(float),f);
  111. }
  112. g_pFullFileSystem->Close(f);
  113. return true;
  114. }
  115. return false;
  116. }
  117. float FloatBitMap_t::InterpolatedPixel(float x, float y, int comp) const
  118. {
  119. int Top= floor(y);
  120. float Yfrac= y - Top;
  121. int Bot= min(Height-1,Top+1);
  122. int Left= floor(x);
  123. float Xfrac= x - Left;
  124. int Right= min(Width-1,Left+1);
  125. return
  126. BiLinInterp(Xfrac, Yfrac,
  127. Pixel(Left, Top, comp),
  128. Pixel(Right, Top, comp),
  129. Pixel(Left, Bot, comp),
  130. Pixel(Right, Bot, comp));
  131. }
  132. //-----------------------------------------------------------------
  133. // resize (with bilinear filter) truecolor bitmap in place
  134. void FloatBitMap_t::ReSize(int NewWidth, int NewHeight)
  135. {
  136. float XRatio= (float)Width / (float)NewWidth;
  137. float YRatio= (float)Height / (float)NewHeight;
  138. float SourceX, SourceY, Xfrac, Yfrac;
  139. int Top, Bot, Left, Right;
  140. float *newrgba=new float[NewWidth * NewHeight * 4];
  141. SourceY= 0;
  142. for(int y=0;y<NewHeight;y++)
  143. {
  144. Yfrac= SourceY - floor(SourceY);
  145. Top= SourceY;
  146. Bot= SourceY+1;
  147. if (Bot>=Height) Bot= Height-1;
  148. SourceX= 0;
  149. for(int x=0;x<NewWidth;x++)
  150. {
  151. Xfrac= SourceX - floor(SourceX);
  152. Left= SourceX;
  153. Right= SourceX+1;
  154. if (Right>=Width) Right= Width-1;
  155. for(int c=0;c<4;c++)
  156. {
  157. newrgba[4*(y*NewWidth+x)+c] = BiLinInterp(Xfrac, Yfrac,
  158. Pixel(Left, Top, c),
  159. Pixel(Right, Top, c),
  160. Pixel(Left, Bot, c),
  161. Pixel(Right, Bot, c));
  162. }
  163. SourceX+= XRatio;
  164. }
  165. SourceY+= YRatio;
  166. }
  167. delete[] RGBAData;
  168. RGBAData=newrgba;
  169. Width=NewWidth;
  170. Height=NewHeight;
  171. }
  172. struct TGAHeader_t
  173. {
  174. unsigned char id_length, colormap_type, image_type;
  175. unsigned char colormap_index0,colormap_index1, colormap_length0,colormap_length1;
  176. unsigned char colormap_size;
  177. unsigned char x_origin0,x_origin1, y_origin0,y_origin1, width0, width1,height0,height1;
  178. unsigned char pixel_size, attributes;
  179. };
  180. bool FloatBitMap_t::WriteTGAFile(char const *filename) const
  181. {
  182. FileHandle_t f = g_pFullFileSystem->Open(filename, "wb");
  183. if (f)
  184. {
  185. TGAHeader_t myheader;
  186. memset(&myheader,0,sizeof(myheader));
  187. myheader.image_type=2;
  188. myheader.pixel_size=32;
  189. myheader.width0= Width & 0xff;
  190. myheader.width1= (Width>>8);
  191. myheader.height0= Height & 0xff;
  192. myheader.height1= (Height>>8);
  193. myheader.attributes=0x20;
  194. g_pFullFileSystem->Write(&myheader,sizeof(myheader),f);
  195. // now, write the pixels
  196. for(int y=0;y<Height;y++)
  197. {
  198. for(int x=0;x<Width;x++)
  199. {
  200. PixRGBAF fpix = PixelRGBAF( x, y );
  201. PixRGBA8 pix8 = PixRGBAF_to_8( fpix );
  202. g_pFullFileSystem->Write(&pix8.Blue,1,f);
  203. g_pFullFileSystem->Write(&pix8.Green,1,f);
  204. g_pFullFileSystem->Write(&pix8.Red,1,f);
  205. g_pFullFileSystem->Write(&pix8.Alpha,1,f);
  206. }
  207. }
  208. g_pFullFileSystem->Close( f ); // close file after reading
  209. return true;
  210. }
  211. return false;
  212. }
  213. FloatBitMap_t::FloatBitMap_t(char const *tgafilename)
  214. {
  215. RGBAData=0;
  216. // load from a tga or pfm
  217. if (Q_stristr(tgafilename, ".pfm"))
  218. {
  219. LoadFromPFM(tgafilename);
  220. return;
  221. }
  222. int width1, height1;
  223. ImageFormat imageFormat1;
  224. float gamma1;
  225. if( !TGALoader::GetInfo( tgafilename, &width1, &height1, &imageFormat1, &gamma1 ) )
  226. {
  227. printf( "error loading %s\n", tgafilename);
  228. exit( -1 );
  229. }
  230. AllocateRGB(width1,height1);
  231. uint8 *pImage1Tmp =
  232. new uint8 [ImageLoader::GetMemRequired( width1, height1, 1, imageFormat1, false )];
  233. if( !TGALoader::Load( pImage1Tmp, tgafilename, width1, height1, imageFormat1, 2.2f, false ) )
  234. {
  235. printf( "error loading %s\n", tgafilename);
  236. exit( -1 );
  237. }
  238. uint8 *pImage1 =
  239. new uint8 [ImageLoader::GetMemRequired( width1, height1, 1, IMAGE_FORMAT_ABGR8888, false )];
  240. ImageLoader::ConvertImageFormat( pImage1Tmp, imageFormat1, pImage1, IMAGE_FORMAT_ABGR8888, width1, height1, 0, 0 );
  241. for(int y=0;y<height1;y++)
  242. {
  243. for(int x=0;x<width1;x++)
  244. {
  245. for(int c=0;c<4;c++)
  246. {
  247. Pixel(x,y,3-c)=pImage1[c+4*(x+(y*width1))]/255.0;
  248. }
  249. }
  250. }
  251. delete[] pImage1;
  252. delete[] pImage1Tmp;
  253. }
  254. FloatBitMap_t::~FloatBitMap_t(void)
  255. {
  256. if (RGBAData)
  257. delete[] RGBAData;
  258. }
  259. FloatBitMap_t *FloatBitMap_t::QuarterSize(void) const
  260. {
  261. // generate a new bitmap half on each axis
  262. FloatBitMap_t *newbm=new FloatBitMap_t(Width/2,Height/2);
  263. for(int y=0;y<Height/2;y++)
  264. for(int x=0;x<Width/2;x++)
  265. {
  266. for(int c=0;c<4;c++)
  267. newbm->Pixel(x,y,c)=((Pixel(x*2,y*2,c)+Pixel(x*2+1,y*2,c)+
  268. Pixel(x*2,y*2+1,c)+Pixel(x*2+1,y*2+1,c))/4);
  269. }
  270. return newbm;
  271. }
  272. FloatBitMap_t *FloatBitMap_t::QuarterSizeBlocky(void) const
  273. {
  274. // generate a new bitmap half on each axis
  275. FloatBitMap_t *newbm=new FloatBitMap_t(Width/2,Height/2);
  276. for(int y=0;y<Height/2;y++)
  277. for(int x=0;x<Width/2;x++)
  278. {
  279. for(int c=0;c<4;c++)
  280. newbm->Pixel(x,y,c)=Pixel(x*2,y*2,c);
  281. }
  282. return newbm;
  283. }
  284. Vector FloatBitMap_t::AverageColor(void)
  285. {
  286. Vector ret(0,0,0);
  287. for(int y=0;y<Height;y++)
  288. for(int x=0;x<Width;x++)
  289. for(int c=0;c<3;c++)
  290. ret[c]+=Pixel(x,y,c);
  291. ret*=1.0/(Width*Height);
  292. return ret;
  293. }
  294. float FloatBitMap_t::BrightestColor(void)
  295. {
  296. float ret=0.0;
  297. for(int y=0;y<Height;y++)
  298. for(int x=0;x<Width;x++)
  299. {
  300. Vector v(Pixel(x,y,0),Pixel(x,y,1),Pixel(x,y,2));
  301. ret=max(ret,v.Length());
  302. }
  303. return ret;
  304. }
  305. template <class T> static inline void SWAP(T & a, T & b)
  306. {
  307. T temp=a;
  308. a=b;
  309. b=temp;
  310. }
  311. void FloatBitMap_t::RaiseToPower(float power)
  312. {
  313. for(int y=0;y<Height;y++)
  314. for(int x=0;x<Width;x++)
  315. for(int c=0;c<3;c++)
  316. Pixel(x,y,c)=pow((float)MAX(0.0,Pixel(x,y,c)),(float)power);
  317. }
  318. void FloatBitMap_t::Logize(void)
  319. {
  320. for(int y=0;y<Height;y++)
  321. for(int x=0;x<Width;x++)
  322. for(int c=0;c<3;c++)
  323. Pixel(x,y,c)=log(1.0+Pixel(x,y,c));
  324. }
  325. void FloatBitMap_t::UnLogize(void)
  326. {
  327. for(int y=0;y<Height;y++)
  328. for(int x=0;x<Width;x++)
  329. for(int c=0;c<3;c++)
  330. Pixel(x,y,c)=exp(Pixel(x,y,c))-1;
  331. }
  332. void FloatBitMap_t::Clear(float r, float g, float b, float alpha)
  333. {
  334. for(int y=0;y<Height;y++)
  335. for(int x=0;x<Width;x++)
  336. {
  337. Pixel(x,y,0)=r;
  338. Pixel(x,y,1)=g;
  339. Pixel(x,y,2)=b;
  340. Pixel(x,y,3)=alpha;
  341. }
  342. }
  343. void FloatBitMap_t::ScaleRGB(float scale_factor)
  344. {
  345. for(int y=0;y<Height;y++)
  346. for(int x=0;x<Width;x++)
  347. for(int c=0;c<3;c++)
  348. Pixel(x,y,c)*=scale_factor;
  349. }
  350. static int dx[4]={0,-1,1,0};
  351. static int dy[4]={-1,0,0,1};
  352. #define NDELTAS 4
  353. void FloatBitMap_t::SmartPaste(FloatBitMap_t const &b, int xofs, int yofs, uint32 Flags)
  354. {
  355. // now, need to make Difference map
  356. FloatBitMap_t DiffMap0(this);
  357. FloatBitMap_t DiffMap1(this);
  358. FloatBitMap_t DiffMap2(this);
  359. FloatBitMap_t DiffMap3(this);
  360. FloatBitMap_t *deltas[4]={&DiffMap0,&DiffMap1,&DiffMap2,&DiffMap3};
  361. for(int x=0;x<Width;x++)
  362. for(int y=0;y<Height;y++)
  363. for(int c=0;c<3;c++)
  364. {
  365. for(int i=0;i<NDELTAS;i++)
  366. {
  367. int x1=x+dx[i];
  368. int y1=y+dy[i];
  369. x1=MAX(0,x1);
  370. x1=MIN(Width-1,x1);
  371. y1=MAX(0,y1);
  372. y1=MIN(Height-1,y1);
  373. float dx1=Pixel(x,y,c)-Pixel(x1,y1,c);
  374. deltas[i]->Pixel(x,y,c)=dx1;
  375. }
  376. }
  377. for(int x=1;x<b.Width-1;x++)
  378. for(int y=1;y<b.Height-1;y++)
  379. for(int c=0;c<3;c++)
  380. {
  381. for(int i=0;i<NDELTAS;i++)
  382. {
  383. float diff=b.Pixel(x,y,c)-b.Pixel(x+dx[i],y+dy[i],c);
  384. deltas[i]->Pixel(x+xofs,y+yofs,c)=diff;
  385. if (Flags & SPFLAGS_MAXGRADIENT)
  386. {
  387. float dx1=Pixel(x+xofs,y+yofs,c)-Pixel(x+dx[i]+xofs,y+dy[i]+yofs,c);
  388. if (fabs(dx1)>fabs(diff))
  389. deltas[i]->Pixel(x+xofs,y+yofs,c)=dx1;
  390. }
  391. }
  392. }
  393. // now, calculate modifiability
  394. for(int x=0;x<Width;x++)
  395. for(int y=0;y<Height;y++)
  396. {
  397. float modify=0;
  398. if (
  399. (x>xofs+1) && (x<=xofs+b.Width-2) &&
  400. (y>yofs+1) && (y<=yofs+b.Height-2))
  401. modify=1;
  402. Alpha(x,y)=modify;
  403. }
  404. // // now, force a fex pixels in center to be constant
  405. // int midx=xofs+b.Width/2;
  406. // int midy=yofs+b.Height/2;
  407. // for(x=midx-10;x<midx+10;x++)
  408. // for(int y=midy-10;y<midy+10;y++)
  409. // {
  410. // Alpha(x,y)=0;
  411. // for(int c=0;c<3;c++)
  412. // Pixel(x,y,c)=b.Pixel(x-xofs,y-yofs,c);
  413. // }
  414. Poisson(deltas,6000,Flags);
  415. }
  416. void FloatBitMap_t::ScaleGradients(void)
  417. {
  418. // now, need to make Difference map
  419. FloatBitMap_t DiffMap0(this);
  420. FloatBitMap_t DiffMap1(this);
  421. FloatBitMap_t DiffMap2(this);
  422. FloatBitMap_t DiffMap3(this);
  423. FloatBitMap_t *deltas[4]={&DiffMap0,&DiffMap1,&DiffMap2,&DiffMap3};
  424. double gsum=0.0;
  425. for(int x=0;x<Width;x++)
  426. for(int y=0;y<Height;y++)
  427. for(int c=0;c<3;c++)
  428. {
  429. for(int i=0;i<NDELTAS;i++)
  430. {
  431. int x1=x+dx[i];
  432. int y1=y+dy[i];
  433. x1=MAX(0,x1);
  434. x1=MIN(Width-1,x1);
  435. y1=MAX(0,y1);
  436. y1=MIN(Height-1,y1);
  437. float dx1=Pixel(x,y,c)-Pixel(x1,y1,c);
  438. deltas[i]->Pixel(x,y,c)=dx1;
  439. gsum+=fabs(dx1);
  440. }
  441. }
  442. // now, reduce gradient changes
  443. // float gavg=gsum/(Width*Height);
  444. for(int x=0;x<Width;x++)
  445. for(int y=0;y<Height;y++)
  446. for(int c=0;c<3;c++)
  447. {
  448. for(int i=0;i<NDELTAS;i++)
  449. {
  450. float norml=1.1*deltas[i]->Pixel(x,y,c);
  451. // if (norml<0.0)
  452. // norml=-pow(-norml,1.2);
  453. // else
  454. // norml=pow(norml,1.2);
  455. deltas[i]->Pixel(x,y,c)=norml;
  456. }
  457. }
  458. // now, calculate modifiability
  459. for(int x=0;x<Width;x++)
  460. for(int y=0;y<Height;y++)
  461. {
  462. float modify=0;
  463. if (
  464. (x>0) && (x<Width-1) &&
  465. (y) && (y<Height-1))
  466. {
  467. modify=1;
  468. Alpha(x,y)=modify;
  469. }
  470. }
  471. Poisson(deltas,2200,0);
  472. }
  473. void FloatBitMap_t::MakeTileable(void)
  474. {
  475. FloatBitMap_t rslta(this);
  476. // now, need to make Difference map
  477. FloatBitMap_t DiffMapX(this);
  478. FloatBitMap_t DiffMapY(this);
  479. // set each pixel=avg-pixel
  480. FloatBitMap_t *cursrc=&rslta;
  481. for(int x=1;x<Width-1;x++)
  482. for(int y=1;y<Height-1;y++)
  483. for(int c=0;c<3;c++)
  484. {
  485. DiffMapX.Pixel(x,y,c)=Pixel(x,y,c)-Pixel(x+1,y,c);
  486. DiffMapY.Pixel(x,y,c)=Pixel(x,y,c)-Pixel(x,y+1,c);
  487. }
  488. // initialize edge conditions
  489. for(int x=0;x<Width;x++)
  490. {
  491. for(int c=0;c<3;c++)
  492. {
  493. float a=0.5*(Pixel(x,Height-1,c)+=Pixel(x,0,c));
  494. rslta.Pixel(x,Height-1,c)=a;
  495. rslta.Pixel(x,0,c)=a;
  496. }
  497. }
  498. for(int y=0;y<Height;y++)
  499. {
  500. for(int c=0;c<3;c++)
  501. {
  502. float a=0.5*(Pixel(Width-1,y,c)+Pixel(0,y,c));
  503. rslta.Pixel(Width-1,y,c)=a;
  504. rslta.Pixel(0,y,c)=a;
  505. }
  506. }
  507. FloatBitMap_t rsltb(&rslta);
  508. FloatBitMap_t *curdst=&rsltb;
  509. // now, ready to iterate
  510. for(int pass=0;pass<10;pass++)
  511. {
  512. float error=0.0;
  513. for(int x=1;x<Width-1;x++)
  514. for(int y=1;y<Height-1;y++)
  515. for(int c=0;c<3;c++)
  516. {
  517. float desiredx=DiffMapX.Pixel(x,y,c)+cursrc->Pixel(x+1,y,c);
  518. float desiredy=DiffMapY.Pixel(x,y,c)+cursrc->Pixel(x,y+1,c);
  519. float desired=0.5*(desiredy+desiredx);
  520. curdst->Pixel(x,y,c)=FLerp(cursrc->Pixel(x,y,c),desired,0.5);
  521. error+=SQ(desired-cursrc->Pixel(x,y,c));
  522. }
  523. SWAP(cursrc,curdst);
  524. }
  525. // paste result
  526. for(int x=0;x<Width;x++)
  527. for(int y=0;y<Height;y++)
  528. for(int c=0;c<3;c++)
  529. Pixel(x,y,c)=curdst->Pixel(x,y,c);
  530. }
  531. void FloatBitMap_t::GetAlphaBounds(int &minx, int &miny, int &maxx,int &maxy)
  532. {
  533. for(minx=0;minx<Width;minx++)
  534. {
  535. int y;
  536. for(y=0;y<Height;y++)
  537. if (Alpha(minx,y))
  538. break;
  539. if (y!=Height)
  540. break;
  541. }
  542. for(maxx=Width-1;maxx>=0;maxx--)
  543. {
  544. int y;
  545. for(y=0;y<Height;y++)
  546. if (Alpha(maxx,y))
  547. break;
  548. if (y!=Height)
  549. break;
  550. }
  551. for(miny=0;minx<Height;miny++)
  552. {
  553. int x;
  554. for(x=minx;x<=maxx;x++)
  555. if (Alpha(x,miny))
  556. break;
  557. if (x<maxx)
  558. break;
  559. }
  560. for(maxy=Height-1;maxy>=0;maxy--)
  561. {
  562. int x;
  563. for(x=minx;x<=maxx;x++)
  564. if (Alpha(x,maxy))
  565. break;
  566. if (x<maxx)
  567. break;
  568. }
  569. }
  570. void FloatBitMap_t::Poisson(FloatBitMap_t *deltas[4],
  571. int n_iters,
  572. uint32 flags // SPF_xxx
  573. )
  574. {
  575. int minx,miny,maxx,maxy;
  576. GetAlphaBounds(minx,miny,maxx,maxy);
  577. minx=MAX(1,minx);
  578. miny=MAX(1,miny);
  579. maxx=MIN(Width-2,maxx);
  580. maxy=MIN(Height-2,maxy);
  581. if (((maxx-minx)>25) && (maxy-miny)>25)
  582. {
  583. // perform at low resolution
  584. FloatBitMap_t *lowdeltas[NDELTAS];
  585. for(int i=0;i<NDELTAS;i++)
  586. lowdeltas[i]=deltas[i]->QuarterSize();
  587. FloatBitMap_t *tmp=QuarterSize();
  588. tmp->Poisson(lowdeltas,n_iters*4,flags);
  589. // now, propagate results from tmp to us
  590. for(int x=0;x<tmp->Width;x++)
  591. for(int y=0;y<tmp->Height;y++)
  592. for(int xi=0;xi<2;xi++)
  593. for(int yi=0;yi<2;yi++)
  594. if (Alpha(x*2+xi,y*2+yi))
  595. {
  596. for(int c=0;c<3;c++)
  597. Pixel(x*2+xi,y*2+yi,c)=
  598. FLerp(Pixel(x*2+xi,y*2+yi,c),tmp->Pixel(x,y,c),Alpha(x*2+xi,y*2+yi));
  599. }
  600. char fname[80];
  601. sprintf(fname,"sub%dx%d.tga",tmp->Width,tmp->Height);
  602. tmp->WriteTGAFile(fname);
  603. sprintf(fname,"submrg%dx%d.tga",tmp->Width,tmp->Height);
  604. WriteTGAFile(fname);
  605. delete tmp;
  606. for(int i=0;i<NDELTAS;i++)
  607. delete lowdeltas[i];
  608. }
  609. FloatBitMap_t work1(this);
  610. FloatBitMap_t work2(this);
  611. FloatBitMap_t *curdst=&work1;
  612. FloatBitMap_t *cursrc=&work2;
  613. // now, ready to iterate
  614. while(n_iters--)
  615. {
  616. float error=0.0;
  617. for(int x=minx;x<=maxx;x++)
  618. {
  619. for(int y=miny;y<=maxy;y++)
  620. {
  621. if (Alpha(x,y))
  622. {
  623. for(int c=0;c<3;c++)
  624. {
  625. float desired=0.0;
  626. for(int i=0;i<NDELTAS;i++)
  627. desired+=deltas[i]->Pixel(x,y,c)+cursrc->Pixel(x+dx[i],y+dy[i],c);
  628. desired*=(1.0/NDELTAS);
  629. // desired=FLerp(Pixel(x,y,c),desired,Alpha(x,y));
  630. curdst->Pixel(x,y,c)=FLerp(cursrc->Pixel(x,y,c),desired,0.5);
  631. error+=SQ(desired-cursrc->Pixel(x,y,c));
  632. }
  633. }
  634. SWAP(cursrc,curdst);
  635. }
  636. }
  637. }
  638. // paste result
  639. for(int x=0;x<Width;x++)
  640. {
  641. for(int y=0;y<Height;y++)
  642. {
  643. for(int c=0;c<3;c++)
  644. {
  645. Pixel(x,y,c)=curdst->Pixel(x,y,c);
  646. }
  647. }
  648. }
  649. }