ImgEffects.cpp 76 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856
  1. #include "ImgEffects.h"
  2. #include "ImageData.h"
  3. #include <math.h>
  4. #include "util/CatmullRom.h"
  5. #include "util/Vector.h"
  6. #include <fstream>
  7. #include "PSDReader.h"
  8. #include "ImageUtils.h"
  9. #include "ImageAdjustments.h"
  10. #include "util/PerfTimer.h"
  11. USING_NS_BF;
  12. static inline float BFRound(float val)
  13. {
  14. if (val < 0)
  15. return (float) (int) (val - 0.5f);
  16. else
  17. return (float) (int) (val + 0.5f);
  18. }
  19. static uint16* CreateContourDataTable(ImageCurve* contour, float range = 1.0f)
  20. {
  21. uint16* contourData = new uint16[CONTOUR_DATA_SIZE];
  22. for (int i = 0; i < CONTOUR_DATA_SIZE; i++)
  23. {
  24. float aX = i / (float) (CONTOUR_DATA_SIZE - 1);
  25. float tableX = std::min(1.0f, aX / range);
  26. float yVal = contour->GetVal(tableX * 255.0f) / 255.0f;
  27. contourData[i] = BFClamp((int) (yVal * (GRADIENT_DATA_SIZE - 1) + 0.5f), 0, GRADIENT_DATA_SIZE - 1);
  28. }
  29. return contourData;
  30. }
  31. static uint32* CreateGradientDataTable(ImageGradient* colorGradient)
  32. {
  33. uint32* gradientData = new uint32[GRADIENT_DATA_SIZE];
  34. for (int i = 0; i < GRADIENT_DATA_SIZE; i++)
  35. {
  36. float yVal = i / (float) (GRADIENT_DATA_SIZE - 1);
  37. uint32 color = 0;
  38. for (int colorIdx = 0; colorIdx < 4; colorIdx++)
  39. {
  40. float gradientPos = 1.0f - yVal;
  41. if ((colorIdx == 3) && (colorGradient[colorIdx].mPoints.size() > 2))
  42. {
  43. // Strange effect where alpha gradient never fully reaches end when there's more than one stop
  44. gradientPos = std::min(gradientPos, 0.95f);
  45. }
  46. color |= (colorGradient[colorIdx].GetVal(gradientPos * colorGradient[colorIdx].mXSize)) << (colorIdx * 8);
  47. }
  48. gradientData[i] = color;
  49. }
  50. return gradientData;
  51. }
  52. ImageCurvePoint::ImageCurvePoint()
  53. {
  54. mSpline = NULL;
  55. mIsSplineOwner = false;
  56. }
  57. ImageCurvePoint::~ImageCurvePoint()
  58. {
  59. if (mIsSplineOwner)
  60. mSpline = NULL;
  61. }
  62. void ImageCurve::Init()
  63. {
  64. CubicFuncSpline* curSpline = NULL;
  65. for (int i = 0; i < (int) mPoints.size(); i++)
  66. {
  67. ImageCurvePoint* pt = &mPoints[i];
  68. if (pt->mIsCorner)
  69. {
  70. if (curSpline != NULL)
  71. {
  72. curSpline->AddPt(pt->mX, pt->mY);
  73. curSpline = NULL;
  74. }
  75. }
  76. else
  77. {
  78. if (curSpline == NULL)
  79. {
  80. curSpline = new CubicFuncSpline();
  81. pt->mIsSplineOwner = true;
  82. }
  83. pt->mSpline = curSpline;
  84. curSpline->AddPt(pt->mX, pt->mY);
  85. }
  86. }
  87. /*{
  88. std::fstream stream("c:\\temp\\curve.csv", std::ios::out);
  89. for (int i = 0; i < (int) 255; i++)
  90. {
  91. float aVal = GetVal(i);
  92. stream << aVal << std::endl;
  93. }
  94. BF_ASSERT(stream.is_open());
  95. stream.flush();
  96. }
  97. _asm nop;*/
  98. }
  99. float ImageCurve::GetVal(float x)
  100. {
  101. ImageCurvePoint* prevPt = NULL;
  102. for (int i = 0; i < (int) mPoints.size(); i++)
  103. {
  104. ImageCurvePoint* nextPt = &mPoints[i];
  105. if (x == nextPt->mX)
  106. return nextPt->mY;
  107. if ((x <= nextPt->mX) && (prevPt != NULL))
  108. {
  109. if (prevPt->mSpline != NULL)
  110. return prevPt->mSpline->Evaluate(x);
  111. //return BFClamp(prevPt->mSpline->Evaluate(x), 0.0f, 255.0f);
  112. return prevPt->mY +
  113. ((x - prevPt->mX) / (nextPt->mX - prevPt->mX)) * (nextPt->mY - prevPt->mY);
  114. }
  115. prevPt = nextPt;
  116. }
  117. return mPoints.back().mY;
  118. }
  119. bool ImageCurve::IsDefault()
  120. {
  121. return (mPoints.size() == 2) && (mPoints[0].mX == 0) && (mPoints[0].mY == 0) && (mPoints[1].mX == 255.0f) && (mPoints[1].mY == 255.0f);
  122. }
  123. static uint32 LerpColor(uint32 color1, uint32 color2, float pct)
  124. {
  125. if (color1 == color2)
  126. return color1;
  127. uint32 a = (uint32)(pct * 256.0f);
  128. uint32 oma = 256 - a;
  129. uint32 color =
  130. (((((color1 & 0x000000FF) * oma) + ((color2 & 0x000000FF) * a)) >> 8) & 0x000000FF) |
  131. (((((color1 & 0x0000FF00) * oma) + ((color2 & 0x0000FF00) * a)) >> 8) & 0x0000FF00) |
  132. (((((color1 & 0x00FF0000) * oma) + ((color2 & 0x00FF0000) * a)) >> 8) & 0x00FF0000) |
  133. (((((color1 >> 24) & 0xFF) * oma) + (((color2 >> 24) & 0xFF) * a) & 0x0000FF00) << 16);
  134. return color;
  135. }
  136. int ImageGradient::GetVal(float x)
  137. {
  138. if (mSpline.mInputPoints.size() == 0)
  139. {
  140. int n = (int)mPoints.size() - 1;
  141. mSpline.AddPt((float) mPoints[0].mValue);
  142. for (int i = 0; i < (int) mPoints.size(); i++)
  143. mSpline.AddPt((float) mPoints[i].mValue);
  144. mSpline.AddPt((float) mPoints[n].mValue);
  145. /*{
  146. std::fstream stream("c:\\temp\\curve.csv", std::ios::out);
  147. for (int i = 0; i < (int) 256; i++)
  148. {
  149. int aVal = GetVal((float) i * 4096 / 256);
  150. stream << aVal << std::endl;
  151. }
  152. BF_ASSERT(stream.is_open());
  153. stream.flush();
  154. }
  155. _asm nop;*/
  156. }
  157. for (int i = 0; i < (int) mPoints.size(); i++)
  158. {
  159. if (x < mPoints[i].mX)
  160. {
  161. if (i == 0)
  162. return mPoints[i].mValue;
  163. float prevVal = (float) mPoints[i - 1].mValue;
  164. float nextVal = (float) mPoints[i].mValue;
  165. float aPct = (x - mPoints[i - 1].mX) / (mPoints[i].mX - mPoints[i - 1].mX);
  166. float linearVal = (prevVal * (1.0f - aPct)) + (nextVal * aPct);
  167. if ((mSmoothness == 0) || (mPoints.size() <= 2))
  168. return (int) (linearVal + 0.5f);
  169. float curveVal = mSpline.Evaluate(i + aPct);
  170. float result = (curveVal * mSmoothness) + (linearVal * (1.0f - mSmoothness));
  171. if (prevVal < nextVal)
  172. result = BFClamp(result, prevVal, nextVal);
  173. else
  174. result = BFClamp(result, nextVal, prevVal);
  175. return (int) (result + 0.5f);
  176. }
  177. }
  178. return mPoints.back().mValue;
  179. }
  180. ImageEffects::ImageEffects()
  181. {
  182. mSwapImages[0] = NULL;
  183. mSwapImages[1] = NULL;
  184. }
  185. ImageEffects::~ImageEffects()
  186. {
  187. for (int i = 0; i < (int) mImageEffectVector.size(); i++)
  188. delete mImageEffectVector[i];
  189. }
  190. ImageData* ImageEffects::GetDestImage(ImageData* usingImage)
  191. {
  192. if ((mSwapImages[0] != usingImage) && (mSwapImages[0] != NULL))
  193. return mSwapImages[0];
  194. if ((mSwapImages[1] != usingImage) && (mSwapImages[1] != NULL))
  195. return mSwapImages[1];
  196. ImageData* anImage = new ImageData();
  197. anImage->mStride = usingImage->mStride;
  198. anImage->mWidth = usingImage->mWidth;
  199. anImage->mHeight = usingImage->mHeight;
  200. anImage->mBits = new uint32[anImage->mWidth*anImage->mHeight];
  201. if (mSwapImages[0] == NULL)
  202. mSwapImages[0] = anImage;
  203. else
  204. mSwapImages[1] = anImage;
  205. return anImage;
  206. }
  207. #define BOXBLUR_IN(x) (((x < 0) || (x >= width)) ? edgeValue : in[inIndex + x])
  208. static void BoxBlur(uint32* in, uint32* out, int width, int height, float radius, uint32 edgeValue)
  209. {
  210. AutoPerf gPerf("ImgEffects - BoxBlur");
  211. int widthMinus1 = width-1;
  212. int r = (int)radius;
  213. int tableSize = 2*r+1;
  214. float frac = radius - r;
  215. int a = (int) (frac * 256);
  216. int oma = 256 - a;
  217. int div = (2*r+1)*256 + a*2;
  218. int inIndex = 0;
  219. if (radius > 1)
  220. {
  221. for ( int y = 0; y < height; y++ )
  222. {
  223. int outIndex = y;
  224. uint32 ta = 0;
  225. for ( int i = -r; i <= r; i++ )
  226. {
  227. int rgb = BOXBLUR_IN(i);
  228. ta += rgb * 256;
  229. }
  230. ta += a * BOXBLUR_IN(-r-1);
  231. ta += a * BOXBLUR_IN(r+1);
  232. for ( int x = 0; x < width; x++ )
  233. {
  234. out[outIndex] = ta / div;
  235. uint32 r1Value = edgeValue;
  236. uint32 r2Value = edgeValue;
  237. int r1 = x+r+1;
  238. int r2 = r1+1;
  239. if (r2 < width)
  240. {
  241. r1Value = in[inIndex + r1];
  242. r2Value = in[inIndex + r2];
  243. }
  244. else if (r1 < width)
  245. {
  246. r1Value = in[inIndex + r1];
  247. }
  248. uint32 l1Value = edgeValue;
  249. uint32 l2Value = edgeValue;
  250. int l1 = x-r-1;
  251. int l2 = l1+1;
  252. if (l1 >= 0)
  253. {
  254. l1Value = in[inIndex + l1];
  255. l2Value = in[inIndex + l2];
  256. }
  257. else if (l2 >= 0)
  258. {
  259. l2Value = in[inIndex + l2];
  260. }
  261. int rgbL = (l1Value * a) + (l2Value * oma);
  262. int rgbR = (r1Value * oma) + (r2Value * a);
  263. ta += rgbR;
  264. ta -= rgbL;
  265. outIndex += height;
  266. }
  267. inIndex += width;
  268. }
  269. }
  270. else
  271. {
  272. for ( int y = 0; y < height; y++ )
  273. {
  274. int outIndex = y;
  275. for ( int x = 0; x < width; x++ )
  276. {
  277. int r = x+1;
  278. if (r > widthMinus1)
  279. r = widthMinus1;
  280. int l = x-1;
  281. if (l < 0)
  282. l = 0;
  283. int rgbL = in[inIndex+l] * a;
  284. int rgbR = in[inIndex+r] * a;
  285. int rgbM = in[inIndex+x] * 256;
  286. out[outIndex] = (rgbL + rgbM + rgbR) / div;
  287. outIndex += height;
  288. }
  289. inIndex += width;
  290. }
  291. }
  292. }
  293. float GetSoftBlurRadius(float origRadius, float radiusLeft)
  294. {
  295. //float radiusOffset = 1.90f - 0.7f * std::min(1.0f, origRadius / 10);
  296. //return radiusLeft - radiusOffset;
  297. if (radiusLeft == 0)
  298. return 0;
  299. float radiusOffset = 1.2f;
  300. float blurRadius = radiusLeft - radiusOffset;
  301. if (radiusLeft <= 2)
  302. blurRadius = 0.5f;
  303. return blurRadius;
  304. }
  305. float GetSoftBlurRadius(float origRadius)
  306. {
  307. return GetSoftBlurRadius(origRadius, origRadius);
  308. }
  309. void SoftBlurInit(ImageData* inImage, ImageData* outImage, bool invert)
  310. {
  311. uint32* in = inImage->mBits;
  312. uint32* out = outImage->mBits;
  313. int iw = inImage->mWidth;
  314. int ih = inImage->mHeight;
  315. int ow = outImage->mWidth;
  316. int oh = outImage->mHeight;
  317. int ox = inImage->mX - outImage->mX;
  318. int oy = inImage->mY - outImage->mY;
  319. if (!invert)
  320. {
  321. for (int y = 0; y < oh; y++)
  322. for (int x = 0; x < ow; x++)
  323. out[x+y*ow] = 0;
  324. for (int y = 0; y < ih; y++)
  325. {
  326. for (int x = 0; x < iw; x++)
  327. {
  328. int anAlpha = in[x+y*iw]>>24;
  329. out[(x+ox)+(y+oy)*ow] = anAlpha * 256;
  330. }
  331. }
  332. }
  333. else
  334. {
  335. for (int y = 0; y < oh; y++)
  336. for (int x = 0; x < ow; x++)
  337. out[x+y*ow] = 255*256;
  338. for (int y = 0; y < ih; y++)
  339. {
  340. for (int x = 0; x < iw; x++)
  341. {
  342. int anAlpha = in[x+y*iw]>>24;
  343. out[(x+ox)+(y+oy)*ow] = (255 - (anAlpha)) * 256;
  344. }
  345. }
  346. }
  347. }
  348. void SoftBlur(uint32* data, int w, int h, float radius, uint32 defaultValue)
  349. {
  350. uint32* tempBuffer = new uint32[w*h];
  351. int expandedX = 0;
  352. int expandedY = 0;
  353. int itrCount = (radius < 0.9f) ? 1 : 2;
  354. float d = radius / itrCount;
  355. if (d > 0)
  356. {
  357. for (int i = 0; i < itrCount; i++)
  358. {
  359. BoxBlur(data, tempBuffer, w, h, d, defaultValue);
  360. BoxBlur(tempBuffer, data, h, w, d, defaultValue);
  361. }
  362. }
  363. delete [] tempBuffer;
  364. }
  365. static int gAlphaCheckOfs [][2] =
  366. {{-1, -1}, {0, -1}, {1, -1},
  367. {-1, 0}, {1, 0},
  368. {-1, 1}, {0, 1}, {1, 1}};
  369. static int gAlphaScaleVals [] =
  370. {358, 254, 358,
  371. 254, 256,
  372. 358, 254, 358};
  373. static int gKernelOfsFwd[][2] =
  374. { {-1, -2}, {1, -2},
  375. {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1},
  376. {-1, 0}};
  377. static int gKernelValsFwd[] =
  378. {567, 567,
  379. 567, 358, 254, 358, 567,
  380. 254};
  381. static int gKernelOfsRev[][2] =
  382. {
  383. {1, 0},
  384. {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1},
  385. {-1, 2}, {1, 2}};
  386. static int gKernelValsRev[] =
  387. { 254,
  388. 567, 358, 254, 358, 567,
  389. 567, 567};
  390. static void ChamferedDistanceTransformInit(ImageData* inImage, ImageData* outImage, bool invert, int softSize = 0)
  391. {
  392. AutoPerf gPerf("ImgEffects - ChamferedDistanceTransformInit");
  393. uint32* in = inImage->mBits;
  394. uint32* out = outImage->mBits;
  395. int iw = inImage->mWidth;
  396. int ih = inImage->mHeight;
  397. int ow = outImage->mWidth;
  398. int oh = outImage->mHeight;
  399. int ox = inImage->mX - outImage->mX;
  400. int oy = inImage->mY - outImage->mY;
  401. int inf = (ow+oh)*564;
  402. int alphaCheckCount = sizeof(gAlphaScaleVals) / sizeof(int);
  403. if (!invert)
  404. {
  405. for (int y = 0; y < oh; y++)
  406. for (int x = 0; x < ow; x++)
  407. out[x+y*ow] = inf;
  408. for (int y = 0; y < ih; y++)
  409. {
  410. for (int x = 0; x < iw; x++)
  411. {
  412. int anAlpha = in[x+y*iw]>>24;
  413. if (anAlpha != 0)
  414. {
  415. int aVal = (255 - anAlpha);
  416. out[(x+ox)+(y+oy)*ow] = aVal + aVal / 32;
  417. }
  418. else
  419. out[(x+ox)+(y+oy)*ow] = inf;
  420. }
  421. }
  422. }
  423. else
  424. {
  425. for (int y = 0; y < oh; y++)
  426. for (int x = 0; x < ow; x++)
  427. out[x+y*ow] = 0;
  428. if (softSize != 0)
  429. {
  430. for (int y = 0; y < ih; y++)
  431. {
  432. for (int x = 0; x < iw; x++)
  433. {
  434. int anAlpha = in[x+y*iw]>>24;
  435. int aVal;
  436. if (anAlpha > 128)
  437. aVal = (anAlpha - 128) * (softSize + 1)*2;
  438. else
  439. aVal = 0;
  440. out[(x+ox)+(y+oy)*ow] = aVal;
  441. }
  442. }
  443. }
  444. else
  445. {
  446. for (int y = 0; y < ih; y++)
  447. {
  448. for (int x = 0; x < iw; x++)
  449. {
  450. int anAlpha = in[x+y*iw]>>24;
  451. if (anAlpha == 255)
  452. {
  453. out[(x+ox)+(y+oy)*ow] = inf;
  454. }
  455. else
  456. {
  457. out[(x+ox)+(y+oy)*ow] = anAlpha + anAlpha / 32;
  458. }
  459. }
  460. }
  461. }
  462. }
  463. }
  464. static void ChamferedDistanceTransformSlow(uint32* out, int width, int height, int startX, int startY, int endX, int endY)
  465. {
  466. AutoPerf gPerf("ImgEffects - ChamferedDistanceTransform");
  467. int kernelCountFwd = sizeof(gKernelValsFwd) / sizeof(int);
  468. int kernelCountRev = sizeof(gKernelValsRev) / sizeof(int);
  469. for (int y = startY; y < endY; y++)
  470. {
  471. for (int x = startX; x < endX; x++)
  472. {
  473. for (int kernIdx = 0; kernIdx < kernelCountFwd; kernIdx++)
  474. {
  475. int cx = BFClamp(x + gKernelOfsFwd[kernIdx][0], 0, width - 1);
  476. int cy = BFClamp(y + gKernelOfsFwd[kernIdx][1], 0, height - 1);
  477. int aVal = out[cx+cy*width] + gKernelValsFwd[kernIdx];
  478. if (aVal < (int) out[x+y*width])
  479. out[x+y*width] = aVal;
  480. }
  481. }
  482. }
  483. for (int y = endY - 1; y >= startY; y--)
  484. {
  485. for (int x = endX - 1; x >= startX; x--)
  486. {
  487. for (int kernIdx = 0; kernIdx < kernelCountRev; kernIdx++)
  488. {
  489. int cx = BFClamp(x + gKernelOfsRev[kernIdx][0], 0, width - 1);
  490. int cy = BFClamp(y + gKernelOfsRev[kernIdx][1], 0, height - 1);
  491. int aVal = out[cx+cy*width] + gKernelValsRev[kernIdx];
  492. if (aVal < (int) out[x+y*width])
  493. out[x+y*width] = aVal;
  494. }
  495. }
  496. }
  497. }
  498. static void ChamferedDistanceTransform(uint32* out, int width, int height)
  499. {
  500. AutoPerf gPerf("ImgEffects - ChamferedDistanceTransform");
  501. if ((width < 4) || (height < 4))
  502. {
  503. ChamferedDistanceTransformSlow(out, width, height, 0, 0, width, height);
  504. return;
  505. }
  506. // Do 2 pixel border (where we have to clamp)
  507. ChamferedDistanceTransformSlow(out, width, height, 0, 0, width, 2);
  508. ChamferedDistanceTransformSlow(out, width, height, 0, height-2, width, 2);
  509. ChamferedDistanceTransformSlow(out, width, height, 0, 2, 2, height - 2);
  510. ChamferedDistanceTransformSlow(out, width, height, width - 2, 2, 2, height - 2);
  511. // Do inner region (no clamping)
  512. int kernelCountFwd = sizeof(gKernelValsFwd) / sizeof(int);
  513. int kernelCountRev = sizeof(gKernelValsRev) / sizeof(int);
  514. int aStartX = 2;
  515. int aStartY = 2;
  516. int aEndX = width - 2;
  517. int aEndY = height - 2;
  518. for (int y = aStartY; y < aEndY; y++)
  519. {
  520. for (int x = aStartX; x < aEndX; x++)
  521. {
  522. for (int kernIdx = 0; kernIdx < kernelCountFwd; kernIdx++)
  523. {
  524. int cx = x + gKernelOfsFwd[kernIdx][0];
  525. int cy = y + gKernelOfsFwd[kernIdx][1];
  526. int aVal = out[cx+cy*width] + gKernelValsFwd[kernIdx];
  527. if (aVal < (int) out[x+y*width])
  528. out[x+y*width] = aVal;
  529. }
  530. }
  531. }
  532. for (int y = aEndY - 1; y >= aStartY; y--)
  533. {
  534. for (int x = aEndX - 1; x >= aStartX; x--)
  535. {
  536. for (int kernIdx = 0; kernIdx < kernelCountRev; kernIdx++)
  537. {
  538. int cx = x + gKernelOfsRev[kernIdx][0];
  539. int cy = y + gKernelOfsRev[kernIdx][1];
  540. int aVal = out[cx+cy*width] + gKernelValsRev[kernIdx];
  541. if (aVal < (int) out[x+y*width])
  542. out[x+y*width] = aVal;
  543. }
  544. }
  545. }
  546. }
  547. #define IN_PIXEL(xval,yval) in[(xval) + (yval)*width]
  548. #define IN_PIXEL_YX(yval,xval) in[(xval) + (yval)*width]
  549. static void CreateNormalMap(uint32* in, uint32* out, int width, int height, float depth, Vector3* dotVector)
  550. {
  551. AutoPerf gPerf("ImgEffects - CreateNormalMap");
  552. for (int y = 0; y < height; y++)
  553. {
  554. for (int x = 0; x < width; x++)
  555. {
  556. // surrounding pixels
  557. const uint32 topLeft = IN_PIXEL_YX(std::max(y - 1, 0), std::max(x - 1, 0));
  558. const uint32 top = IN_PIXEL_YX(std::max(y - 1, 0), x);
  559. const uint32 topRight = IN_PIXEL_YX(std::max(y - 1, 0), std::min(x + 1, width - 1));
  560. const uint32 right = IN_PIXEL_YX(y, std::min(x + 1, width - 1));
  561. const uint32 bottomRight = IN_PIXEL_YX(std::min(y + 1, height - 1), std::min(x + 1, width - 1));
  562. const uint32 bottom = IN_PIXEL_YX(std::min(y + 1, height - 1), x);
  563. const uint32 bottomLeft = IN_PIXEL_YX(std::min(y + 1, height - 1), std::max(x - 1, 0));
  564. const uint32 left = IN_PIXEL_YX(y, std::max(x - 1, 0));
  565. // their intensities
  566. const float tl = (float)(topLeft);
  567. const float t = (float)(top);
  568. const float tr = (float)(topRight);
  569. const float r = (float)(right);
  570. const float br = (float)(bottomRight);
  571. const float b = (float)(bottom);
  572. const float bl = (float)(bottomLeft);
  573. const float l = (float) (left);
  574. // sobel filter
  575. float dX = (tr + 2.0f * r + br) - (tl + 2.0f * l + bl);
  576. float dY = (bl + 2.0f * b + br) - (tl + 2.0f * t + tr);
  577. float dZ = depth * 10 * 0x100;
  578. float len = sqrt(dX*dX + dY*dY + dZ*dZ);
  579. dX /= len;
  580. dY /= len;
  581. dZ /= len;
  582. if (dotVector != NULL)
  583. {
  584. Vector3 aNorm(dX, dY, dZ);
  585. float dot = Vector3::Dot(*dotVector, aNorm);
  586. out[x+y*width] = (uint32) (0xFF00 * dot) + 0x100000;
  587. }
  588. else
  589. {
  590. out[x+y*width] =
  591. ((int) (dX * 0x7F + 0x80 + 0.5f)) |
  592. ((int) (dY * 0x7F + 0x80 + 0.5f) << 8) |
  593. ((int) (dZ * 0xFF) << 16) |
  594. 0xFF000000;
  595. }
  596. }
  597. }
  598. }
  599. static void AntiAliasIndices(uint32* in, int width, int height)
  600. {
  601. int w = width;
  602. int h = height;
  603. for (int y = 0; y < h - 1; y++)
  604. {
  605. for (int x = 0; x < w - 1; x++)
  606. {
  607. int val1 = in[x+y*w];
  608. int val2 = in[(x+1)+y*w];
  609. int val3 = in[x+(y+1)*w];
  610. int val4 = in[(x+1)+(y+1)*w];
  611. in[x+y*w] = ((val1 * 114) + (val2 * 57) + (val3 * 57) + (val4 * 28)) / 256;
  612. }
  613. }
  614. }
  615. static inline void BlendColors(PackedColor* destColor, PackedColor* underColor, PackedColor* overColor)
  616. {
  617. int a = 255 - overColor->a;
  618. int oma = 255 - a;
  619. destColor->r = ((underColor->r * a) + (overColor->r * oma)) / 255;
  620. destColor->g = ((underColor->g * a) + (overColor->g * oma)) / 255;
  621. destColor->b = ((underColor->b * a) + (overColor->b * oma)) / 255;
  622. }
  623. template <class CompareFunctor>
  624. void ApplyBlendingRange(ImageData* origImage, ImageData* destImage, ImageData* checkImage, int rangeStart, int rangeEnd, CompareFunctor functor)
  625. {
  626. if ((rangeStart == 0) && (rangeEnd == 0xFF))
  627. return;
  628. int aStartX = std::max(checkImage->mX, origImage->mX);
  629. int aStartY = std::max(checkImage->mY, origImage->mY);
  630. int aEndX = std::min(checkImage->mX + checkImage->mWidth, origImage->mX + origImage->mWidth);
  631. int aEndY = std::min(checkImage->mY + checkImage->mHeight, origImage->mY + origImage->mHeight);
  632. if (rangeStart <= rangeEnd)
  633. {
  634. for (int y = aStartY; y < aEndY; y++)
  635. {
  636. PackedColor* aDestColor = (PackedColor*) (destImage->mBits + (aStartX - destImage->mX) + ((y - destImage->mY) * destImage->mWidth));
  637. PackedColor* origColor = (PackedColor*) (origImage->mBits + (aStartX - origImage->mX) + ((y - origImage->mY) * origImage->mWidth));
  638. PackedColor* checkColor = (PackedColor*) (checkImage->mBits + (aStartX - checkImage->mX) + ((y - checkImage->mY) * checkImage->mWidth));
  639. for (int x = aStartX; x < aEndX; x++)
  640. {
  641. if ((functor(*checkColor) < rangeStart) || (functor(*checkColor) > rangeEnd))
  642. *aDestColor = *origColor;
  643. aDestColor++;
  644. origColor++;
  645. checkColor++;
  646. }
  647. }
  648. }
  649. else // Inverted range
  650. {
  651. for (int y = aStartY; y < aEndY; y++)
  652. {
  653. PackedColor* aDestColor = (PackedColor*) (destImage->mBits + (aStartX - destImage->mX) + ((y - destImage->mY) * destImage->mWidth));
  654. PackedColor* origColor = (PackedColor*) (origImage->mBits + (aStartX - origImage->mX) + ((y - origImage->mY) * origImage->mWidth));
  655. PackedColor* checkColor = (PackedColor*) (checkImage->mBits + (aStartX - checkImage->mX) + ((y - checkImage->mY) * checkImage->mWidth));
  656. for (int x = aStartX; x < aEndX; x++)
  657. {
  658. if ((functor(*checkColor) < rangeStart) && (functor(*checkColor) > rangeEnd))
  659. *aDestColor = *origColor;
  660. aDestColor++;
  661. origColor++;
  662. checkColor++;
  663. }
  664. }
  665. }
  666. }
  667. ImageData* ImageEffects::FlattenInto(ImageData* dest, PSDLayerInfo* srcLayer, ImageData* srcImage, ImageData* knockoutBottom, ImageData* insideImage)
  668. {
  669. AutoPerf gPerf("ImageEffects::FlattenInto");
  670. bool hasComplexBlending = srcLayer->mBlendMode != 'norm';
  671. BF_ASSERT((dest == NULL) || (!dest->mAlphaPremultiplied));
  672. BF_ASSERT(!srcLayer->mAlphaPremultiplied);
  673. ImageData* aSrcImage = srcImage;
  674. if (srcLayer->mImageAdjustment != NULL)
  675. {
  676. if (((srcLayer->mLayerMask != NULL) && (srcLayer->mLayerMaskEnabled)) || (srcLayer->mVectorMask != NULL))
  677. {
  678. if (srcLayer->mWidth == 0)
  679. {
  680. aSrcImage = new ImageData();
  681. if (srcLayer->mLayerMaskDefault == 255)
  682. aSrcImage->CreateNew(0, 0, srcLayer->mPSDReader->mWidth, srcLayer->mPSDReader->mHeight, false);
  683. else
  684. aSrcImage->CreateNew(srcLayer->mLayerMaskX, srcLayer->mLayerMaskY, srcLayer->mLayerMaskWidth, srcLayer->mLayerMaskHeight, false);
  685. aSrcImage->Fill(0xFFFFFFFF);
  686. srcLayer->ApplyMask(aSrcImage);
  687. }
  688. }
  689. else
  690. {
  691. // No mask - just directly apply the effects
  692. ImageData* aDestImage = srcLayer->mImageAdjustment->CreateAdjustedImage(srcLayer, dest);
  693. ImageEffectCtx aCtx;
  694. aCtx.mOrigImage = NULL;
  695. aCtx.mBlendX = dest->mX;
  696. aCtx.mBlendY = dest->mY;
  697. aCtx.mBlendWidth = dest->mWidth;
  698. aCtx.mBlendHeight = dest->mHeight;
  699. aCtx.mInnerImage = NULL;
  700. aCtx.mOuterImage = NULL;
  701. aCtx.mLayerInfo = srcLayer;
  702. aCtx.mLayerImage = NULL;
  703. return aDestImage;
  704. }
  705. }
  706. int borderSize = 0;
  707. bool hasInnerEffect = false;
  708. bool hasOuterEffect = false;
  709. bool needsOrigBits = false;
  710. for (int i = 0; i < (int) mImageEffectVector.size(); i++)
  711. {
  712. BaseImageEffect* anEffect = mImageEffectVector[i];
  713. borderSize = std::max(borderSize, anEffect->GetNeededBorderSize());
  714. int mixType = anEffect->GetMixType();
  715. hasInnerEffect |= (mixType == IMAGEMIX_INNER) || (mixType == IMAGEMIX_OVER);
  716. hasOuterEffect |= (mixType == IMAGEMIX_OUTER) || (mixType == IMAGEMIX_OVER);
  717. needsOrigBits |= anEffect->NeedsOrigBits(this);
  718. hasComplexBlending |= anEffect->mBlendMode != 'Nrml';
  719. }
  720. bool hasBlendingRanges =
  721. (srcLayer->mBlendingRangeSourceStart != 0x00000000) ||
  722. (srcLayer->mBlendingRangeSourceEnd != 0xFFFFFFFF) ||
  723. (srcLayer->mBlendingRangeDestStart != 0x00000000) ||
  724. (srcLayer->mBlendingRangeDestEnd != 0xFFFFFFFF);
  725. bool doPostOpacity = hasComplexBlending || hasOuterEffect;
  726. uint8* aMask = NULL;
  727. //hasInnerEffect = true;
  728. if (insideImage != NULL)
  729. hasInnerEffect = true;
  730. hasInnerEffect = true;
  731. hasOuterEffect = true;
  732. needsOrigBits |= srcLayer->mLayerMaskHidesEffects;
  733. if (!srcLayer->mTransparencyShapesLayer)
  734. hasOuterEffect = false;
  735. int minDestX = aSrcImage->mX - borderSize;
  736. int maxDestX = aSrcImage->mX + aSrcImage->mWidth + borderSize;
  737. int minDestY = aSrcImage->mY - borderSize;
  738. int maxDestY = aSrcImage->mY + aSrcImage->mHeight + borderSize;
  739. if (dest != NULL)
  740. {
  741. minDestX = std::min(dest->mX, minDestX);
  742. maxDestX = std::max(dest->mX + dest->mWidth, maxDestX);
  743. minDestY = std::min(dest->mY, minDestY);
  744. maxDestY = std::max(dest->mY + dest->mHeight, maxDestY);
  745. }
  746. ImageEffectCtx aCtx;
  747. aCtx.mOrigImage = NULL;
  748. aCtx.mBlendX = minDestX;
  749. aCtx.mBlendY = minDestY;
  750. aCtx.mBlendWidth = maxDestX - minDestX;
  751. aCtx.mBlendHeight = maxDestY - minDestY;
  752. aCtx.mInnerImage = NULL;
  753. aCtx.mOuterImage = NULL;
  754. aCtx.mLayerInfo = srcLayer;
  755. aCtx.mLayerImage = aSrcImage;
  756. ImageData* aDestImage = NULL;
  757. int minCopyX = aSrcImage->mX - borderSize;
  758. int maxCopyX = aSrcImage->mX + aSrcImage->mWidth + borderSize;
  759. int minCopyY = aSrcImage->mY - borderSize;
  760. int maxCopyY = aSrcImage->mY + aSrcImage->mHeight + borderSize;
  761. // This gets set if we need the 'dest' initialized with bits
  762. bool needsDestInit = (!hasOuterEffect) || (!hasInnerEffect);
  763. for (int i = 0; i < 4; i++)
  764. {
  765. bool needed = ((i == 0) && (hasInnerEffect)) || ((i == 1) && (hasOuterEffect)) ||
  766. ((i == 2) && (needsOrigBits)) || ((i == 3) && (needsDestInit));
  767. if (!needed)
  768. continue;
  769. ImageData* effectImage = new ImageData();
  770. effectImage->mX = aCtx.mBlendX;
  771. effectImage->mY = aCtx.mBlendY;
  772. effectImage->CreateNew(aCtx.mBlendWidth, aCtx.mBlendHeight);
  773. if (dest != NULL)
  774. {
  775. int minX = dest->mX;
  776. int maxX = dest->mX + dest->mWidth;
  777. int minY = dest->mY;
  778. int maxY = dest->mY + dest->mHeight;
  779. if ((i == 0) && (insideImage != NULL))
  780. {
  781. CopyImageBits(effectImage, insideImage);
  782. }
  783. else if ((i == 0) && (srcLayer->mKnockout == 1))
  784. {
  785. // Shallow knockout
  786. if (knockoutBottom != NULL)
  787. {
  788. for (int y = knockoutBottom->mY; y < knockoutBottom->mY + knockoutBottom->mHeight; y++)
  789. {
  790. for (int x = knockoutBottom->mX; x < knockoutBottom->mX + knockoutBottom->mWidth; x++)
  791. {
  792. effectImage->mBits[(x - effectImage->mX) + (y - effectImage->mY)*effectImage->mWidth] =
  793. knockoutBottom->mBits[(x - knockoutBottom->mX) + (y - knockoutBottom->mY)*knockoutBottom->mWidth];
  794. }
  795. }
  796. }
  797. }
  798. else if ((i == 0) && (srcLayer->mKnockout == 2))
  799. {
  800. // Deep knockout - leave blank
  801. }
  802. else
  803. {
  804. for (int y = minY; y < maxY; y++)
  805. {
  806. for (int x = minX; x < maxX; x++)
  807. {
  808. effectImage->mBits[(x - effectImage->mX) + (y - effectImage->mY)*effectImage->mWidth] =
  809. dest->mBits[(x - dest->mX) + (y - dest->mY)*dest->mWidth];
  810. }
  811. }
  812. }
  813. }
  814. if (i == 0)
  815. aCtx.mInnerImage = effectImage;
  816. else if (i == 1)
  817. aCtx.mOuterImage = effectImage;
  818. else if (i == 2)
  819. aCtx.mOrigImage = effectImage;
  820. else
  821. aDestImage = effectImage;
  822. }
  823. if (aDestImage == NULL)
  824. {
  825. aDestImage = new ImageData();
  826. aDestImage->mX = aCtx.mBlendX;
  827. aDestImage->mY = aCtx.mBlendY;
  828. aDestImage->CreateNew(aCtx.mBlendWidth, aCtx.mBlendHeight);
  829. }
  830. if (aCtx.mInnerImage != NULL)
  831. {
  832. if (insideImage != NULL)
  833. {
  834. //BlendImage(aCtx.mInnerImage, aSrcImage, insideImage->mX - aCtx.mBlendX, insideImage->mY - aCtx.mBlendY, 1.0f, 'Nrml');
  835. }
  836. else if (srcLayer->mImageAdjustment != NULL)
  837. {
  838. srcLayer->mImageAdjustment->ApplyImageAdjustment(srcLayer, aCtx.mInnerImage);
  839. CrossfadeImage(dest, aCtx.mInnerImage, srcLayer->mFillOpacity / 255.0f);
  840. }
  841. else
  842. {
  843. int blendMode = srcLayer->mBlendMode;
  844. float anAlpha = srcLayer->mFillOpacity / 255.0f;
  845. if (srcLayer->mBlendInteriorEffectsAsGroup)
  846. anAlpha = 1.0f;
  847. if (!doPostOpacity)
  848. anAlpha *= (srcLayer->mOpacity / 255.0f);
  849. BlendImage(aCtx.mInnerImage, aSrcImage, aSrcImage->mX - aCtx.mBlendX, aSrcImage->mY - aCtx.mBlendY, anAlpha, blendMode, true);
  850. }
  851. }
  852. else
  853. {
  854. float anAlpha = srcLayer->mFillOpacity / 255.0f;
  855. if (srcLayer->mBlendInteriorEffectsAsGroup)
  856. anAlpha = 1.0f;
  857. if (!doPostOpacity)
  858. anAlpha *= (srcLayer->mOpacity / 255.0f);
  859. BlendImage(aDestImage, aSrcImage, aSrcImage->mX - aCtx.mBlendX, aSrcImage->mY - aCtx.mBlendY, anAlpha, srcLayer->mBlendMode, aCtx.mOuterImage != NULL);
  860. }
  861. if ((srcLayer->mLayerMaskHidesEffects) && (srcLayer->mLayerMaskEnabled))
  862. {
  863. aMask = new uint8[aCtx.mBlendWidth * aCtx.mBlendHeight];
  864. memset(aMask, srcLayer->mLayerMaskDefault, aCtx.mBlendWidth * aCtx.mBlendHeight);
  865. ImageData* anImage = aCtx.mOrigImage;
  866. int maskStartX = std::max(srcLayer->mLayerMaskX, anImage->mX);
  867. int maskStartY = std::max(srcLayer->mLayerMaskY, anImage->mY);
  868. int maskEndX = std::min(srcLayer->mLayerMaskX + srcLayer->mLayerMaskWidth, anImage->mX + anImage->mWidth);
  869. int maskEndY = std::min(srcLayer->mLayerMaskY + srcLayer->mLayerMaskHeight, anImage->mY + anImage->mHeight);
  870. for (int y = maskStartY; y < maskEndY; y++)
  871. {
  872. uint8* maskSrc = srcLayer->mLayerMask + (y - srcLayer->mLayerMaskY)*srcLayer->mLayerMaskWidth;
  873. uint8* maskDest = aMask + (y - anImage->mY)*anImage->mWidth;
  874. for (int x = maskStartX; x < maskEndX; x++)
  875. maskDest[x - anImage->mX] = maskSrc[x - srcLayer->mLayerMaskX];
  876. }
  877. }
  878. for (int i = 0; i < (int) mImageEffectVector.size(); i++)
  879. {
  880. BaseImageEffect* anEffect = mImageEffectVector[i];
  881. if (!anEffect->mInitialized)
  882. {
  883. anEffect->Init();
  884. anEffect->mInitialized = true;
  885. }
  886. AutoPerf gPerf("ImageEffects::FlattenInto ImageEffect");
  887. anEffect->Apply(&aCtx);
  888. }
  889. // Did we create a temporary source image (for adjustment layers, primary)
  890. if (aSrcImage != srcImage)
  891. {
  892. //delete aSrcImage;
  893. //aSrcImage = srcImage;
  894. // Add back in the destination alpha that was factored out during adjustment image creation
  895. //MultiplyImageAlpha(aSrcImage, dest);
  896. }
  897. //aCtx.mOuterImage->mBits[0] = 0xFFFFFFFF;
  898. //aCtx.mOuterImage->mBits[aCtx.mBlendWidth*aCtx.mBlendHeight-1] = 0xFFFFFFFF;
  899. if (srcLayer->mBlendInteriorEffectsAsGroup)
  900. {
  901. for (int y = 0; y < aSrcImage->mHeight; y++)
  902. {
  903. PackedColor* srcColor = (PackedColor*) (aSrcImage->mBits + y*aSrcImage->mWidth);
  904. for (int x = 0; x < aSrcImage->mWidth; x++)
  905. {
  906. srcColor->a = (srcColor->a * srcLayer->mFillOpacity) / 255;
  907. srcColor++;
  908. }
  909. }
  910. }
  911. if (aCtx.mOuterImage != NULL)
  912. {
  913. //TODO: Do this right...
  914. /*for (int x = 0; x < aSrcImage->mWidth; x++)
  915. {
  916. for (int y = 0; y < borderSize; y++)
  917. aDestImage->mBits[x+y*aCtx.mBlendWidth] = aCtx.mOuterImage->mBits[x+y*aCtx.mBlendWidth];
  918. for (int y = aCtx.mBlendHeight-borderSize; y < aCtx.mBlendHeight; y++)
  919. aDestImage->mBits[x+y*aCtx.mBlendWidth] = aCtx.mOuterImage->mBits[x+y*aCtx.mBlendWidth];
  920. }
  921. for (int y = borderSize; y < aCtx.mBlendHeight-borderSize; y++)
  922. {
  923. for (int x = 0; x < borderSize; x++)
  924. aDestImage->mBits[x+y*aCtx.mBlendWidth] = aCtx.mOuterImage->mBits[x+y*aCtx.mBlendWidth];
  925. for (int x = aCtx.mBlendWidth-borderSize; x < aCtx.mBlendWidth; x++)
  926. aDestImage->mBits[x+y*aCtx.mBlendWidth] = aCtx.mOuterImage->mBits[x+y*aCtx.mBlendWidth];
  927. }*/
  928. for (int y = aCtx.mBlendY; y < aCtx.mBlendY + aCtx.mBlendHeight; y++)
  929. {
  930. for (int x = aCtx.mBlendX; x < aCtx.mBlendX + aCtx.mBlendWidth; x++)
  931. {
  932. aDestImage->mBits[(x-aCtx.mBlendX)+(y-aCtx.mBlendY)*aCtx.mBlendWidth] =
  933. aCtx.mOuterImage->mBits[(x-aCtx.mBlendX)+(y-aCtx.mBlendY)*aCtx.mBlendWidth];
  934. }
  935. }
  936. /*int aSize = aCtx.mBlendWidth*aCtx.mBlendHeight;
  937. for (int i = 0; i < aSize; i++)
  938. aDestImage->mBits[i] = aCtx.mOuterImage->mBits[i];*/
  939. if (aCtx.mInnerImage == NULL)
  940. {
  941. for (int y = 0; y < aSrcImage->mHeight; y++)
  942. {
  943. PackedColor* srcColor = (PackedColor*) (aSrcImage->mBits + y*aSrcImage->mWidth);
  944. PackedColor* aDestColor = (PackedColor*) (aDestImage->mBits + borderSize + (y + borderSize) * aDestImage->mWidth);
  945. PackedColor* effectOutsideColor = (PackedColor*) (aCtx.mOuterImage->mBits + borderSize + ((y + borderSize) * aCtx.mBlendWidth));
  946. for (int x = 0; x < aSrcImage->mWidth; x++)
  947. {
  948. int a = srcColor->a;
  949. int oma = 255 - a;
  950. int newDestAlpha = ((aDestColor->a * a) + (effectOutsideColor->a * oma)) / 255;
  951. if (newDestAlpha != 0)
  952. {
  953. int ca = (255 * aDestColor->a * a) / (aDestColor->a * a + effectOutsideColor->a * oma);
  954. int coma = 255 - ca;
  955. aDestColor->a = newDestAlpha;
  956. aDestColor->r = ((aDestColor->r * ca) + (effectOutsideColor->r * coma)) / 255;
  957. aDestColor->g = ((aDestColor->g * ca) + (effectOutsideColor->g * coma)) / 255;
  958. aDestColor->b = ((aDestColor->b * ca) + (effectOutsideColor->b * coma)) / 255;
  959. }
  960. srcColor++;
  961. aDestColor++;
  962. effectOutsideColor++;
  963. }
  964. }
  965. }
  966. }
  967. if (aCtx.mInnerImage != NULL)
  968. {
  969. if (aCtx.mOuterImage != NULL)
  970. {
  971. if (aMask != NULL)
  972. {
  973. for (int y = 0; y < aSrcImage->mHeight; y++)
  974. {
  975. uint8* maskData = (aMask + borderSize + ((y + borderSize) * aCtx.mBlendWidth));
  976. PackedColor* srcColor = (PackedColor*) (aSrcImage->mBits + y*aSrcImage->mWidth);
  977. PackedColor* aDestColor = (PackedColor*) (aDestImage->mBits + borderSize + (y + borderSize) * aDestImage->mWidth);
  978. PackedColor* effectInsideColor = (PackedColor*) (aCtx.mInnerImage->mBits + borderSize + ((y + borderSize) * aCtx.mBlendWidth));
  979. PackedColor* effectOutsideColor = (PackedColor*) (aCtx.mOuterImage->mBits + borderSize + ((y + borderSize) * aCtx.mBlendWidth));
  980. PackedColor* origColor = (PackedColor*) (aCtx.mOrigImage->mBits + borderSize + ((y + borderSize) * aCtx.mBlendWidth));
  981. for (int x = 0; x < aSrcImage->mWidth; x++)
  982. {
  983. /*if ((aCtx.mBlendX + x == 60) && (aCtx.mBlendY + y == 60))
  984. {
  985. _asm nop;
  986. }*/
  987. uint32 insidePct = srcColor->a * (*maskData);
  988. uint32 outsidePct = (255 - srcColor->a) * (*maskData);
  989. uint32 origPct = 255 * (255 - *maskData);
  990. uint32 insideContrib = effectInsideColor->a * insidePct;
  991. uint32 outsideContrib = effectOutsideColor->a * outsidePct;
  992. uint32 origContrib = origColor->a * origPct;
  993. uint32 totalContrib = insideContrib + outsideContrib + origContrib;
  994. int newDestAlpha = (insideContrib + outsideContrib + origContrib) / 255 / 255;
  995. if (newDestAlpha != 0)
  996. {
  997. int ma = *maskData;
  998. int moma = 255 - ma;
  999. aDestColor->r = ((insideContrib * effectInsideColor->r) + (outsideContrib * effectOutsideColor->r) + (origContrib * origColor->r)) / totalContrib;
  1000. aDestColor->g = ((insideContrib * effectInsideColor->g) + (outsideContrib * effectOutsideColor->g) + (origContrib * origColor->g)) / totalContrib;
  1001. aDestColor->b = ((insideContrib * effectInsideColor->b) + (outsideContrib * effectOutsideColor->b) + (origContrib * origColor->b)) / totalContrib;
  1002. }
  1003. aDestColor->a = newDestAlpha;
  1004. origColor++;
  1005. maskData++;
  1006. srcColor++;
  1007. aDestColor++;
  1008. effectInsideColor++;
  1009. effectOutsideColor++;
  1010. }
  1011. }
  1012. }
  1013. else
  1014. {
  1015. for (int y = 0; y < aSrcImage->mHeight; y++)
  1016. {
  1017. int ctxOffset = (aSrcImage->mX - aCtx.mBlendX) + (aSrcImage->mY - aCtx.mBlendY + y)*aCtx.mBlendWidth;
  1018. PackedColor* srcColor = (PackedColor*) (aSrcImage->mBits + y*aSrcImage->mWidth);
  1019. PackedColor* aDestColor = (PackedColor*) (aDestImage->mBits + ctxOffset);
  1020. PackedColor* effectInsideColor = (PackedColor*) (aCtx.mInnerImage->mBits + ctxOffset);
  1021. PackedColor* effectOutsideColor = (PackedColor*) (aCtx.mOuterImage->mBits + ctxOffset);
  1022. for (int x = 0; x < aSrcImage->mWidth; x++)
  1023. {
  1024. if (srcColor->a == 0)
  1025. {
  1026. *aDestColor = *effectOutsideColor;
  1027. }
  1028. else
  1029. {
  1030. int a = srcColor->a;
  1031. int oma = 255 - a;
  1032. int newDestAlpha = ((effectInsideColor->a * a) + (effectOutsideColor->a * oma)) / 255;
  1033. if (newDestAlpha != 0)
  1034. {
  1035. int ca = (255 * effectInsideColor->a * a) / (effectInsideColor->a * a + effectOutsideColor->a * oma);
  1036. int coma = 255 - ca;
  1037. aDestColor->a = newDestAlpha;
  1038. aDestColor->r = ((effectInsideColor->r * ca) + (effectOutsideColor->r * coma)) / 255;
  1039. aDestColor->g = ((effectInsideColor->g * ca) + (effectOutsideColor->g * coma)) / 255;
  1040. aDestColor->b = ((effectInsideColor->b * ca) + (effectOutsideColor->b * coma)) / 255;
  1041. }
  1042. else
  1043. {
  1044. *aDestColor = *effectOutsideColor;
  1045. }
  1046. }
  1047. srcColor++;
  1048. aDestColor++;
  1049. effectInsideColor++;
  1050. effectOutsideColor++;
  1051. }
  1052. }
  1053. }
  1054. }
  1055. else
  1056. {
  1057. for (int y = 0; y < aSrcImage->mHeight; y++)
  1058. {
  1059. PackedColor* srcColor = (PackedColor*) (aSrcImage->mBits + y*aSrcImage->mWidth);
  1060. PackedColor* aDestColor = (PackedColor*) (aDestImage->mBits + borderSize + (y + borderSize) * aDestImage->mWidth);
  1061. PackedColor* effectInsideColor = (PackedColor*) (aCtx.mInnerImage->mBits + borderSize + ((y + borderSize) * aCtx.mBlendWidth));
  1062. for (int x = 0; x < aSrcImage->mWidth; x++)
  1063. {
  1064. //if (srcColor->a != 0)
  1065. {
  1066. int a = 255 - srcColor->a;
  1067. if (!srcLayer->mTransparencyShapesLayer)
  1068. a = 0;
  1069. int oma = 255 - a;
  1070. int newDestAlpha = ((aDestColor->a * a) + (effectInsideColor->a * oma)) / 255;
  1071. if (newDestAlpha != 0)
  1072. {
  1073. int ca = (255 * aDestColor->a * a) / (aDestColor->a * a + effectInsideColor->a * oma);
  1074. int coma = 255 - ca;
  1075. aDestColor->a = newDestAlpha;
  1076. aDestColor->r = ((aDestColor->r * ca) + (effectInsideColor->r * coma)) / 255;
  1077. aDestColor->g = ((aDestColor->g * ca) + (effectInsideColor->g * coma)) / 255;
  1078. aDestColor->b = ((aDestColor->b * ca) + (effectInsideColor->b * coma)) / 255;
  1079. }
  1080. }
  1081. srcColor++;
  1082. aDestColor++;
  1083. effectInsideColor++;
  1084. }
  1085. }
  1086. }
  1087. }
  1088. /*if (srcLayer->mImageAdjustment != NULL)
  1089. {
  1090. // Just use the "inner image" as the dest since there's no mask to apply
  1091. delete aDestImage;
  1092. aDestImage = aCtx.mInnerImage;
  1093. aCtx.mInnerImage = NULL;
  1094. }*/
  1095. if (hasBlendingRanges)
  1096. {
  1097. int aStartX = std::max(aSrcImage->mX, dest->mX);
  1098. int aStartY = std::max(aSrcImage->mY, dest->mY);
  1099. int aEndX = std::min(aSrcImage->mX + aSrcImage->mWidth, dest->mX + dest->mWidth);
  1100. int aEndY = std::min(aSrcImage->mY + aSrcImage->mHeight, dest->mY + dest->mHeight);
  1101. PackedColor* blendingRangeSourceStart = (PackedColor*) &(srcLayer->mBlendingRangeSourceStart);
  1102. PackedColor* blendingRangeSourceEnd = (PackedColor*) &(srcLayer->mBlendingRangeSourceEnd);
  1103. PackedColor* blendingRangeDestStart = (PackedColor*) &(srcLayer->mBlendingRangeDestStart);
  1104. PackedColor* blendingRangeDestEnd = (PackedColor*) &(srcLayer->mBlendingRangeDestEnd);
  1105. ApplyBlendingRange(dest, aDestImage, aSrcImage, blendingRangeSourceStart->r, blendingRangeSourceEnd->r, PackedColorGetR());
  1106. ApplyBlendingRange(dest, aDestImage, dest, blendingRangeDestStart->r, blendingRangeDestEnd->r, PackedColorGetR());
  1107. ApplyBlendingRange(dest, aDestImage, aSrcImage, blendingRangeSourceStart->g, blendingRangeSourceEnd->g, PackedColorGetG());
  1108. ApplyBlendingRange(dest, aDestImage, dest, blendingRangeDestStart->g, blendingRangeDestEnd->g, PackedColorGetG());
  1109. ApplyBlendingRange(dest, aDestImage, aSrcImage, blendingRangeSourceStart->b, blendingRangeSourceEnd->b, PackedColorGetB());
  1110. ApplyBlendingRange(dest, aDestImage, dest, blendingRangeDestStart->b, blendingRangeDestEnd->b, PackedColorGetB());
  1111. ApplyBlendingRange(dest, aDestImage, aSrcImage, blendingRangeSourceStart->a, blendingRangeSourceEnd->a, PackedColorGetGray());
  1112. ApplyBlendingRange(dest, aDestImage, dest, blendingRangeDestStart->a, blendingRangeDestEnd->a, PackedColorGetGray());
  1113. }
  1114. if (srcLayer->mChannelMask != 0xFFFFFFFF)
  1115. {
  1116. for (int i = 0; i < aDestImage->mWidth*aDestImage->mHeight; i++)
  1117. aDestImage->mBits[i] &= srcLayer->mChannelMask;
  1118. int aStartX = dest->mX;
  1119. int aStartY = dest->mY;
  1120. int aEndX = dest->mX + dest->mWidth;
  1121. int aEndY = dest->mY + dest->mHeight;
  1122. for (int y = aStartY; y < aEndY; y++)
  1123. {
  1124. uint32* aDestColor = aDestImage->mBits + (aStartX - aDestImage->mX) + ((y - aDestImage->mY) * aDestImage->mWidth);
  1125. uint32* origColor = dest->mBits + (aStartX - dest->mX) + ((y - dest->mY) * dest->mWidth);
  1126. for (int x = aStartX; x < aEndX; x++)
  1127. {
  1128. *aDestColor |= (*origColor & ~srcLayer->mChannelMask);
  1129. aDestColor++;
  1130. origColor++;
  1131. }
  1132. }
  1133. }
  1134. if ((srcLayer->mOpacity != 255) && (doPostOpacity))
  1135. CrossfadeImage(dest, aDestImage, srcLayer->mOpacity / 255.0f);
  1136. if (aSrcImage != srcImage)
  1137. {
  1138. // If we have a temporary source image (for an adjustment layer, for example)
  1139. delete aSrcImage;
  1140. }
  1141. delete aMask;
  1142. return aDestImage;
  1143. }
  1144. void ImageEffects::AddEffect(BaseImageEffect* effect)
  1145. {
  1146. mImageEffectVector.push_back(effect);
  1147. }
  1148. //
  1149. BaseImageEffect::BaseImageEffect()
  1150. {
  1151. mContourData = NULL;
  1152. mGradientData = NULL;
  1153. mInitialized = false;
  1154. }
  1155. BaseImageEffect::~BaseImageEffect()
  1156. {
  1157. delete mContourData;
  1158. delete mGradientData;
  1159. }
  1160. void BaseImageEffect::Init()
  1161. {
  1162. }
  1163. void BaseImageEffect::Apply(ImageEffectCtx* ctx)
  1164. {
  1165. ImageData* effectImage = new ImageData();
  1166. effectImage->CreateNew(ctx->mBlendWidth, ctx->mBlendHeight);
  1167. effectImage->mX = ctx->mBlendX;
  1168. effectImage->mY = ctx->mBlendY;
  1169. Apply(ctx->mLayerInfo, ctx->mLayerImage, effectImage);
  1170. int mixType = GetMixType();
  1171. if ((mixType == IMAGEMIX_INNER) || (mixType == IMAGEMIX_OVER))
  1172. BlendImage(ctx->mInnerImage, effectImage, 0, 0, (float) mOpacity / 100.0f, mBlendMode);
  1173. if ((mixType == IMAGEMIX_OUTER) || (mixType == IMAGEMIX_OVER))
  1174. BlendImage(ctx->mOuterImage, effectImage, 0, 0, (float) mOpacity / 100.0f, mBlendMode);
  1175. delete effectImage;
  1176. }
  1177. int BaseImageEffect::GetMixType() // Otherwise interior
  1178. {
  1179. return IMAGEMIX_INNER;
  1180. }
  1181. int BaseImageEffect::GetNeededBorderSize()
  1182. {
  1183. return 0;
  1184. }
  1185. bool BaseImageEffect::NeedsOrigBits(ImageEffects* effects)
  1186. {
  1187. return false;
  1188. }
  1189. void ImageShadowEffect::Init()
  1190. {
  1191. mContourData = CreateContourDataTable(&mContour, 1.0f);
  1192. }
  1193. void ImageShadowEffect::Apply(PSDLayerInfo* layerInfo, ImageData* imageData, ImageData* destImageData)
  1194. {
  1195. int w = destImageData->mWidth;
  1196. int h = destImageData->mHeight;
  1197. int aSize = w*h;
  1198. float spread = (float) mSpread / 100.0f;
  1199. float spreadSize = (float) (int) (mSize * spread + 0.5f);
  1200. int distTransSize = 0;
  1201. ImageData* tempImage = new ImageData();
  1202. tempImage->CreateNew(w, h);
  1203. tempImage->mX = destImageData->mX;
  1204. tempImage->mY = destImageData->mY;
  1205. float aRadius = (float) mSize;
  1206. float aRadiusLeft = (float) mSize;
  1207. bool isInside = GetMixType() == IMAGEMIX_INNER;
  1208. if (spreadSize != 0)
  1209. {
  1210. // Do distance transform first to "grow" area
  1211. float distLenOffset = spreadSize / 20.0f;
  1212. float distLen = spreadSize - 1.0f + distLenOffset;
  1213. ChamferedDistanceTransformInit(imageData, tempImage, isInside);
  1214. ChamferedDistanceTransform(tempImage->mBits, w, h);
  1215. for (int i = 0; i < aSize; i++)
  1216. {
  1217. float dist = tempImage->mBits[i] / 256.0f;
  1218. dist -= spreadSize;
  1219. if (dist < 0)
  1220. tempImage->mBits[i] = 0xFF00;
  1221. else if (dist < 1.0f)
  1222. tempImage->mBits[i] = BFClamp((int) ((1.0f - dist) * 255.0f * 256.0f), 0, 0xFF00);
  1223. else
  1224. tempImage->mBits[i] = 0;
  1225. }
  1226. aRadiusLeft -= spreadSize;
  1227. }
  1228. else
  1229. {
  1230. SoftBlurInit(imageData, tempImage, isInside);
  1231. }
  1232. float radiusOffset = 1.2f;
  1233. float blurRadius = aRadiusLeft - radiusOffset;
  1234. if (aRadiusLeft <= 2)
  1235. blurRadius = 0.5f;
  1236. if (aRadiusLeft != 0)
  1237. SoftBlur(tempImage->mBits, w, h, blurRadius, 0);
  1238. bool doFrontTaper = (!isInside) &&
  1239. (((mContour.GetVal(0) != 0) || (mNoise != 0)));
  1240. if ((mAntiAliased) && (!mContour.IsDefault()) && (!doFrontTaper))
  1241. AntiAliasIndices(tempImage->mBits, w, h);
  1242. memset(destImageData->mBits, 0, w*h*sizeof(uint32));
  1243. float noise = (float) mNoise / 100.0f;
  1244. float angle = mUseGlobalLight ? (float) layerInfo->mPSDReader->mGlobalAngle : (float) mLocalAngle;
  1245. angle *= BF_PI / 180.0f;
  1246. int ofsX = (int) (BFRound(-cos(angle) * (float) mDistance));
  1247. int ofsY = (int) (BFRound(sin(angle) * (float) mDistance));
  1248. int maxX = std::min(w, w + ofsX);
  1249. int maxY = std::min(h, h + ofsY);
  1250. for (int y = std::max(0, ofsY); y < maxY; y++)
  1251. {
  1252. for (int x = std::max(0, ofsX); x < maxX; x++)
  1253. {
  1254. int i = x+y*w;
  1255. PackedColor* aDestColor = (PackedColor*) (destImageData->mBits + i);
  1256. int blurVal = tempImage->mBits[(x-ofsX)+(y-ofsY)*w];
  1257. int idx = (blurVal * (CONTOUR_DATA_SIZE - 1) / 255) / 256;
  1258. BF_ASSERT(idx >= 0);
  1259. BF_ASSERT(idx < CONTOUR_DATA_SIZE);
  1260. int gradientIdx = mContourData[idx];
  1261. BF_ASSERT(gradientIdx >= 0);
  1262. BF_ASSERT(gradientIdx < GRADIENT_DATA_SIZE);
  1263. destImageData->mBits[i] = ((gradientIdx * 255 / (GRADIENT_DATA_SIZE - 1)) << 24) | (mColor & 0x00FFFFFF);
  1264. //TODO: Apply 'front taper?'
  1265. if (mNoise > 0)
  1266. {
  1267. if (rand() % 5 < 4)
  1268. {
  1269. float pixNoise = 256 * noise;
  1270. if (aDestColor->a > 0)
  1271. {
  1272. float randPct = ((Rand() % 10000) / 5000.0f) - 1.0f;
  1273. aDestColor->a = BFClamp(aDestColor->a + (int) (randPct * pixNoise + 0.5f), 0, 255);
  1274. }
  1275. }
  1276. }
  1277. if (doFrontTaper)
  1278. {
  1279. float minAlpha = std::min(1.0f, (idx / 4095.0f) * 8.4f);
  1280. aDestColor->a = std::min((int) aDestColor->a, (int) (minAlpha * 255));
  1281. }
  1282. /*if (i % 7 == 0)
  1283. {
  1284. aDestColor->a = 255;
  1285. aDestColor->r = 255;
  1286. }*/
  1287. }
  1288. }
  1289. delete tempImage;
  1290. }
  1291. int ImageShadowEffect::GetNeededBorderSize()
  1292. {
  1293. return (int) mSize + (int) mDistance;
  1294. }
  1295. int ImageDropShadowEffect::GetMixType()
  1296. {
  1297. return IMAGEMIX_OUTER;
  1298. }
  1299. void ImageGlowEffect::Init()
  1300. {
  1301. CreateContourAndGradientData();
  1302. }
  1303. ///
  1304. void ImageGlowEffect::CreateContourAndGradientData()
  1305. {
  1306. mContourData = CreateContourDataTable(&mContour, (float) mRange / 100.0f);
  1307. mGradientData = CreateGradientDataTable(mColorGradient);
  1308. }
  1309. int ImageGlowEffect::GetNeededBorderSize()
  1310. {
  1311. //TODO: Empirically we only need (mSize / 2) for soft inner glow...
  1312. return (int) mSize;
  1313. }
  1314. void ChokedPixelTransform(ImageData* src, ImageData* dest, float radius, float chokePct, bool invert, bool soften = false)
  1315. {
  1316. int w = dest->mWidth;
  1317. int h = dest->mHeight;
  1318. uint32* aDest = dest->mBits;
  1319. ChamferedDistanceTransformInit(src, dest, invert, soften ? (int) radius : 0);
  1320. ChamferedDistanceTransform(dest->mBits, w, h);
  1321. int aSize = w*h;
  1322. int chokePixels = (int) (radius * chokePct + 0.5f);
  1323. bool fullChoke = chokePixels == radius;
  1324. uint32* tempBuffer = new uint32[w*h];
  1325. uint32* exterior = dest->mBits;
  1326. uint32* anInterior = tempBuffer;
  1327. float rad = radius + 0.5f - chokePixels;
  1328. int inf = (int) (radius + 2) * 256;
  1329. if (soften)
  1330. {
  1331. uint32* in = src->mBits;
  1332. int iw = src->mWidth;
  1333. int ih = src->mHeight;
  1334. int ox = src->mX - dest->mX;
  1335. int oy = src->mY - dest->mY;
  1336. for (int y = 0; y < ih; y++)
  1337. {
  1338. for (int x = 0; x < iw; x++)
  1339. {
  1340. int anAlpha = in[x+y*iw]>>24;
  1341. int i = (x+ox)+(y+oy)*w;
  1342. float dist = aDest[i] / 256.0f;
  1343. dist -= chokePixels + 0.001f;
  1344. if (dist < 0)
  1345. anInterior[i] = 0;
  1346. else if (dist < 1.0f)
  1347. anInterior[i] = (int) (dist * 256);
  1348. else
  1349. anInterior[i] = (int) (dist * 256);
  1350. if (anAlpha <= 128)
  1351. exterior[i] = (int) ((128.0f - anAlpha) * (radius * 2 + 2) + 0.5f);
  1352. else
  1353. exterior[i] = 0;
  1354. }
  1355. }
  1356. inf = (int) (128.0f * (radius * 2 + 2) + 0.5f);
  1357. for (int x = 0; x < w; x++)
  1358. {
  1359. for (int y = 0; y < oy; y++)
  1360. exterior[x+y*w] = inf;
  1361. for (int y = oy+ih; y < h; y++)
  1362. exterior[x+y*w] = inf;
  1363. }
  1364. for (int y = oy; y < oy+ih; y++)
  1365. {
  1366. for (int x = 0; x < ox; x++)
  1367. exterior[x+y*w] = inf;
  1368. for (int x = ox+iw; x < w; x++)
  1369. exterior[x+y*w] = inf;
  1370. }
  1371. }
  1372. else
  1373. {
  1374. for (int i = 0; i < aSize; i++)
  1375. {
  1376. float dist = aDest[i] / 256.0f;
  1377. dist -= chokePixels + 0.001f;
  1378. if (dist < 0)
  1379. {
  1380. exterior[i] = inf;
  1381. anInterior[i] = 0;
  1382. }
  1383. else if (dist < 1.0f)
  1384. {
  1385. exterior[i] = BFClamp((int) ((1.0f - dist) * 256.0f), 0, 0xFF);
  1386. anInterior[i] = (int) (dist * 256);
  1387. }
  1388. else
  1389. {
  1390. exterior[i] = 0;
  1391. anInterior[i] = (int) (dist * 256);
  1392. }
  1393. }
  1394. }
  1395. ChamferedDistanceTransform(exterior, w, h);
  1396. float interiorDiv = (rad + 0.5f);
  1397. float interiorOffset = 0;
  1398. float exteriorOffset = -255;
  1399. float exteriorDivide = (radius + 1.0f - chokePixels);
  1400. if (soften)
  1401. {
  1402. exteriorOffset = 0;
  1403. }
  1404. if (fullChoke)
  1405. {
  1406. for (int i = 0; i < aSize; i++)
  1407. aDest[i] = std::min((uint32)0xFF00, exterior[i] * 256);
  1408. }
  1409. else
  1410. {
  1411. for (int i = 0; i < aSize; i++)
  1412. {
  1413. uint32 alphaVal = (uint32) (std::max(0.0f, (int) exterior[i] + exteriorOffset ) * 256 / exteriorDivide);
  1414. alphaVal = std::min((uint32) 0xFF00, (uint32) (alphaVal * 0.5f + 0x7F00));
  1415. uint32 alphaVal2 = (uint32) (std::max(0.0f, (int) anInterior[i] + interiorOffset) * 256 / interiorDiv);
  1416. if (alphaVal <= 0x7F80)
  1417. alphaVal = (uint32) std::min((uint32) 0xFF00, (uint32) std::max(0.0f, (0xFF00 - (int) alphaVal2) * 0.5f));
  1418. aDest[i] = alphaVal;
  1419. BF_ASSERT(alphaVal <= 0xFF00);
  1420. }
  1421. }
  1422. delete [] tempBuffer;
  1423. }
  1424. void ImageOuterGlowEffect::Apply(PSDLayerInfo* layerInfo, ImageData* imageData, ImageData* destImageData)
  1425. {
  1426. int sw = imageData->mWidth;
  1427. int sh = imageData->mHeight;
  1428. int w = destImageData->mWidth;
  1429. int h = destImageData->mHeight;
  1430. ImageData* newImage = destImageData;
  1431. float radius = (float) mSize;
  1432. int aSize = w*h;
  1433. float spread = (float) mSpread / 100.0f;
  1434. float spreadSize = (float) (int) (mSize * spread + 0.5f);
  1435. int distTransSize = 0;
  1436. if (mTechnique == 'PrBL')
  1437. {
  1438. ChokedPixelTransform(imageData, newImage, radius, spread, false);
  1439. }
  1440. else if (mTechnique == 'SfBL')
  1441. {
  1442. radius = std::max(radius, 2.0f); // Radius of '1' gets bumped up to 2
  1443. float aRadiusLeft = radius;
  1444. if (spreadSize != 0)
  1445. {
  1446. // Do distance transform first to "grow" area
  1447. float distLenOffset = spreadSize / 20.0f;
  1448. float distLen = spreadSize - 1.0f + distLenOffset;
  1449. ChamferedDistanceTransformInit(imageData, newImage, false);
  1450. ChamferedDistanceTransform(newImage->mBits, w, h);
  1451. for (int i = 0; i < aSize; i++)
  1452. {
  1453. float dist = newImage->mBits[i] / 256.0f;
  1454. dist -= spreadSize;
  1455. if (dist < 0)
  1456. newImage->mBits[i] = 0xFF00;
  1457. else if (dist < 1.0f)
  1458. newImage->mBits[i] = BFClamp((int) ((1.0f - dist) * 255.0f * 256.0f), 0, 0xFF00);
  1459. else
  1460. newImage->mBits[i] = 0;
  1461. }
  1462. aRadiusLeft -= spreadSize;
  1463. }
  1464. else
  1465. {
  1466. SoftBlurInit(imageData, newImage, false);
  1467. }
  1468. float radiusOffset = 1.2f;
  1469. float blurRadius = aRadiusLeft - radiusOffset;
  1470. if (aRadiusLeft <= 2)
  1471. blurRadius = 0.5f;
  1472. if ((aRadiusLeft != 0) && (mSize != 0))
  1473. SoftBlur(newImage->mBits, w, h, blurRadius, 0);
  1474. }
  1475. //OutputDebugStrF("Contour Time: %d\r\n", timeGetTime() - tickStart);
  1476. bool doFrontTaper =
  1477. ((mColorGradient[3].GetVal((1.0f - mContour.GetVal(0) / 255.0f) * mColorGradient[3].mXSize) != 0) || (mNoise != 0));
  1478. if ((mAntiAliased) && (!mContour.IsDefault()) && (!doFrontTaper))
  1479. AntiAliasIndices(newImage->mBits, w, h);
  1480. float noise = (float) mNoise / 100.0f;
  1481. float jitter = (float) mJitter / 100.0f;
  1482. for (int i = 0; i < aSize; i++)
  1483. {
  1484. PackedColor* srcColor = (PackedColor*) (imageData->mBits + i);
  1485. PackedColor* aDestColor = (PackedColor*) (newImage->mBits + i);
  1486. int blurVal = newImage->mBits[i];
  1487. int idx = (blurVal * (CONTOUR_DATA_SIZE - 1) / 255) / 256;
  1488. BF_ASSERT(idx >= 0);
  1489. BF_ASSERT(idx < CONTOUR_DATA_SIZE);
  1490. int gradientIdx = mContourData[idx];
  1491. if ((jitter > 0) && (mHasGradient))
  1492. {
  1493. if (rand() % 5 < 4)
  1494. {
  1495. float idxJitter = GRADIENT_DATA_SIZE * jitter;
  1496. if (idx != 0)
  1497. {
  1498. float randPct = ((Rand() % 10000) / 5000.0f) - 1.0f;
  1499. gradientIdx = BFClamp(gradientIdx + (int) (randPct * idxJitter + 0.5f), 0, CONTOUR_DATA_SIZE - 1);
  1500. }
  1501. }
  1502. }
  1503. BF_ASSERT(gradientIdx >= 0);
  1504. BF_ASSERT(gradientIdx < GRADIENT_DATA_SIZE);
  1505. newImage->mBits[i] = mGradientData[gradientIdx];
  1506. if (mNoise > 0)
  1507. {
  1508. if (rand() % 5 < 4)
  1509. {
  1510. float pixNoise = 256 * noise;
  1511. if (aDestColor->a > 0)
  1512. {
  1513. float randPct = ((Rand() % 10000) / 5000.0f) - 1.0f;
  1514. aDestColor->a = BFClamp(aDestColor->a + (int) (randPct * pixNoise + 0.5f), 0, 255);
  1515. }
  1516. }
  1517. }
  1518. if (doFrontTaper)
  1519. {
  1520. float minAlpha = std::min(1.0f, (idx / 4095.0f) * 8.4f);
  1521. aDestColor->a = std::min(aDestColor->a, (uint8) (minAlpha * 255));
  1522. }
  1523. }
  1524. }
  1525. int ImageOuterGlowEffect::GetMixType()
  1526. {
  1527. return IMAGEMIX_OUTER;
  1528. }
  1529. ///
  1530. void ImageInnerGlowEffect::Apply(PSDLayerInfo* layerInfo, ImageData* imageData, ImageData* destImageData)
  1531. {
  1532. int sw = destImageData->mWidth;
  1533. int sh = destImageData->mHeight;
  1534. int w = sw;
  1535. int h = sh;
  1536. ImageData* newImage = destImageData;
  1537. float radius = (float) mSize;
  1538. int aSize = w*h;
  1539. float choke = (float) mChoke / 100.0f;
  1540. float chokePixels = (float) (int) (choke * mSize + 0.5f);
  1541. bool fullChoke = chokePixels == mSize;
  1542. float rad = radius + 0.5f - chokePixels;
  1543. float inf = (radius + 1.5f) * 256;
  1544. if (mTechnique == 'PrBL')
  1545. {
  1546. ChokedPixelTransform(imageData, newImage, radius, choke, true);
  1547. }
  1548. else if (mTechnique == 'SfBL')
  1549. {
  1550. // Soft blur
  1551. float aRadiusLeft = radius;
  1552. if (chokePixels > 0)
  1553. {
  1554. aRadiusLeft -= chokePixels;
  1555. ChamferedDistanceTransformInit(imageData, newImage, true);
  1556. ChamferedDistanceTransform(newImage->mBits, w, h);
  1557. for (int i = 0; i < aSize; i++)
  1558. {
  1559. float dist = newImage->mBits[i] / 256.0f;
  1560. dist -= chokePixels + 0.001f;
  1561. /*if (((int) (imageData->mBits[i] >> 24) == 255) && (dist >= 0))
  1562. newImage->mBits[i] = std::max(0, 256 - (int) (dist * 256)) * 256;
  1563. else
  1564. newImage->mBits[i] = 255*256; */
  1565. if (dist < 0)
  1566. newImage->mBits[i] = 0xFF00;
  1567. else if (dist < 1.0f)
  1568. newImage->mBits[i] = BFClamp((int) ((1.0f - dist) * 255.0f * 256.0f), 0, 0xFF00);
  1569. else
  1570. newImage->mBits[i] = 0;
  1571. }
  1572. }
  1573. else
  1574. {
  1575. SoftBlurInit(imageData, newImage, true);
  1576. }
  1577. SoftBlur(newImage->mBits, w, h, GetSoftBlurRadius(radius, aRadiusLeft), 0xFF00);
  1578. }
  1579. //OutputDebugStrF("Contour Time: %d\r\n", timeGetTime() - tickStart);
  1580. if ((mAntiAliased) && (!mContour.IsDefault()))
  1581. AntiAliasIndices(newImage->mBits, w, h);
  1582. float noise = (float) mNoise / 100.0f;
  1583. float jitter = (float) mJitter / 100.0f;
  1584. for (int i = 0; i < aSize; i++)
  1585. {
  1586. PackedColor* aDestColor = (PackedColor*) (newImage->mBits + i);
  1587. int blurVal = newImage->mBits[i];
  1588. int idx = (blurVal * (CONTOUR_DATA_SIZE - 1) / 255) / 256;
  1589. BF_ASSERT(idx >= 0);
  1590. BF_ASSERT(idx < CONTOUR_DATA_SIZE);
  1591. int gradientIdx = mContourData[idx];
  1592. if ((jitter > 0) && (mHasGradient))
  1593. {
  1594. if (rand() % 5 < 4)
  1595. {
  1596. float idxJitter = GRADIENT_DATA_SIZE * jitter;
  1597. if (idx != 0)
  1598. {
  1599. float randPct = ((Rand() % 10000) / 5000.0f) - 1.0f;
  1600. gradientIdx = BFClamp(gradientIdx + (int) (randPct * idxJitter + 0.5f), 0, CONTOUR_DATA_SIZE - 1);
  1601. }
  1602. }
  1603. }
  1604. BF_ASSERT(gradientIdx >= 0);
  1605. BF_ASSERT(gradientIdx < GRADIENT_DATA_SIZE);
  1606. newImage->mBits[i] = mGradientData[gradientIdx];
  1607. if (mIsCenter)
  1608. aDestColor->a = std::max(0, 255 - aDestColor->a);
  1609. if (mNoise > 0)
  1610. {
  1611. if (rand() % 5 < 4)
  1612. {
  1613. float pixNoise = 256 * noise;
  1614. if (aDestColor->a > 0)
  1615. {
  1616. float randPct = ((Rand() % 10000) / 5000.0f) - 1.0f;
  1617. aDestColor->a = BFClamp(aDestColor->a + (int) (randPct * pixNoise + 0.5f), 0, 255);
  1618. }
  1619. }
  1620. }
  1621. }
  1622. }
  1623. ///
  1624. ImageBevelEffect::ImageBevelEffect()
  1625. {
  1626. mGlossContourData = NULL;
  1627. }
  1628. ImageBevelEffect::~ImageBevelEffect()
  1629. {
  1630. delete mGlossContourData;
  1631. }
  1632. void ImageBevelEffect::Init()
  1633. {
  1634. mGlossContourData = CreateContourDataTable(&mGlossContour);
  1635. if (mUseContour)
  1636. {
  1637. float aRange = (float) (mBevelContourRange / 100.0f);
  1638. mBevelContourData = new int32[CONTOUR_DATA_SIZE];
  1639. int minVal = 0;
  1640. for (int i = 0; i < CONTOUR_DATA_SIZE; i++)
  1641. {
  1642. float aX = i / (float) (CONTOUR_DATA_SIZE - 1);
  1643. aX = (aX - (1.0f - aRange)) / aRange;
  1644. float yVal = mBevelContour.GetVal(aX * 255.0f) / 255.0f;
  1645. int aVal = (int) (yVal * 0xFF00 + 0.5f);
  1646. minVal = std::min(minVal, aVal);
  1647. mBevelContourData[i] = aVal;
  1648. }
  1649. for (int i = 0; i < CONTOUR_DATA_SIZE; i++)
  1650. mBevelContourData[i] -= minVal;
  1651. }
  1652. }
  1653. void ImageBevelEffect::Apply(PSDLayerInfo* layerInfo, ImageData* imageData, ImageData* destImageData)
  1654. {
  1655. }
  1656. int ImageBevelEffect::GetMixType()
  1657. {
  1658. if (mStyle == 'OtrB') // Outer bevel
  1659. return IMAGEMIX_OUTER;
  1660. if (mStyle == 'Embs') // Emboss
  1661. return IMAGEMIX_OVER;
  1662. if (mStyle == 'PlEb') // Pillow emboss
  1663. return IMAGEMIX_OVER;
  1664. return IMAGEMIX_INNER;
  1665. }
  1666. void ImageBevelEffect::Apply(int pass, int style, PSDLayerInfo* layerInfo, ImageData* imageData, ImageData* hiliteImage, ImageData* shadowImage)
  1667. {
  1668. int w = hiliteImage->mWidth;
  1669. int h = hiliteImage->mHeight;
  1670. int aSize = w*h;
  1671. uint32* normalMap = new uint32[aSize];
  1672. PSDLayerInfo* aLayerInfo = layerInfo;
  1673. ImageData* anImageData = imageData;
  1674. ImageData* newImage = hiliteImage;
  1675. float aDepth = (float) mDepth / 100.0f;
  1676. float aRadius = (float) mSize;
  1677. float angle = mUseGlobalLight ? (float) aLayerInfo->mPSDReader->mGlobalAngle : (float) mLocalAngle;
  1678. float altitude = mUseGlobalLight ? (float) aLayerInfo->mPSDReader->mGlobalAltitude : (float) mLocalAltitude;
  1679. float lightAngle = angle * BF_PI / 180.0f;
  1680. float lightElevation = altitude * BF_PI / 180.0f;
  1681. bool doFlip = !mDirectionUp;
  1682. if (pass == 1)
  1683. doFlip = !doFlip;
  1684. if (doFlip)
  1685. lightAngle = lightAngle + BF_PI;
  1686. Vector3 shadowVec(cosf((float) lightElevation) * -cosf(lightAngle),
  1687. cosf(lightElevation) * sinf(lightAngle),
  1688. sinf(lightElevation));
  1689. bool doOuterTaper = (style == 'OtrB') || (style == 'Embs') || (style == 'PlEb');
  1690. float blurRadius = aRadius;
  1691. if ((style == 'Embs') || (style == 'PlEb'))
  1692. blurRadius = (float) (int) (blurRadius / 2 + 0.75f);
  1693. if (mTechnique == 'SfBL') // Technique:Smooth
  1694. {
  1695. SoftBlurInit(anImageData, newImage, false);
  1696. SoftBlur(newImage->mBits, w, h, blurRadius - 1.0f, 0);
  1697. for (int i = 0; i < aSize; i++)
  1698. {
  1699. uint32 aVal = newImage->mBits[i];
  1700. newImage->mBits[i] = std::min(0xFF00, (int) (aVal + 256 / blurRadius));
  1701. }
  1702. }
  1703. else
  1704. {
  1705. ChokedPixelTransform(anImageData, newImage, blurRadius, 0, true, mTechnique == 'Slmt');
  1706. for (int i = 0; i < aSize; i++)
  1707. {
  1708. uint32 aVal = newImage->mBits[i];
  1709. newImage->mBits[i] = 0xFF00 - aVal;
  1710. }
  1711. }
  1712. if (mUseContour)
  1713. {
  1714. for (int i = 0; i < aSize; i++)
  1715. {
  1716. uint32 aVal = newImage->mBits[i];
  1717. int idx = (aVal * (CONTOUR_DATA_SIZE - 1) / 255) / 256;
  1718. newImage->mBits[i] = mBevelContourData[idx];
  1719. }
  1720. }
  1721. if (mUseTexture)
  1722. {
  1723. PSDPattern* pattern = aLayerInfo->mPSDReader->mPSDPatternMap[mTexture.mPatternName];
  1724. int32 texMultiply = (int32) (0x100 * mTextureDepth / 100.0f);
  1725. int32 texOffset = texMultiply * 255;
  1726. if (!mTextureInvert)
  1727. texMultiply = -texMultiply;
  1728. int mipLevel = 0;
  1729. float dU = 1.0f / (float) (mTexture.mScale / 100.0f);
  1730. float dV = dU;
  1731. float virtPW = (float) pattern->mWidth;
  1732. float virtPH = (float) pattern->mHeight;
  1733. while (dU > 1.0001f)
  1734. {
  1735. // Select next mip level
  1736. mipLevel++;
  1737. PSDPattern* aMip = pattern->GetNextMipLevel();
  1738. dU /= 2.0f;
  1739. dV /= 2.0f;
  1740. virtPW /= 2.0f;
  1741. virtPH /= 2.0f;
  1742. pattern = aMip;
  1743. }
  1744. int pw = pattern->mWidth;
  1745. int ph = pattern->mHeight;
  1746. float startU = (float) (newImage->mX - (int) BFRound((float) mTexture.mPhaseX)) * dU;
  1747. while (startU < 0)
  1748. startU += virtPW;
  1749. float startV = (float) (newImage->mY - (int) BFRound((float) mTexture.mPhaseY)) * dV;
  1750. if (startV < 0)
  1751. startV += virtPH;
  1752. float aU = startU;
  1753. float aV = startV;
  1754. for (int y = 0; y < h; y++)
  1755. {
  1756. aU = startU;
  1757. uint32* aBits = newImage->mBits + (y*w);
  1758. for (int x = 0; x < w; x++)
  1759. {
  1760. int u1 = ((int) aU) % pw;
  1761. int v1 = ((int) aV) % ph;
  1762. float ua = aU - (int) aU;
  1763. float va = aV - (int) aV;
  1764. int u2 = (u1 + 1) % pw;
  1765. int v2 = (v1 + 1) % ph;
  1766. int intensity = (int) ((
  1767. ((float) pattern->mIntensityBits[u1+v1*pw] * (1.0f - ua) * (1.0f - va)) +
  1768. ((float) pattern->mIntensityBits[u2+v1*pw] * ( ua) * (1.0f - va)) +
  1769. ((float) pattern->mIntensityBits[u1+v2*pw] * (1.0f - ua) * ( va)) +
  1770. ((float) pattern->mIntensityBits[u2+v2*pw] * ( ua) * ( va))
  1771. ) * texMultiply + 0.5f);
  1772. *aBits = *aBits + intensity + texOffset;
  1773. aBits++;
  1774. aU += dU;
  1775. aU -= (int) (aU / virtPW) * virtPW;
  1776. }
  1777. aV += dV;
  1778. aV -= (int) (aV / virtPH) * virtPH;
  1779. }
  1780. }
  1781. CreateNormalMap(newImage->mBits, normalMap, w, h, 255.0f / blurRadius / aDepth * 0.80f, &shadowVec);
  1782. // Shadows need to be weightedly differently for 'softening' purposes
  1783. // This equation fits the proper curve, but I don't really understand why
  1784. float shadowWeighting = sin(lightElevation) / (1.0f - sin(lightElevation));
  1785. if ((mAntiAliased) && (!mGlossContour.IsDefault()))
  1786. AntiAliasIndices(normalMap, w, h);
  1787. for (int i = 0; i < aSize; i++)
  1788. {
  1789. float dot = (int) (normalMap[i] - 0x100000) / (float) 0xFF00;
  1790. float zeroPt = shadowVec.mZ;
  1791. //TODO: Cache gloss contour
  1792. float curvePos = mGlossContour.GetVal(255.0f * dot) / 255.0f;
  1793. curvePos -= zeroPt;
  1794. float curveIdx = 0;
  1795. if (curvePos > 0)
  1796. {
  1797. float hilitePct = curvePos / (1.0f - zeroPt);
  1798. curvePos = hilitePct;
  1799. curveIdx = curvePos;
  1800. }
  1801. else
  1802. {
  1803. float shadowPct = curvePos / zeroPt;
  1804. curvePos /= zeroPt;
  1805. }
  1806. float lightVal = curvePos;
  1807. lightVal = BFClamp(lightVal, -1.0f, 1.0f);
  1808. if (lightVal < 0)
  1809. lightVal *= shadowWeighting;
  1810. normalMap[i] = std::max((uint32) (0xFF00 * lightVal) + 0x100000, (uint32) 0);
  1811. }
  1812. float aSoften = (float) mSoften;
  1813. if (aSoften > 0)
  1814. {
  1815. float d = GetSoftBlurRadius(aSoften) / 2;
  1816. if (d > 0)
  1817. {
  1818. uint32* tempBuffer = newImage->mBits;
  1819. for (int i = 0; i < 2; i++)
  1820. {
  1821. BoxBlur(normalMap, tempBuffer, w, h, d, 0);
  1822. BoxBlur(tempBuffer, normalMap, h, w, d, 0);
  1823. }
  1824. }
  1825. }
  1826. for (int i = 0; i < aSize; i++)
  1827. {
  1828. float lightVal = (int) (normalMap[i] - 0x100000) / (float) 0xFF00;
  1829. if (lightVal < 0)
  1830. lightVal /= shadowWeighting;
  1831. if (doOuterTaper)
  1832. {
  1833. float taperVal = newImage->mBits[i] / 256.0f / 255.0f * 7.85f;
  1834. if (lightVal > 0)
  1835. lightVal = std::min(lightVal, taperVal);
  1836. else
  1837. lightVal = std::max(lightVal, -taperVal);
  1838. }
  1839. if (lightVal > 0)
  1840. {
  1841. hiliteImage->mBits[i] = ((int) (BFClamp(lightVal, 0.0f, 1.0f) * 255.0f + 0.5f) << 24) | (mHiliteColor & 0x00FFFFFF);
  1842. shadowImage->mBits[i] = 0;
  1843. }
  1844. else
  1845. {
  1846. hiliteImage->mBits[i] = 0;
  1847. shadowImage->mBits[i] = ((int) (BFClamp(-lightVal, 0.0f, 1.0f) * 255.0f + 0.5f) << 24) | (mShadowColor & 0x00FFFFFF);
  1848. }
  1849. }
  1850. delete [] normalMap;
  1851. }
  1852. void ImageBevelEffect::Apply(ImageEffectCtx* ctx)
  1853. {
  1854. if (mStyle == 'stro')
  1855. return;
  1856. ImageData* hiliteEffectImage = new ImageData();
  1857. hiliteEffectImage->CreateNew(ctx->mBlendWidth, ctx->mBlendHeight);
  1858. hiliteEffectImage->mX = ctx->mBlendX;
  1859. hiliteEffectImage->mY = ctx->mBlendY;
  1860. ImageData* shadowEffectImage = new ImageData();
  1861. shadowEffectImage->CreateNew(ctx->mBlendWidth, ctx->mBlendHeight);
  1862. shadowEffectImage->mX = ctx->mBlendX;
  1863. shadowEffectImage->mY = ctx->mBlendY;
  1864. // Pillow emboss takes two passes, the others only take one
  1865. for (int aPass = 0; aPass < 2; aPass++)
  1866. {
  1867. bool needsMorePasses = false;
  1868. Apply(aPass, mStyle, ctx->mLayerInfo, ctx->mLayerImage, hiliteEffectImage, shadowEffectImage);
  1869. if ((aPass == 0) && ((mStyle == 'Embs') || (mStyle == 'PlEb') || (mStyle == 'InrB') || (mStyle == 'PlEb'))) // Emboss or pillow emboss or inner
  1870. {
  1871. BlendImage(ctx->mInnerImage, hiliteEffectImage, 0, 0, (float) mHiliteOpacity / 100.0f, mHiliteMode);
  1872. BlendImage(ctx->mInnerImage, shadowEffectImage, 0, 0, (float) mShadowOpacity / 100.0f, mShadowMode);
  1873. needsMorePasses |= (mStyle == 'PlEb');
  1874. }
  1875. if ((mStyle == 'Embs') || (mStyle == 'OtrB') || ((mStyle == 'PlEb') && (aPass == 1))) // Emboss or pillow emboss or outer
  1876. {
  1877. BlendImage(ctx->mOuterImage, hiliteEffectImage, 0, 0, (float) mHiliteOpacity / 100.0f, mHiliteMode);
  1878. BlendImage(ctx->mOuterImage, shadowEffectImage, 0, 0, (float) mShadowOpacity / 100.0f, mShadowMode);
  1879. }
  1880. if (!needsMorePasses)
  1881. break;
  1882. }
  1883. delete shadowEffectImage;
  1884. delete hiliteEffectImage;
  1885. }
  1886. int ImageBevelEffect::GetNeededBorderSize()
  1887. {
  1888. return (int) mSize;
  1889. }
  1890. ///
  1891. void ImageSatinEffect::Init()
  1892. {
  1893. mContourData = CreateContourDataTable(&mContour, 1.0f);
  1894. }
  1895. void ImageSatinEffect::Apply(PSDLayerInfo* layerInfo, ImageData* imageData, ImageData* destImageData)
  1896. {
  1897. int sw = destImageData->mWidth;
  1898. int sh = destImageData->mHeight;
  1899. int w = sw;
  1900. int h = sh;
  1901. ImageData* newImage = destImageData;
  1902. int aSize = w*h;
  1903. ImageData* tempImage = new ImageData();
  1904. tempImage->CreateNew(w, h);
  1905. SoftBlurInit(imageData, tempImage, false);
  1906. SoftBlur(tempImage->mBits, w, h, GetSoftBlurRadius((float) mSize), 0);
  1907. float angle = (float) mAngle * BF_PI / 180.0f;
  1908. int ofsx = (int) (BFRound(cosf(angle) * (float) mDistance));
  1909. int ofsy = (int) (BFRound(-sinf(angle) * (float) mDistance));
  1910. uint32* tempData = tempImage->mBits;
  1911. for (int y = 0; y < h; y++)
  1912. {
  1913. for (int x = 0; x < w; x++)
  1914. {
  1915. int x1 = BFClamp(x + ofsx, 0, w - 1);
  1916. int y1 = BFClamp(y + ofsy, 0, h - 1);
  1917. int idx1 = (tempData[x1+y1*w] * (CONTOUR_DATA_SIZE - 1) / 255) / 256;
  1918. int val1 = mContourData[idx1] * 255 / (GRADIENT_DATA_SIZE - 1);
  1919. int x2 = BFClamp(x - ofsx, 0, w - 1);
  1920. int y2 = BFClamp(y - ofsy, 0, h - 1);
  1921. int idx2 = (tempData[x2+y2*w] * (CONTOUR_DATA_SIZE - 1) / 255) / 256;
  1922. int val2 = mContourData[idx2] * 255 / (GRADIENT_DATA_SIZE - 1);
  1923. uint32 aVal = (uint32) abs((int) val1 - (int) val2);
  1924. newImage->mBits[x+y*w] = aVal;
  1925. }
  1926. }
  1927. if ((mAntiAliased) && (!mContour.IsDefault()))
  1928. AntiAliasIndices(newImage->mBits, w, h);
  1929. if (mInvert)
  1930. {
  1931. for (int i = 0; i < aSize; i++)
  1932. newImage->mBits[i] = ((255 - newImage->mBits[i]) << 24) | (mColor & 0x00FFFFFF);
  1933. }
  1934. else
  1935. {
  1936. for (int i = 0; i < aSize; i++)
  1937. newImage->mBits[i] = (newImage->mBits[i] << 24) | (mColor & 0x00FFFFFF);
  1938. }
  1939. delete tempImage;
  1940. }
  1941. int ImageSatinEffect::GetMixType() // Default:Interior
  1942. {
  1943. return IMAGEMIX_INNER;
  1944. }
  1945. int ImageSatinEffect::GetNeededBorderSize()
  1946. {
  1947. return (int) mSize;
  1948. }
  1949. void ImageColorOverlayEffect::Apply(PSDLayerInfo* layerInfo, ImageData* imageData, ImageData* destImageData)
  1950. {
  1951. mColorFill.Apply(layerInfo, imageData, destImageData);
  1952. }
  1953. ///
  1954. void ImageColorFill::Apply(PSDLayerInfo* layerInfo, ImageData* imageData, ImageData* destImageData)
  1955. {
  1956. int w = destImageData->mWidth;
  1957. int h = destImageData->mHeight;
  1958. int aSize = w*h;
  1959. for (int i = 0; i < aSize; i++)
  1960. destImageData->mBits[i] = mColor;
  1961. }
  1962. ImageGradientFill::ImageGradientFill()
  1963. {
  1964. mGradientData = NULL;
  1965. }
  1966. ImageGradientFill::~ImageGradientFill()
  1967. {
  1968. delete mGradientData;
  1969. }
  1970. void ImageGradientFill::Apply(PSDLayerInfo* layerInfo, ImageData* imageData, ImageData* destImageData)
  1971. {
  1972. int w = destImageData->mWidth;
  1973. int h = destImageData->mHeight;
  1974. int iw = layerInfo->mWidth;
  1975. int ih = layerInfo->mHeight;
  1976. int ox = layerInfo->mX - destImageData->mX;
  1977. int oy = layerInfo->mY - destImageData->mY;
  1978. if (mGradientData == NULL)
  1979. {
  1980. mGradientData = CreateGradientDataTable(mColorGradient);
  1981. if (mReverse)
  1982. {
  1983. for (int i = 0; i < GRADIENT_DATA_SIZE / 2; i++)
  1984. {
  1985. int endIdx = (GRADIENT_DATA_SIZE - 1) - i;
  1986. uint32 swap = mGradientData[i];
  1987. mGradientData[i] = mGradientData[endIdx];
  1988. mGradientData[endIdx] = swap;
  1989. }
  1990. }
  1991. }
  1992. int minX = w;
  1993. int maxX = 0;
  1994. int minY = h;
  1995. int maxY = 0;
  1996. for (int y = 0; y < ih; y++)
  1997. {
  1998. uint32* checkBits = imageData->mBits + (y*iw);
  1999. bool hadPixel = false;
  2000. for (int x = 0; x < iw; x++)
  2001. {
  2002. if ((checkBits[x] >> 24) >= 128)
  2003. {
  2004. minX = std::min(minX, x + ox);
  2005. hadPixel = true;
  2006. break;
  2007. }
  2008. }
  2009. for (int x = iw - 1; x >= 0; x--)
  2010. {
  2011. if ((checkBits[x] >> 24) >= 128)
  2012. {
  2013. maxX = std::max(maxX, x + ox);
  2014. hadPixel = true;
  2015. break;
  2016. }
  2017. }
  2018. if (hadPixel)
  2019. {
  2020. minY = std::min(minY, y + oy);
  2021. maxY = std::max(maxY, y + oy);
  2022. }
  2023. }
  2024. int contentW = std::max(0, maxX - minX + 1);
  2025. int contentH = std::max(0, maxY - minY + 1);
  2026. float angleDeg = (float) mAngle;
  2027. // There seems to be some inaccuracy with photoshop with angles.
  2028. // There's a large gap between 180 degrees and 179 degrees than there should be, for example
  2029. // This is not yet simulated here. Offsets are also slightly effected.
  2030. float angle = BF_PI * angleDeg / 180.0f;
  2031. float matA = -cosf(angle);
  2032. float matB = sinf(angle);
  2033. float matC = sin(angle);
  2034. float matD = cos(angle);
  2035. float xOfs = 0;
  2036. float yOfs = 0;
  2037. float gradWidth;
  2038. float gradHeight;
  2039. float offsetScale = 1.0f;
  2040. float sizeBasis;
  2041. if (mAlignWithLayer)
  2042. {
  2043. gradWidth = (float) contentW;
  2044. gradHeight = (float) contentH;
  2045. xOfs = -(float)contentW/2 - minX;
  2046. yOfs = -(float)contentH/2 - minY;
  2047. }
  2048. else
  2049. {
  2050. gradWidth = (float) layerInfo->mPSDReader->mWidth;
  2051. gradHeight = (float) layerInfo->mPSDReader->mHeight;
  2052. xOfs = destImageData->mX - (float) gradWidth/2;
  2053. yOfs = destImageData->mY - (float) gradHeight/2;
  2054. }
  2055. xOfs -= ((float) mOffsetX / 100.0f) * gradWidth;
  2056. yOfs -= ((float) mOffsetY / 100.0f) * gradHeight;
  2057. float sizeBasisX = gradWidth / fabs(matA);
  2058. float sizeBasisY = gradHeight / fabs(matB);
  2059. sizeBasis = std::min(sizeBasisX, sizeBasisY);
  2060. float scale = (float) mScale / 100.0f;
  2061. float gradientScale = (float) (GRADIENT_DATA_SIZE - 1) / sizeBasis / scale * 2;
  2062. for (int y = 0; y < h; y++)
  2063. {
  2064. uint32* aBits = destImageData->mBits + (y*w);
  2065. for (int x = 0; x < w; x++)
  2066. {
  2067. float aX = (float) x + xOfs;
  2068. float aY = (float) y + yOfs;
  2069. float xRot = (aX * matA) + (aY * matB);
  2070. float yRot = (aX * matC) + (aY * matD);
  2071. int gradientIdx;
  2072. switch (mStyle)
  2073. {
  2074. case 'Lnr ':
  2075. gradientIdx = BFClamp((int) ((xRot/2) * gradientScale + GRADIENT_DATA_SIZE/2 + 0.5f), 0, GRADIENT_DATA_SIZE - 1);
  2076. break;
  2077. case 'Rdl ':
  2078. {
  2079. float dist = sqrt(xRot*xRot + yRot * yRot);
  2080. gradientIdx = (GRADIENT_DATA_SIZE - 1) - BFClamp((int) ((dist) * gradientScale + 0.5f), 0, GRADIENT_DATA_SIZE - 1);
  2081. }
  2082. break;
  2083. case 'Angl':
  2084. {
  2085. float ang = (atan2(yRot, xRot) / BF_PI / 2.0f) + 0.5f;
  2086. gradientIdx = BFClamp((int) ((ang) * (GRADIENT_DATA_SIZE - 1) + 0.5f), 0, GRADIENT_DATA_SIZE - 1);
  2087. }
  2088. break;
  2089. case 'Rflc':
  2090. gradientIdx = (GRADIENT_DATA_SIZE - 1) - BFClamp((int) (fabs(xRot) * gradientScale + 0.5f), 0, GRADIENT_DATA_SIZE - 1);
  2091. break;
  2092. case 'Dmnd':
  2093. gradientIdx = (GRADIENT_DATA_SIZE - 1) - BFClamp((int) ((fabs(xRot) + fabs(yRot)) * gradientScale + 0.5f), 0, GRADIENT_DATA_SIZE - 1);
  2094. break;
  2095. }
  2096. aBits[x] = mGradientData[gradientIdx];
  2097. }
  2098. }
  2099. }
  2100. void ImagePatternFill::Apply(PSDLayerInfo* layerInfo, ImageData* imageData, ImageData* destImageData)
  2101. {
  2102. PSDPattern* pattern = layerInfo->mPSDReader->mPSDPatternMap[mPatternName];
  2103. int mipLevel = 0;
  2104. int w = destImageData->mWidth;
  2105. int h = destImageData->mHeight;
  2106. float dU = 1.0f / (float) (mScale / 100.0f);
  2107. float dV = dU;
  2108. float virtPW = (float) pattern->mWidth;
  2109. float virtPH = (float) pattern->mHeight;
  2110. while ((dU > 1.0001f) && (pattern->mWidth >= 4) && (pattern->mHeight >= 4))
  2111. {
  2112. // Select next mip level
  2113. mipLevel++;
  2114. PSDPattern* aMip = pattern->GetNextMipLevel();
  2115. dU /= 2.0f;
  2116. dV /= 2.0f;
  2117. virtPW /= 2.0f;
  2118. virtPH /= 2.0f;
  2119. pattern = aMip;
  2120. }
  2121. int pw = pattern->mWidth;
  2122. int ph = pattern->mHeight;
  2123. float phaseX = (float) mPhaseX;
  2124. float phaseY = (float) mPhaseY;
  2125. if (mLinkWithLayer)
  2126. {
  2127. phaseX += (float) layerInfo->mRefX;
  2128. phaseY += (float) layerInfo->mRefY;
  2129. }
  2130. float startU = (float) (destImageData->mX - (int) BFRound((float) phaseX)) * dU;
  2131. while (startU < 0)
  2132. startU += virtPW;
  2133. float startV = (float) (destImageData->mY - (int) BFRound((float) phaseY)) * dV;
  2134. if (startV < 0)
  2135. startV += virtPH;
  2136. float aU = startU;
  2137. float aV = startV;
  2138. for (int y = 0; y < h; y++)
  2139. {
  2140. aU = startU;
  2141. uint32* aBits = destImageData->mBits + (y*w);
  2142. for (int x = 0; x < w; x++)
  2143. {
  2144. int u1 = ((int) aU) % pw;
  2145. int v1 = ((int) aV) % ph;
  2146. float ua = aU - (int) aU;
  2147. float va = aV - (int) aV;
  2148. int u2 = (u1 + 1) % pw;
  2149. int v2 = (v1 + 1) % ph;
  2150. uint32 aColor1 = pattern->mBits[u1+v1*pw];
  2151. uint32 aColor2 = pattern->mBits[u2+v1*pw];
  2152. uint32 color3 = pattern->mBits[u1+v2*pw];
  2153. uint32 color4 = pattern->mBits[u2+v2*pw];
  2154. uint32 a1 = (int) ((1.0f - ua) * (1.0f - va) * 256 + 0.5f);
  2155. uint32 a2 = (int) (( ua) * (1.0f - va) * 256 + 0.5f);
  2156. uint32 a3 = (int) ((1.0f - ua) * ( va) * 256 + 0.5f);
  2157. uint32 a4 = (int) (( ua) * ( va) * 256 + 0.5f);
  2158. *aBits =
  2159. (((((aColor1 & 0x00FF00FF) * a1) + ((aColor2 & 0x00FF00FF) * a2) +
  2160. ((color3 & 0x00FF00FF) * a3) + ((color4 & 0x00FF00FF) * a4)) >> 8) & 0x00FF00FF) |
  2161. (((((aColor1 >> 8) & 0x00FF00FF) * a1) + (((aColor2 >> 8) & 0x00FF00FF) * a2) +
  2162. (((color3 >> 8) & 0x00FF00FF) * a3) + (((color4 >> 8) & 0x00FF00FF) * a4)) & 0xFF00FF00);
  2163. //*aBits = aColor1;
  2164. aBits++;
  2165. aU += dU;
  2166. aU -= (int) (aU / virtPW) * virtPW;
  2167. }
  2168. aV += dV;
  2169. aV -= (int) (aV / virtPH) * virtPH;
  2170. }
  2171. }
  2172. void ImagePatternOverlayEffect::Apply(PSDLayerInfo* layerInfo, ImageData* imageData, ImageData* destImageData)
  2173. {
  2174. mPattern.Apply(layerInfo, imageData, destImageData);
  2175. }
  2176. void ImageGradientOverlayEffect::Apply(PSDLayerInfo* layerInfo, ImageData* imageData, ImageData* destImageData)
  2177. {
  2178. mGradientFill.Apply(layerInfo, imageData, destImageData);
  2179. }
  2180. void ImageStrokeEffect::Apply(PSDLayerInfo* layerInfo, ImageData* imageData, ImageData* destImageData)
  2181. {
  2182. int w = destImageData->mWidth;
  2183. int h = destImageData->mHeight;
  2184. int aSize = w*h;
  2185. ImageData* tempImage = new ImageData();
  2186. tempImage->CreateNew(w, h);
  2187. tempImage->mX = destImageData->mX;
  2188. tempImage->mY = destImageData->mY;
  2189. float aRadius = (float) mSize;
  2190. float blurRadius = aRadius;
  2191. if (mPosition == 'CtrF')
  2192. blurRadius /= 2;
  2193. uint32* aDest = tempImage->mBits;
  2194. ChamferedDistanceTransformInit(imageData, tempImage, false, 0);
  2195. ChamferedDistanceTransform(aDest, w, h);
  2196. uint32* tempBuffer = destImageData->mBits;//new uint32[w*h];
  2197. uint32* exterior = aDest;
  2198. uint32* anInterior = tempBuffer;
  2199. float rad = blurRadius;
  2200. int inf = (int) (blurRadius + 2) * 256;
  2201. for (int i = 0; i < aSize; i++)
  2202. {
  2203. float dist = aDest[i] / 256.0f;
  2204. dist -= 0.001f;
  2205. if (dist < 0)
  2206. {
  2207. exterior[i] = inf;
  2208. anInterior[i] = 0;
  2209. }
  2210. else if (dist < 1.0f)
  2211. {
  2212. exterior[i] = BFClamp((int) ((1.0f - dist) * 256.0f), 0, 0xFF);
  2213. anInterior[i] = (int) (dist * 256);
  2214. }
  2215. else
  2216. {
  2217. exterior[i] = 0;
  2218. anInterior[i] = (int) (dist * 256);
  2219. }
  2220. }
  2221. ChamferedDistanceTransform(exterior, w, h);
  2222. for (int i = 0; i < aSize; i++)
  2223. {
  2224. float distInterior = (anInterior[i] / 256.0f) - rad;
  2225. float distExterior = (exterior[i] / 256.0f) - rad;
  2226. float maxDist = std::max(distInterior, distExterior);
  2227. if (maxDist < 0)
  2228. aDest[i] = 0xFF000000;
  2229. else if (maxDist < 1.0f)
  2230. aDest[i] = ((int) (255.0f * (1.0f - maxDist))) << 24;
  2231. else
  2232. aDest[i] = 0;
  2233. }
  2234. tempImage->mX = destImageData->mX;
  2235. tempImage->mY = destImageData->mY;
  2236. if (mFillType == 'Ptrn')
  2237. mPatternFill.Apply(layerInfo, imageData, destImageData);
  2238. else if (mFillType == 'GrFl')
  2239. mGradientFill.Apply(layerInfo, imageData, destImageData);
  2240. else
  2241. mColorFill.Apply(layerInfo, imageData, destImageData);
  2242. for (int i = 0; i < aSize; i++)
  2243. {
  2244. uint32 srcAlpha = tempImage->mBits[i] >> 24;
  2245. uint32 destAlpha = destImageData->mBits[i] >> 24;
  2246. destImageData->mBits[i] = ((int) (srcAlpha * destAlpha / 255 + 0.5f) << 24) | (destImageData->mBits[i] & 0x00FFFFFF);
  2247. }
  2248. delete tempImage;
  2249. }
  2250. void ImageStrokeEffect::Apply(ImageEffectCtx* ctx)
  2251. {
  2252. // Try to find a bevel effect with a 'Stroke Emboss' style
  2253. ImageBevelEffect* bevelEffect = NULL;
  2254. for (int effectIdx = 0; effectIdx < (int) ctx->mLayerInfo->mImageEffects->mImageEffectVector.size(); effectIdx++)
  2255. {
  2256. BaseImageEffect* anEffect = ctx->mLayerInfo->mImageEffects->mImageEffectVector[effectIdx];
  2257. bevelEffect = dynamic_cast<ImageBevelEffect*>(anEffect);
  2258. if ((bevelEffect != NULL) && (bevelEffect->mStyle == 'stro'))
  2259. break;
  2260. bevelEffect = NULL;
  2261. }
  2262. if ((mOpacity == 100.0) && (bevelEffect == NULL))
  2263. {
  2264. BaseImageEffect::Apply(ctx);
  2265. return;
  2266. }
  2267. ImageData* effectImage = new ImageData();
  2268. effectImage->CreateNew(ctx->mBlendWidth, ctx->mBlendHeight);
  2269. effectImage->mX = ctx->mBlendX;
  2270. effectImage->mY = ctx->mBlendY;
  2271. Apply(ctx->mLayerInfo, ctx->mLayerImage, effectImage);
  2272. float opacity = (float) mOpacity / 100.0f;
  2273. ImageData* mixImage = CreateResizedImageUnion(ctx->mOrigImage, effectImage->mX, effectImage->mY, effectImage->mWidth, effectImage->mHeight);
  2274. BlendImage(mixImage, effectImage, effectImage->mX - mixImage->mX, effectImage->mY - mixImage->mY, opacity, mBlendMode, true);
  2275. if (bevelEffect != NULL)
  2276. {
  2277. ImageData* hiliteEffectImage = new ImageData();
  2278. hiliteEffectImage->CreateNew(ctx->mBlendWidth, ctx->mBlendHeight);
  2279. hiliteEffectImage->mX = ctx->mBlendX;
  2280. hiliteEffectImage->mY = ctx->mBlendY;
  2281. ImageData* shadowEffectImage = new ImageData();
  2282. shadowEffectImage->CreateNew(ctx->mBlendWidth, ctx->mBlendHeight);
  2283. shadowEffectImage->mX = ctx->mBlendX;
  2284. shadowEffectImage->mY = ctx->mBlendY;
  2285. int aStyle = 'Embs';
  2286. if (mPosition == 'OutF')
  2287. aStyle = 'OtrB';
  2288. else if (mPosition == 'InsF')
  2289. aStyle = 'InrB';
  2290. bevelEffect->Apply(0, aStyle, ctx->mLayerInfo, ctx->mLayerImage, hiliteEffectImage, shadowEffectImage);
  2291. BlendImage(mixImage, hiliteEffectImage, hiliteEffectImage->mX - mixImage->mX, hiliteEffectImage->mY - mixImage->mY, (float) bevelEffect->mHiliteOpacity / 100.0f, bevelEffect->mHiliteMode);
  2292. BlendImage(mixImage, shadowEffectImage, shadowEffectImage->mX - mixImage->mX, shadowEffectImage->mY - mixImage->mY, (float) bevelEffect->mShadowOpacity / 100.0f, bevelEffect->mShadowMode);
  2293. delete shadowEffectImage;
  2294. delete hiliteEffectImage;
  2295. }
  2296. int mixType = GetMixType();
  2297. if ((mixType == IMAGEMIX_INNER) || (mixType == IMAGEMIX_OVER))
  2298. BlendImagesTogether(ctx->mInnerImage, mixImage, effectImage);
  2299. if ((mixType == IMAGEMIX_OUTER) || (mixType == IMAGEMIX_OVER))
  2300. BlendImagesTogether(ctx->mOuterImage, mixImage, effectImage);
  2301. delete mixImage;
  2302. delete effectImage;
  2303. }
  2304. int ImageStrokeEffect::GetMixType() // Default:Interior
  2305. {
  2306. if (mPosition == 'OutF') // Outside
  2307. return IMAGEMIX_OUTER;
  2308. if (mPosition == 'InsF') // Inside
  2309. return IMAGEMIX_INNER;
  2310. if (mPosition == 'CtrF') // Inside
  2311. return IMAGEMIX_OVER;
  2312. return IMAGEMIX_INNER;
  2313. }
  2314. int ImageStrokeEffect::GetNeededBorderSize()
  2315. {
  2316. return (int)(mSize + 2.5);
  2317. }
  2318. bool ImageStrokeEffect::NeedsOrigBits(ImageEffects* effects)
  2319. {
  2320. ImageBevelEffect* bevelEffect = NULL;
  2321. for (int effectIdx = 0; effectIdx < (int) effects->mImageEffectVector.size(); effectIdx++)
  2322. {
  2323. BaseImageEffect* anEffect = effects->mImageEffectVector[effectIdx];
  2324. bevelEffect = dynamic_cast<ImageBevelEffect*>(anEffect);
  2325. if ((bevelEffect != NULL) && (bevelEffect->mStyle == 'stro'))
  2326. return true;
  2327. }
  2328. return mOpacity != 100.0;
  2329. }