KOffice – TDE office suite
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

kis_rgb_f32_colorspace.cc 32KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  1. /*
  2. * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
  3. * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
  4. * Copyright (c) 2005 Adrian Page <adrian@pagenet.plus.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor,
  19. * Boston, MA 02110-1301, USA.
  20. */
  21. #include <config.h>
  22. #include <limits.h>
  23. #include <stdlib.h>
  24. #include LCMS_HEADER
  25. #include <tqimage.h>
  26. #include <kdebug.h>
  27. #include <tdelocale.h>
  28. #include "kis_rgb_f32_colorspace.h"
  29. #include "kis_color_conversions.h"
  30. namespace {
  31. const TQ_INT32 MAX_CHANNEL_RGB = 3;
  32. const TQ_INT32 MAX_CHANNEL_RGBA = 4;
  33. }
  34. #include "kis_integer_maths.h"
  35. #ifndef HAVE_POWF
  36. #undef powf
  37. #define powf pow
  38. #endif
  39. #define FLOAT_MAX 1.0f //temp
  40. #define EPSILON 1e-6
  41. // FIXME: lcms doesn't support 32-bit float
  42. #define F32_LCMS_TYPE TYPE_BGRA_16
  43. // disable the lcms handling by setting profile=0
  44. KisRgbF32ColorSpace::KisRgbF32ColorSpace(KisColorSpaceFactoryRegistry * parent, KisProfile */*p*/) :
  45. KisF32BaseColorSpace(KisID("RGBAF32", i18n("RGB (32-bit float/channel)")), F32_LCMS_TYPE, icSigRgbData, parent, 0)
  46. {
  47. m_channels.push_back(new KisChannelInfo(i18n("Red"), i18n("R"), PIXEL_RED * sizeof(float), KisChannelInfo::COLOR, KisChannelInfo::FLOAT32, sizeof(float)));
  48. m_channels.push_back(new KisChannelInfo(i18n("Green"), i18n("G"), PIXEL_GREEN * sizeof(float), KisChannelInfo::COLOR, KisChannelInfo::FLOAT32, sizeof(float)));
  49. m_channels.push_back(new KisChannelInfo(i18n("Blue"), i18n("B"), PIXEL_BLUE * sizeof(float), KisChannelInfo::COLOR, KisChannelInfo::FLOAT32, sizeof(float)));
  50. m_channels.push_back(new KisChannelInfo(i18n("Alpha"), i18n("A"), PIXEL_ALPHA * sizeof(float), KisChannelInfo::ALPHA, KisChannelInfo::FLOAT32, sizeof(float)));
  51. m_alphaPos = PIXEL_ALPHA * sizeof(float);
  52. }
  53. KisRgbF32ColorSpace::~KisRgbF32ColorSpace()
  54. {
  55. }
  56. void KisRgbF32ColorSpace::setPixel(TQ_UINT8 *dst, float red, float green, float blue, float alpha) const
  57. {
  58. Pixel *dstPixel = reinterpret_cast<Pixel *>(dst);
  59. dstPixel->red = red;
  60. dstPixel->green = green;
  61. dstPixel->blue = blue;
  62. dstPixel->alpha = alpha;
  63. }
  64. void KisRgbF32ColorSpace::getPixel(const TQ_UINT8 *src, float *red, float *green, float *blue, float *alpha) const
  65. {
  66. const Pixel *srcPixel = reinterpret_cast<const Pixel *>(src);
  67. *red = srcPixel->red;
  68. *green = srcPixel->green;
  69. *blue = srcPixel->blue;
  70. *alpha = srcPixel->alpha;
  71. }
  72. void KisRgbF32ColorSpace::fromTQColor(const TQColor& c, TQ_UINT8 *dstU8, KisProfile * /*profile*/)
  73. {
  74. Pixel *dst = reinterpret_cast<Pixel *>(dstU8);
  75. dst->red = UINT8_TO_FLOAT(c.red());
  76. dst->green = UINT8_TO_FLOAT(c.green());
  77. dst->blue = UINT8_TO_FLOAT(c.blue());
  78. }
  79. void KisRgbF32ColorSpace::fromTQColor(const TQColor& c, TQ_UINT8 opacity, TQ_UINT8 *dstU8, KisProfile * /*profile*/)
  80. {
  81. Pixel *dst = reinterpret_cast<Pixel *>(dstU8);
  82. dst->red = UINT8_TO_FLOAT(c.red());
  83. dst->green = UINT8_TO_FLOAT(c.green());
  84. dst->blue = UINT8_TO_FLOAT(c.blue());
  85. dst->alpha = UINT8_TO_FLOAT(opacity);
  86. }
  87. void KisRgbF32ColorSpace::toTQColor(const TQ_UINT8 *srcU8, TQColor *c, KisProfile * /*profile*/)
  88. {
  89. const Pixel *src = reinterpret_cast<const Pixel *>(srcU8);
  90. c->setRgb(FLOAT_TO_UINT8(src->red), FLOAT_TO_UINT8(src->green), FLOAT_TO_UINT8(src->blue));
  91. }
  92. void KisRgbF32ColorSpace::toTQColor(const TQ_UINT8 *srcU8, TQColor *c, TQ_UINT8 *opacity, KisProfile * /*profile*/)
  93. {
  94. const Pixel *src = reinterpret_cast<const Pixel *>(srcU8);
  95. c->setRgb(FLOAT_TO_UINT8(src->red), FLOAT_TO_UINT8(src->green), FLOAT_TO_UINT8(src->blue));
  96. *opacity = FLOAT_TO_UINT8(src->alpha);
  97. }
  98. TQ_UINT8 KisRgbF32ColorSpace::difference(const TQ_UINT8 *src1U8, const TQ_UINT8 *src2U8)
  99. {
  100. const Pixel *src1 = reinterpret_cast<const Pixel *>(src1U8);
  101. const Pixel *src2 = reinterpret_cast<const Pixel *>(src2U8);
  102. return FLOAT_TO_UINT8(TQMAX(TQABS(src2->red - src1->red),
  103. TQMAX(TQABS(src2->green - src1->green),
  104. TQABS(src2->blue - src1->blue))));
  105. }
  106. void KisRgbF32ColorSpace::mixColors(const TQ_UINT8 **colors, const TQ_UINT8 *weights, TQ_UINT32 nColors, TQ_UINT8 *dst) const
  107. {
  108. float totalRed = 0, totalGreen = 0, totalBlue = 0, newAlpha = 0;
  109. while (nColors--)
  110. {
  111. const Pixel *pixel = reinterpret_cast<const Pixel *>(*colors);
  112. float alpha = pixel->alpha;
  113. float alphaTimesWeight = alpha * UINT8_TO_FLOAT(*weights);
  114. totalRed += pixel->red * alphaTimesWeight;
  115. totalGreen += pixel->green * alphaTimesWeight;
  116. totalBlue += pixel->blue * alphaTimesWeight;
  117. newAlpha += alphaTimesWeight;
  118. weights++;
  119. colors++;
  120. }
  121. Q_ASSERT(newAlpha <= F32_OPACITY_OPAQUE);
  122. Pixel *dstPixel = reinterpret_cast<Pixel *>(dst);
  123. dstPixel->alpha = newAlpha;
  124. if (newAlpha > EPSILON) {
  125. totalRed = totalRed / newAlpha;
  126. totalGreen = totalGreen / newAlpha;
  127. totalBlue = totalBlue / newAlpha;
  128. }
  129. dstPixel->red = totalRed;
  130. dstPixel->green = totalGreen;
  131. dstPixel->blue = totalBlue;
  132. }
  133. void KisRgbF32ColorSpace::convolveColors(TQ_UINT8** colors, TQ_INT32 * kernelValues, KisChannelInfo::enumChannelFlags channelFlags, TQ_UINT8 *dst, TQ_INT32 factor, TQ_INT32 offset, TQ_INT32 nColors) const
  134. {
  135. float totalRed = 0, totalGreen = 0, totalBlue = 0, totalAlpha = 0;
  136. while (nColors--)
  137. {
  138. const Pixel * pixel = reinterpret_cast<const Pixel *>( *colors );
  139. float weight = *kernelValues;
  140. if (weight != 0) {
  141. totalRed += pixel->red * weight;
  142. totalGreen += pixel->green * weight;
  143. totalBlue += pixel->blue * weight;
  144. totalAlpha += pixel->alpha * weight;
  145. }
  146. colors++;
  147. kernelValues++;
  148. }
  149. Pixel * p = reinterpret_cast< Pixel *>( dst );
  150. if (channelFlags & KisChannelInfo::FLAG_COLOR) {
  151. p->red = CLAMP( ( totalRed / factor) + offset, 0, FLOAT_MAX);
  152. p->green = CLAMP( ( totalGreen / factor) + offset, 0, FLOAT_MAX);
  153. p->blue = CLAMP( ( totalBlue / factor) + offset, 0, FLOAT_MAX);
  154. }
  155. if (channelFlags & KisChannelInfo::FLAG_ALPHA) {
  156. p->alpha = CLAMP((totalAlpha/ factor) + offset, 0, FLOAT_MAX);
  157. }
  158. }
  159. void KisRgbF32ColorSpace::invertColor(TQ_UINT8 * src, TQ_INT32 nPixels)
  160. {
  161. TQ_UINT32 psize = pixelSize();
  162. while (nPixels--)
  163. {
  164. Pixel * p = reinterpret_cast< Pixel *>( src );
  165. p->red = FLOAT_MAX - p->red;
  166. p->green = FLOAT_MAX - p->green;
  167. p->blue = FLOAT_MAX - p->blue;
  168. src += psize;
  169. }
  170. }
  171. TQ_UINT8 KisRgbF32ColorSpace::intensity8(const TQ_UINT8 * src) const
  172. {
  173. const Pixel * p = reinterpret_cast<const Pixel *>( src );
  174. return FLOAT_TO_UINT8((p->red * 0.30 + p->green * 0.59 + p->blue * 0.11) + 0.5);
  175. }
  176. TQValueVector<KisChannelInfo *> KisRgbF32ColorSpace::channels() const
  177. {
  178. return m_channels;
  179. }
  180. TQ_UINT32 KisRgbF32ColorSpace::nChannels() const
  181. {
  182. return MAX_CHANNEL_RGBA;
  183. }
  184. TQ_UINT32 KisRgbF32ColorSpace::nColorChannels() const
  185. {
  186. return MAX_CHANNEL_RGB;
  187. }
  188. TQ_UINT32 KisRgbF32ColorSpace::pixelSize() const
  189. {
  190. return MAX_CHANNEL_RGBA * sizeof(float);
  191. }
  192. TQ_UINT8 convertToDisplay(float value, float exposureFactor, float gamma)
  193. {
  194. //value *= pow(2, exposure + 2.47393);
  195. value *= exposureFactor;
  196. value = powf(value, gamma);
  197. // scale middle gray to the target framebuffer value
  198. value *= 84.66f;
  199. int valueInt = (int)(value + 0.5);
  200. return CLAMP(valueInt, 0, 255);
  201. }
  202. TQImage KisRgbF32ColorSpace::convertToTQImage(const TQ_UINT8 *dataU8, TQ_INT32 width, TQ_INT32 height,
  203. KisProfile * /*dstProfile*/,
  204. TQ_INT32 /*renderingIntent*/, float exposure)
  205. {
  206. const float *data = reinterpret_cast<const float *>(dataU8);
  207. TQImage img = TQImage(width, height, 32, 0, TQImage::LittleEndian);
  208. img.setAlphaBuffer(true);
  209. TQ_INT32 i = 0;
  210. uchar *j = img.bits();
  211. // XXX: For now assume gamma 2.2.
  212. float gamma = 1 / 2.2;
  213. float exposureFactor = powf(2, exposure + 2.47393);
  214. while ( i < width * height * MAX_CHANNEL_RGBA) {
  215. *( j + 3) = FLOAT_TO_UINT8(*( data + i + PIXEL_ALPHA ));
  216. *( j + 2 ) = convertToDisplay(*( data + i + PIXEL_RED ), exposureFactor, gamma);
  217. *( j + 1 ) = convertToDisplay(*( data + i + PIXEL_GREEN ), exposureFactor, gamma);
  218. *( j + 0 ) = convertToDisplay(*( data + i + PIXEL_BLUE ), exposureFactor, gamma);
  219. i += MAX_CHANNEL_RGBA;
  220. j += MAX_CHANNEL_RGBA;
  221. }
  222. /*
  223. if (srcProfile != 0 && dstProfile != 0) {
  224. convertPixelsTo(img.bits(), srcProfile,
  225. img.bits(), this, dstProfile,
  226. width * height, renderingIntent);
  227. }
  228. */
  229. return img;
  230. }
  231. void KisRgbF32ColorSpace::compositeOver(TQ_UINT8 *dstRowStart, TQ_INT32 dstRowStride, const TQ_UINT8 *srcRowStart, TQ_INT32 srcRowStride, const TQ_UINT8 *maskRowStart, TQ_INT32 maskRowStride, TQ_INT32 rows, TQ_INT32 numColumns, float opacity)
  232. {
  233. while (rows > 0) {
  234. const float *src = reinterpret_cast<const float *>(srcRowStart);
  235. float *dst = reinterpret_cast<float *>(dstRowStart);
  236. const TQ_UINT8 *mask = maskRowStart;
  237. TQ_INT32 columns = numColumns;
  238. while (columns > 0) {
  239. float srcAlpha = src[PIXEL_ALPHA];
  240. // apply the alphamask
  241. if (mask != 0) {
  242. TQ_UINT8 U8_mask = *mask;
  243. if (U8_mask != OPACITY_OPAQUE) {
  244. srcAlpha *= UINT8_TO_FLOAT(U8_mask);
  245. }
  246. mask++;
  247. }
  248. if (srcAlpha > F32_OPACITY_TRANSPARENT + EPSILON) {
  249. if (opacity < F32_OPACITY_OPAQUE - EPSILON) {
  250. srcAlpha *= opacity;
  251. }
  252. if (srcAlpha > F32_OPACITY_OPAQUE - EPSILON) {
  253. memcpy(dst, src, MAX_CHANNEL_RGBA * sizeof(float));
  254. } else {
  255. float dstAlpha = dst[PIXEL_ALPHA];
  256. float srcBlend;
  257. if (dstAlpha > F32_OPACITY_OPAQUE - EPSILON) {
  258. srcBlend = srcAlpha;
  259. } else {
  260. float newAlpha = dstAlpha + (F32_OPACITY_OPAQUE - dstAlpha) * srcAlpha;
  261. dst[PIXEL_ALPHA] = newAlpha;
  262. if (newAlpha > EPSILON) {
  263. srcBlend = srcAlpha / newAlpha;
  264. } else {
  265. srcBlend = srcAlpha;
  266. }
  267. }
  268. if (srcBlend > F32_OPACITY_OPAQUE - EPSILON) {
  269. memcpy(dst, src, MAX_CHANNEL_RGB * sizeof(float));
  270. } else {
  271. dst[PIXEL_RED] = FLOAT_BLEND(src[PIXEL_RED], dst[PIXEL_RED], srcBlend);
  272. dst[PIXEL_GREEN] = FLOAT_BLEND(src[PIXEL_GREEN], dst[PIXEL_GREEN], srcBlend);
  273. dst[PIXEL_BLUE] = FLOAT_BLEND(src[PIXEL_BLUE], dst[PIXEL_BLUE], srcBlend);
  274. }
  275. }
  276. }
  277. columns--;
  278. src += MAX_CHANNEL_RGBA;
  279. dst += MAX_CHANNEL_RGBA;
  280. }
  281. rows--;
  282. srcRowStart += srcRowStride;
  283. dstRowStart += dstRowStride;
  284. if(maskRowStart) {
  285. maskRowStart += maskRowStride;
  286. }
  287. }
  288. }
  289. #define COMMON_COMPOSITE_OP_PROLOG() \
  290. while (rows > 0) { \
  291. \
  292. const float *src = reinterpret_cast<const float *>(srcRowStart); \
  293. float *dst = reinterpret_cast<float *>(dstRowStart); \
  294. TQ_INT32 columns = numColumns; \
  295. const TQ_UINT8 *mask = maskRowStart; \
  296. \
  297. while (columns > 0) { \
  298. \
  299. float srcAlpha = src[PIXEL_ALPHA]; \
  300. float dstAlpha = dst[PIXEL_ALPHA]; \
  301. \
  302. srcAlpha = TQMIN(srcAlpha, dstAlpha); \
  303. \
  304. if (mask != 0) { \
  305. TQ_UINT8 U8_mask = *mask; \
  306. \
  307. if (U8_mask != OPACITY_OPAQUE) { \
  308. srcAlpha *= UINT8_TO_FLOAT(U8_mask); \
  309. } \
  310. mask++; \
  311. } \
  312. \
  313. if (srcAlpha > F32_OPACITY_TRANSPARENT + EPSILON) { \
  314. \
  315. if (opacity < F32_OPACITY_OPAQUE - EPSILON) { \
  316. srcAlpha *= opacity; \
  317. } \
  318. \
  319. float srcBlend; \
  320. \
  321. if (dstAlpha > F32_OPACITY_OPAQUE - EPSILON) { \
  322. srcBlend = srcAlpha; \
  323. } else { \
  324. float newAlpha = dstAlpha + (F32_OPACITY_OPAQUE - dstAlpha) * srcAlpha; \
  325. dst[PIXEL_ALPHA] = newAlpha; \
  326. \
  327. if (newAlpha > EPSILON) { \
  328. srcBlend = srcAlpha / newAlpha; \
  329. } else { \
  330. srcBlend = srcAlpha; \
  331. } \
  332. }
  333. #define COMMON_COMPOSITE_OP_EPILOG() \
  334. } \
  335. \
  336. columns--; \
  337. src += MAX_CHANNEL_RGBA; \
  338. dst += MAX_CHANNEL_RGBA; \
  339. } \
  340. \
  341. rows--; \
  342. srcRowStart += srcRowStride; \
  343. dstRowStart += dstRowStride; \
  344. if(maskRowStart) { \
  345. maskRowStart += maskRowStride; \
  346. } \
  347. }
  348. void KisRgbF32ColorSpace::compositeMultiply(TQ_UINT8 *dstRowStart, TQ_INT32 dstRowStride, const TQ_UINT8 *srcRowStart, TQ_INT32 srcRowStride, const TQ_UINT8 *maskRowStart, TQ_INT32 maskRowStride, TQ_INT32 rows, TQ_INT32 numColumns, float opacity)
  349. {
  350. COMMON_COMPOSITE_OP_PROLOG();
  351. {
  352. float srcColor = src[PIXEL_RED];
  353. float dstColor = dst[PIXEL_RED];
  354. srcColor = srcColor * dstColor;
  355. dst[PIXEL_RED] = FLOAT_BLEND(srcColor, dstColor, srcBlend);
  356. srcColor = src[PIXEL_GREEN];
  357. dstColor = dst[PIXEL_GREEN];
  358. srcColor = srcColor * dstColor;
  359. dst[PIXEL_GREEN] = FLOAT_BLEND(srcColor, dstColor, srcBlend);
  360. srcColor = src[PIXEL_BLUE];
  361. dstColor = dst[PIXEL_BLUE];
  362. srcColor = srcColor * dstColor;
  363. dst[PIXEL_BLUE] = FLOAT_BLEND(srcColor, dstColor, srcBlend);
  364. }
  365. COMMON_COMPOSITE_OP_EPILOG();
  366. }
  367. void KisRgbF32ColorSpace::compositeDivide(TQ_UINT8 *dstRowStart, TQ_INT32 dstRowStride, const TQ_UINT8 *srcRowStart, TQ_INT32 srcRowStride, const TQ_UINT8 *maskRowStart, TQ_INT32 maskRowStride, TQ_INT32 rows, TQ_INT32 numColumns, float opacity)
  368. {
  369. COMMON_COMPOSITE_OP_PROLOG();
  370. {
  371. for (int channel = 0; channel < MAX_CHANNEL_RGB; channel++) {
  372. float srcColor = src[channel];
  373. float dstColor = dst[channel];
  374. srcColor = TQMIN(dstColor / (srcColor + EPSILON), FLOAT_MAX);
  375. float newColor = FLOAT_BLEND(srcColor, dstColor, srcBlend);
  376. dst[channel] = newColor;
  377. }
  378. }
  379. COMMON_COMPOSITE_OP_EPILOG();
  380. }
  381. void KisRgbF32ColorSpace::compositeScreen(TQ_UINT8 *dstRowStart, TQ_INT32 dstRowStride, const TQ_UINT8 *srcRowStart, TQ_INT32 srcRowStride, const TQ_UINT8 *maskRowStart, TQ_INT32 maskRowStride, TQ_INT32 rows, TQ_INT32 numColumns, float opacity)
  382. {
  383. COMMON_COMPOSITE_OP_PROLOG();
  384. {
  385. for (int channel = 0; channel < MAX_CHANNEL_RGB; channel++) {
  386. float srcColor = src[channel];
  387. float dstColor = dst[channel];
  388. srcColor = FLOAT_MAX - ((FLOAT_MAX - dstColor) * (FLOAT_MAX - srcColor));
  389. float newColor = FLOAT_BLEND(srcColor, dstColor, srcBlend);
  390. dst[channel] = newColor;
  391. }
  392. }
  393. COMMON_COMPOSITE_OP_EPILOG();
  394. }
  395. void KisRgbF32ColorSpace::compositeOverlay(TQ_UINT8 *dstRowStart, TQ_INT32 dstRowStride, const TQ_UINT8 *srcRowStart, TQ_INT32 srcRowStride, const TQ_UINT8 *maskRowStart, TQ_INT32 maskRowStride, TQ_INT32 rows, TQ_INT32 numColumns, float opacity)
  396. {
  397. COMMON_COMPOSITE_OP_PROLOG();
  398. {
  399. for (int channel = 0; channel < MAX_CHANNEL_RGB; channel++) {
  400. float srcColor = src[channel];
  401. float dstColor = dst[channel];
  402. srcColor = dstColor * (dstColor + 2 * (srcColor * (FLOAT_MAX - dstColor)));
  403. float newColor = FLOAT_BLEND(srcColor, dstColor, srcBlend);
  404. dst[channel] = newColor;
  405. }
  406. }
  407. COMMON_COMPOSITE_OP_EPILOG();
  408. }
  409. void KisRgbF32ColorSpace::compositeDodge(TQ_UINT8 *dstRowStart, TQ_INT32 dstRowStride, const TQ_UINT8 *srcRowStart, TQ_INT32 srcRowStride, const TQ_UINT8 *maskRowStart, TQ_INT32 maskRowStride, TQ_INT32 rows, TQ_INT32 numColumns, float opacity)
  410. {
  411. COMMON_COMPOSITE_OP_PROLOG();
  412. {
  413. for (int channel = 0; channel < MAX_CHANNEL_RGB; channel++) {
  414. float srcColor = src[channel];
  415. float dstColor = dst[channel];
  416. srcColor = TQMIN(dstColor / (FLOAT_MAX + EPSILON - srcColor), FLOAT_MAX);
  417. float newColor = FLOAT_BLEND(srcColor, dstColor, srcBlend);
  418. dst[channel] = newColor;
  419. }
  420. }
  421. COMMON_COMPOSITE_OP_EPILOG();
  422. }
  423. void KisRgbF32ColorSpace::compositeBurn(TQ_UINT8 *dstRowStart, TQ_INT32 dstRowStride, const TQ_UINT8 *srcRowStart, TQ_INT32 srcRowStride, const TQ_UINT8 *maskRowStart, TQ_INT32 maskRowStride, TQ_INT32 rows, TQ_INT32 numColumns, float opacity)
  424. {
  425. COMMON_COMPOSITE_OP_PROLOG();
  426. {
  427. for (int channel = 0; channel < MAX_CHANNEL_RGB; channel++) {
  428. float srcColor = src[channel];
  429. float dstColor = dst[channel];
  430. srcColor = TQMIN((FLOAT_MAX - dstColor) / (srcColor + EPSILON), FLOAT_MAX);
  431. srcColor = CLAMP(FLOAT_MAX - srcColor, 0, FLOAT_MAX);
  432. float newColor = FLOAT_BLEND(srcColor, dstColor, srcBlend);
  433. dst[channel] = newColor;
  434. }
  435. }
  436. COMMON_COMPOSITE_OP_EPILOG();
  437. }
  438. void KisRgbF32ColorSpace::compositeDarken(TQ_UINT8 *dstRowStart, TQ_INT32 dstRowStride, const TQ_UINT8 *srcRowStart, TQ_INT32 srcRowStride, const TQ_UINT8 *maskRowStart, TQ_INT32 maskRowStride, TQ_INT32 rows, TQ_INT32 numColumns, float opacity)
  439. {
  440. COMMON_COMPOSITE_OP_PROLOG();
  441. {
  442. for (int channel = 0; channel < MAX_CHANNEL_RGB; channel++) {
  443. float srcColor = src[channel];
  444. float dstColor = dst[channel];
  445. srcColor = TQMIN(srcColor, dstColor);
  446. float newColor = FLOAT_BLEND(srcColor, dstColor, srcBlend);
  447. dst[channel] = newColor;
  448. }
  449. }
  450. COMMON_COMPOSITE_OP_EPILOG();
  451. }
  452. void KisRgbF32ColorSpace::compositeLighten(TQ_UINT8 *dstRowStart, TQ_INT32 dstRowStride, const TQ_UINT8 *srcRowStart, TQ_INT32 srcRowStride, const TQ_UINT8 *maskRowStart, TQ_INT32 maskRowStride, TQ_INT32 rows, TQ_INT32 numColumns, float opacity)
  453. {
  454. COMMON_COMPOSITE_OP_PROLOG();
  455. {
  456. for (int channel = 0; channel < MAX_CHANNEL_RGB; channel++) {
  457. float srcColor = src[channel];
  458. float dstColor = dst[channel];
  459. srcColor = TQMAX(srcColor, dstColor);
  460. float newColor = FLOAT_BLEND(srcColor, dstColor, srcBlend);
  461. dst[channel] = newColor;
  462. }
  463. }
  464. COMMON_COMPOSITE_OP_EPILOG();
  465. }
  466. void KisRgbF32ColorSpace::compositeHue(TQ_UINT8 *dstRowStart, TQ_INT32 dstRowStride, const TQ_UINT8 *srcRowStart, TQ_INT32 srcRowStride, const TQ_UINT8 *maskRowStart, TQ_INT32 maskRowStride, TQ_INT32 rows, TQ_INT32 numColumns, float opacity)
  467. {
  468. COMMON_COMPOSITE_OP_PROLOG();
  469. {
  470. float srcRed = src[PIXEL_RED];
  471. float srcGreen = src[PIXEL_GREEN];
  472. float srcBlue = src[PIXEL_BLUE];
  473. float dstRed = dst[PIXEL_RED];
  474. float dstGreen = dst[PIXEL_GREEN];
  475. float dstBlue = dst[PIXEL_BLUE];
  476. float srcHue;
  477. float srcSaturation;
  478. float srcValue;
  479. float dstHue;
  480. float dstSaturation;
  481. float dstValue;
  482. RGBToHSV(srcRed, srcGreen, srcBlue, &srcHue, &srcSaturation, &srcValue);
  483. RGBToHSV(dstRed, dstGreen, dstBlue, &dstHue, &dstSaturation, &dstValue);
  484. HSVToRGB(srcHue, dstSaturation, dstValue, &srcRed, &srcGreen, &srcBlue);
  485. dst[PIXEL_RED] = FLOAT_BLEND(srcRed, dstRed, srcBlend);
  486. dst[PIXEL_GREEN] = FLOAT_BLEND(srcGreen, dstGreen, srcBlend);
  487. dst[PIXEL_BLUE] = FLOAT_BLEND(srcBlue, dstBlue, srcBlend);
  488. }
  489. COMMON_COMPOSITE_OP_EPILOG();
  490. }
  491. void KisRgbF32ColorSpace::compositeSaturation(TQ_UINT8 *dstRowStart, TQ_INT32 dstRowStride, const TQ_UINT8 *srcRowStart, TQ_INT32 srcRowStride, const TQ_UINT8 *maskRowStart, TQ_INT32 maskRowStride, TQ_INT32 rows, TQ_INT32 numColumns, float opacity)
  492. {
  493. COMMON_COMPOSITE_OP_PROLOG();
  494. {
  495. float srcRed = src[PIXEL_RED];
  496. float srcGreen = src[PIXEL_GREEN];
  497. float srcBlue = src[PIXEL_BLUE];
  498. float dstRed = dst[PIXEL_RED];
  499. float dstGreen = dst[PIXEL_GREEN];
  500. float dstBlue = dst[PIXEL_BLUE];
  501. float srcHue;
  502. float srcSaturation;
  503. float srcValue;
  504. float dstHue;
  505. float dstSaturation;
  506. float dstValue;
  507. RGBToHSV(srcRed, srcGreen, srcBlue, &srcHue, &srcSaturation, &srcValue);
  508. RGBToHSV(dstRed, dstGreen, dstBlue, &dstHue, &dstSaturation, &dstValue);
  509. HSVToRGB(dstHue, srcSaturation, dstValue, &srcRed, &srcGreen, &srcBlue);
  510. dst[PIXEL_RED] = FLOAT_BLEND(srcRed, dstRed, srcBlend);
  511. dst[PIXEL_GREEN] = FLOAT_BLEND(srcGreen, dstGreen, srcBlend);
  512. dst[PIXEL_BLUE] = FLOAT_BLEND(srcBlue, dstBlue, srcBlend);
  513. }
  514. COMMON_COMPOSITE_OP_EPILOG();
  515. }
  516. void KisRgbF32ColorSpace::compositeValue(TQ_UINT8 *dstRowStart, TQ_INT32 dstRowStride, const TQ_UINT8 *srcRowStart, TQ_INT32 srcRowStride, const TQ_UINT8 *maskRowStart, TQ_INT32 maskRowStride, TQ_INT32 rows, TQ_INT32 numColumns, float opacity)
  517. {
  518. COMMON_COMPOSITE_OP_PROLOG();
  519. {
  520. float srcRed = src[PIXEL_RED];
  521. float srcGreen = src[PIXEL_GREEN];
  522. float srcBlue = src[PIXEL_BLUE];
  523. float dstRed = dst[PIXEL_RED];
  524. float dstGreen = dst[PIXEL_GREEN];
  525. float dstBlue = dst[PIXEL_BLUE];
  526. float srcHue;
  527. float srcSaturation;
  528. float srcValue;
  529. float dstHue;
  530. float dstSaturation;
  531. float dstValue;
  532. RGBToHSV(srcRed, srcGreen, srcBlue, &srcHue, &srcSaturation, &srcValue);
  533. RGBToHSV(dstRed, dstGreen, dstBlue, &dstHue, &dstSaturation, &dstValue);
  534. HSVToRGB(dstHue, dstSaturation, srcValue, &srcRed, &srcGreen, &srcBlue);
  535. dst[PIXEL_RED] = FLOAT_BLEND(srcRed, dstRed, srcBlend);
  536. dst[PIXEL_GREEN] = FLOAT_BLEND(srcGreen, dstGreen, srcBlend);
  537. dst[PIXEL_BLUE] = FLOAT_BLEND(srcBlue, dstBlue, srcBlend);
  538. }
  539. COMMON_COMPOSITE_OP_EPILOG();
  540. }
  541. void KisRgbF32ColorSpace::compositeColor(TQ_UINT8 *dstRowStart, TQ_INT32 dstRowStride, const TQ_UINT8 *srcRowStart, TQ_INT32 srcRowStride, const TQ_UINT8 *maskRowStart, TQ_INT32 maskRowStride, TQ_INT32 rows, TQ_INT32 numColumns, float opacity)
  542. {
  543. COMMON_COMPOSITE_OP_PROLOG();
  544. {
  545. float srcRed = src[PIXEL_RED];
  546. float srcGreen = src[PIXEL_GREEN];
  547. float srcBlue = src[PIXEL_BLUE];
  548. float dstRed = dst[PIXEL_RED];
  549. float dstGreen = dst[PIXEL_GREEN];
  550. float dstBlue = dst[PIXEL_BLUE];
  551. float srcHue;
  552. float srcSaturation;
  553. float srcLightness;
  554. float dstHue;
  555. float dstSaturation;
  556. float dstLightness;
  557. RGBToHSL(srcRed, srcGreen, srcBlue, &srcHue, &srcSaturation, &srcLightness);
  558. RGBToHSL(dstRed, dstGreen, dstBlue, &dstHue, &dstSaturation, &dstLightness);
  559. HSLToRGB(srcHue, srcSaturation, dstLightness, &srcRed, &srcGreen, &srcBlue);
  560. dst[PIXEL_RED] = FLOAT_BLEND(srcRed, dstRed, srcBlend);
  561. dst[PIXEL_GREEN] = FLOAT_BLEND(srcGreen, dstGreen, srcBlend);
  562. dst[PIXEL_BLUE] = FLOAT_BLEND(srcBlue, dstBlue, srcBlend);
  563. }
  564. COMMON_COMPOSITE_OP_EPILOG();
  565. }
  566. void KisRgbF32ColorSpace::compositeErase(TQ_UINT8 *dst,
  567. TQ_INT32 dstRowSize,
  568. const TQ_UINT8 *src,
  569. TQ_INT32 srcRowSize,
  570. const TQ_UINT8 *srcAlphaMask,
  571. TQ_INT32 maskRowStride,
  572. TQ_INT32 rows,
  573. TQ_INT32 cols,
  574. float /*opacity*/)
  575. {
  576. while (rows-- > 0)
  577. {
  578. const Pixel *s = reinterpret_cast<const Pixel *>(src);
  579. Pixel *d = reinterpret_cast<Pixel *>(dst);
  580. const TQ_UINT8 *mask = srcAlphaMask;
  581. for (TQ_INT32 i = cols; i > 0; i--, s++, d++)
  582. {
  583. float srcAlpha = s->alpha;
  584. // apply the alphamask
  585. if (mask != 0) {
  586. TQ_UINT8 U8_mask = *mask;
  587. if (U8_mask != OPACITY_OPAQUE) {
  588. srcAlpha = FLOAT_BLEND(srcAlpha, F32_OPACITY_OPAQUE, UINT8_TO_FLOAT(U8_mask));
  589. }
  590. mask++;
  591. }
  592. d->alpha = srcAlpha * d->alpha;
  593. }
  594. dst += dstRowSize;
  595. src += srcRowSize;
  596. if(srcAlphaMask) {
  597. srcAlphaMask += maskRowStride;
  598. }
  599. }
  600. }
  601. void KisRgbF32ColorSpace::bitBlt(TQ_UINT8 *dst,
  602. TQ_INT32 dstRowStride,
  603. const TQ_UINT8 *src,
  604. TQ_INT32 srcRowStride,
  605. const TQ_UINT8 *mask,
  606. TQ_INT32 maskRowStride,
  607. TQ_UINT8 U8_opacity,
  608. TQ_INT32 rows,
  609. TQ_INT32 cols,
  610. const KisCompositeOp& op)
  611. {
  612. float opacity = UINT8_TO_FLOAT(U8_opacity);
  613. switch (op.op()) {
  614. case COMPOSITE_UNDEF:
  615. // Undefined == no composition
  616. break;
  617. case COMPOSITE_OVER:
  618. compositeOver(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
  619. break;
  620. case COMPOSITE_IN:
  621. //compositeIn(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  622. case COMPOSITE_OUT:
  623. //compositeOut(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  624. break;
  625. case COMPOSITE_ATOP:
  626. //compositeAtop(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  627. break;
  628. case COMPOSITE_XOR:
  629. //compositeXor(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  630. break;
  631. case COMPOSITE_PLUS:
  632. //compositePlus(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  633. break;
  634. case COMPOSITE_MINUS:
  635. //compositeMinus(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  636. break;
  637. case COMPOSITE_ADD:
  638. //compositeAdd(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  639. break;
  640. case COMPOSITE_SUBTRACT:
  641. //compositeSubtract(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  642. break;
  643. case COMPOSITE_DIFF:
  644. //compositeDiff(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  645. break;
  646. case COMPOSITE_MULT:
  647. compositeMultiply(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
  648. break;
  649. case COMPOSITE_DIVIDE:
  650. compositeDivide(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
  651. break;
  652. case COMPOSITE_BUMPMAP:
  653. //compositeBumpmap(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  654. break;
  655. case COMPOSITE_COPY:
  656. compositeCopy(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, U8_opacity);
  657. break;
  658. case COMPOSITE_COPY_RED:
  659. //compositeCopyRed(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  660. break;
  661. case COMPOSITE_COPY_GREEN:
  662. //compositeCopyGreen(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  663. break;
  664. case COMPOSITE_COPY_BLUE:
  665. //compositeCopyBlue(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  666. break;
  667. case COMPOSITE_COPY_OPACITY:
  668. //compositeCopyOpacity(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  669. break;
  670. case COMPOSITE_CLEAR:
  671. //compositeClear(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  672. break;
  673. case COMPOSITE_DISSOLVE:
  674. //compositeDissolve(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  675. break;
  676. case COMPOSITE_DISPLACE:
  677. //compositeDisplace(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  678. break;
  679. #if 0
  680. case COMPOSITE_MODULATE:
  681. compositeModulate(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  682. break;
  683. case COMPOSITE_THRESHOLD:
  684. compositeThreshold(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  685. break;
  686. #endif
  687. case COMPOSITE_NO:
  688. // No composition.
  689. break;
  690. case COMPOSITE_DARKEN:
  691. compositeDarken(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
  692. break;
  693. case COMPOSITE_LIGHTEN:
  694. compositeLighten(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
  695. break;
  696. case COMPOSITE_HUE:
  697. compositeHue(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
  698. break;
  699. case COMPOSITE_SATURATION:
  700. compositeSaturation(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
  701. break;
  702. case COMPOSITE_VALUE:
  703. compositeValue(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
  704. break;
  705. case COMPOSITE_COLOR:
  706. compositeColor(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
  707. break;
  708. case COMPOSITE_COLORIZE:
  709. //compositeColorize(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  710. break;
  711. case COMPOSITE_LUMINIZE:
  712. //compositeLuminize(pixelSize(), dst, dstRowStride, src, srcRowStride, rows, cols, opacity);
  713. break;
  714. case COMPOSITE_SCREEN:
  715. compositeScreen(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
  716. break;
  717. case COMPOSITE_OVERLAY:
  718. compositeOverlay(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
  719. break;
  720. case COMPOSITE_ERASE:
  721. compositeErase(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
  722. break;
  723. case COMPOSITE_DODGE:
  724. compositeDodge(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
  725. break;
  726. case COMPOSITE_BURN:
  727. compositeBurn(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity);
  728. break;
  729. case COMPOSITE_ALPHA_DARKEN:
  730. abstractCompositeAlphaDarken<float, F32Mult, Uint8ToF32, F32OpacityTest,
  731. PIXEL_ALPHA, MAX_CHANNEL_RGB, MAX_CHANNEL_RGBA>(
  732. dst, dstRowStride, src, srcRowStride, mask, maskRowStride,
  733. rows, cols, U8_opacity, F32Mult(), Uint8ToF32(), F32OpacityTest());
  734. default:
  735. break;
  736. }
  737. }
  738. KisCompositeOpList KisRgbF32ColorSpace::userVisiblecompositeOps() const
  739. {
  740. KisCompositeOpList list;
  741. list.append(KisCompositeOp(COMPOSITE_OVER));
  742. list.append(KisCompositeOp(COMPOSITE_ALPHA_DARKEN));
  743. list.append(KisCompositeOp(COMPOSITE_MULT));
  744. list.append(KisCompositeOp(COMPOSITE_BURN));
  745. list.append(KisCompositeOp(COMPOSITE_DODGE));
  746. list.append(KisCompositeOp(COMPOSITE_DIVIDE));
  747. list.append(KisCompositeOp(COMPOSITE_SCREEN));
  748. list.append(KisCompositeOp(COMPOSITE_OVERLAY));
  749. list.append(KisCompositeOp(COMPOSITE_DARKEN));
  750. list.append(KisCompositeOp(COMPOSITE_LIGHTEN));
  751. list.append(KisCompositeOp(COMPOSITE_HUE));
  752. list.append(KisCompositeOp(COMPOSITE_SATURATION));
  753. list.append(KisCompositeOp(COMPOSITE_VALUE));
  754. list.append(KisCompositeOp(COMPOSITE_COLOR));
  755. return list;
  756. }