Changeset View
Changeset View
Standalone View
Standalone View
imagelib/effects/blitz.cpp
Show First 20 Lines • Show All 118 Lines • ▼ Show 20 Line(s) | |||||
119 | typedef struct | 119 | typedef struct | ||
120 | { | 120 | { | ||
121 | quint32 red, green, blue, alpha; | 121 | quint32 red, green, blue, alpha; | ||
122 | } HistogramListItem; | 122 | } HistogramListItem; | ||
123 | 123 | | |||
124 | 124 | | |||
125 | bool equalize(QImage &img) | 125 | bool equalize(QImage &img) | ||
126 | { | 126 | { | ||
127 | if(img.isNull()) | 127 | if(img.isNull()) { | ||
128 | return(false); | 128 | return(false); | ||
129 | } | ||||
129 | 130 | | |||
130 | HistogramListItem *histogram; | 131 | HistogramListItem *histogram; | ||
131 | IntegerPixel *map; | 132 | IntegerPixel *map; | ||
132 | IntegerPixel intensity, high, low; | 133 | IntegerPixel intensity, high, low; | ||
133 | CharPixel *equalize_map; | 134 | CharPixel *equalize_map; | ||
134 | int i, count; | 135 | int i, count; | ||
135 | QRgb pixel, *dest; | 136 | QRgb pixel, *dest; | ||
136 | unsigned char r, g, b; | 137 | unsigned char r, g, b; | ||
Show All 40 Lines | 175 | for(i=0; i < 256; ++i){ | |||
177 | intensity.blue += histogram[i].blue; | 178 | intensity.blue += histogram[i].blue; | ||
178 | map[i] = intensity; | 179 | map[i] = intensity; | ||
179 | } | 180 | } | ||
180 | 181 | | |||
181 | low = map[0]; | 182 | low = map[0]; | ||
182 | high = map[255]; | 183 | high = map[255]; | ||
183 | memset(equalize_map, 0, 256*sizeof(CharPixel)); | 184 | memset(equalize_map, 0, 256*sizeof(CharPixel)); | ||
184 | for(i=0; i < 256; ++i){ | 185 | for(i=0; i < 256; ++i){ | ||
185 | if(high.red != low.red) | 186 | if(high.red != low.red) { | ||
186 | equalize_map[i].red = static_cast<unsigned char> | 187 | equalize_map[i].red = static_cast<unsigned char> | ||
187 | ((255*(map[i].red-low.red))/(high.red-low.red)); | 188 | ((255*(map[i].red-low.red))/(high.red-low.red)); | ||
188 | if(high.green != low.green) | 189 | } | ||
190 | if(high.green != low.green) { | ||||
189 | equalize_map[i].green = static_cast<unsigned char> | 191 | equalize_map[i].green = static_cast<unsigned char> | ||
190 | ((255*(map[i].green-low.green))/(high.green-low.green)); | 192 | ((255*(map[i].green-low.green))/(high.green-low.green)); | ||
191 | if(high.blue != low.blue) | 193 | } | ||
194 | if(high.blue != low.blue) { | ||||
192 | equalize_map[i].blue = static_cast<unsigned char> | 195 | equalize_map[i].blue = static_cast<unsigned char> | ||
193 | ((255*(map[i].blue-low.blue))/(high.blue-low.blue)); | 196 | ((255*(map[i].blue-low.blue))/(high.blue-low.blue)); | ||
194 | } | 197 | } | ||
198 | } | ||||
195 | 199 | | |||
196 | // stretch the histogram and write | 200 | // stretch the histogram and write | ||
197 | dest = (QRgb *)img.bits(); | 201 | dest = (QRgb *)img.bits(); | ||
198 | if(img.format() == QImage::Format_ARGB32_Premultiplied){ | 202 | if(img.format() == QImage::Format_ARGB32_Premultiplied){ | ||
199 | for(i=0; i < count; ++i, ++dest){ | 203 | for(i=0; i < count; ++i, ++dest){ | ||
200 | pixel = convertFromPremult(*dest); | 204 | pixel = convertFromPremult(*dest); | ||
201 | r = static_cast<unsigned char> ((low.red != high.red) ? | 205 | r = static_cast<unsigned char> ((low.red != high.red) ? | ||
202 | equalize_map[qRed(pixel)].red : qRed(pixel)); | 206 | equalize_map[qRed(pixel)].red : qRed(pixel)); | ||
Show All 33 Lines | |||||
236 | 240 | | |||
237 | QImage Blitz::blur(QImage &img, int radius) | 241 | QImage Blitz::blur(QImage &img, int radius) | ||
238 | { | 242 | { | ||
239 | QRgb *p1, *p2; | 243 | QRgb *p1, *p2; | ||
240 | int x, y, w, h, mx, my, mw, mh, mt, xx, yy; | 244 | int x, y, w, h, mx, my, mw, mh, mt, xx, yy; | ||
241 | int a, r, g, b; | 245 | int a, r, g, b; | ||
242 | int *as, *rs, *gs, *bs; | 246 | int *as, *rs, *gs, *bs; | ||
243 | 247 | | |||
244 | if(radius < 1 || img.isNull() || img.width() < (radius << 1)) | 248 | if(radius < 1 || img.isNull() || img.width() < (radius << 1)) { | ||
245 | return(img); | 249 | return(img); | ||
250 | } | ||||
246 | 251 | | |||
247 | w = img.width(); | 252 | w = img.width(); | ||
248 | h = img.height(); | 253 | h = img.height(); | ||
249 | 254 | | |||
250 | if(img.depth() < 8) | 255 | if(img.depth() < 8) { | ||
251 | img = img.convertToFormat(QImage::Format_Indexed8); | 256 | img = img.convertToFormat(QImage::Format_Indexed8); | ||
257 | } | ||||
252 | QImage buffer(w, h, img.hasAlphaChannel() ? | 258 | QImage buffer(w, h, img.hasAlphaChannel() ? | ||
253 | QImage::Format_ARGB32 : QImage::Format_RGB32); | 259 | QImage::Format_ARGB32 : QImage::Format_RGB32); | ||
254 | 260 | | |||
255 | as = new int[w]; | 261 | as = new int[w]; | ||
256 | rs = new int[w]; | 262 | rs = new int[w]; | ||
257 | gs = new int[w]; | 263 | gs = new int[w]; | ||
258 | bs = new int[w]; | 264 | bs = new int[w]; | ||
259 | 265 | | |||
260 | QVector<QRgb> colorTable; | 266 | QVector<QRgb> colorTable; | ||
261 | if(img.format() == QImage::Format_Indexed8) | 267 | if(img.format() == QImage::Format_Indexed8) { | ||
262 | colorTable = img.colorTable(); | 268 | colorTable = img.colorTable(); | ||
269 | } | ||||
263 | 270 | | |||
264 | for(y = 0; y < h; y++){ | 271 | for(y = 0; y < h; y++){ | ||
265 | my = y - radius; | 272 | my = y - radius; | ||
266 | mh = (radius << 1) + 1; | 273 | mh = (radius << 1) + 1; | ||
267 | if(my < 0){ | 274 | if(my < 0){ | ||
268 | mh += my; | 275 | mh += my; | ||
269 | my = 0; | 276 | my = 0; | ||
270 | } | 277 | } | ||
271 | if((my + mh) > h) | 278 | if((my + mh) > h) { | ||
272 | mh = h - my; | 279 | mh = h - my; | ||
280 | } | ||||
273 | 281 | | |||
274 | p1 = (QRgb *)buffer.scanLine(y); | 282 | p1 = (QRgb *)buffer.scanLine(y); | ||
275 | memset(as, 0, static_cast<unsigned int> (w) * sizeof(int)); | 283 | memset(as, 0, static_cast<unsigned int> (w) * sizeof(int)); | ||
276 | memset(rs, 0, static_cast<unsigned int> (w) * sizeof(int)); | 284 | memset(rs, 0, static_cast<unsigned int> (w) * sizeof(int)); | ||
277 | memset(gs, 0, static_cast<unsigned int> (w) * sizeof(int)); | 285 | memset(gs, 0, static_cast<unsigned int> (w) * sizeof(int)); | ||
278 | memset(bs, 0, static_cast<unsigned int> (w) * sizeof(int)); | 286 | memset(bs, 0, static_cast<unsigned int> (w) * sizeof(int)); | ||
279 | 287 | | |||
280 | if(img.format() == QImage::Format_ARGB32_Premultiplied){ | 288 | if(img.format() == QImage::Format_ARGB32_Premultiplied){ | ||
Show All 38 Lines | |||||
319 | for(x = 0; x < w; x++){ | 327 | for(x = 0; x < w; x++){ | ||
320 | a = r = g = b = 0; | 328 | a = r = g = b = 0; | ||
321 | mx = x - radius; | 329 | mx = x - radius; | ||
322 | mw = (radius << 1) + 1; | 330 | mw = (radius << 1) + 1; | ||
323 | if(mx < 0){ | 331 | if(mx < 0){ | ||
324 | mw += mx; | 332 | mw += mx; | ||
325 | mx = 0; | 333 | mx = 0; | ||
326 | } | 334 | } | ||
327 | if((mx + mw) > w) | 335 | if((mx + mw) > w) { | ||
328 | mw = w - mx; | 336 | mw = w - mx; | ||
337 | } | ||||
329 | mt = mw * mh; | 338 | mt = mw * mh; | ||
330 | for(xx = mx; xx < (mw + mx); xx++){ | 339 | for(xx = mx; xx < (mw + mx); xx++){ | ||
331 | a += as[xx]; | 340 | a += as[xx]; | ||
332 | r += rs[xx]; | 341 | r += rs[xx]; | ||
333 | g += gs[xx]; | 342 | g += gs[xx]; | ||
334 | b += bs[xx]; | 343 | b += bs[xx]; | ||
335 | } | 344 | } | ||
336 | a = a / mt; | 345 | a = a / mt; | ||
Show All 21 Lines | 363 | { | |||
358 | float sigmaSQ2PI = static_cast<float>(M_SQ2PI) * sigma; | 367 | float sigmaSQ2PI = static_cast<float>(M_SQ2PI) * sigma; | ||
359 | int max = quality ? 65535 : 255; | 368 | int max = quality ? 65535 : 255; | ||
360 | 369 | | |||
361 | if(sigma == 0.0f){ | 370 | if(sigma == 0.0f){ | ||
362 | qWarning("Blitz::defaultConvolveMatrixSize(): Zero sigma is invalid!"); | 371 | qWarning("Blitz::defaultConvolveMatrixSize(): Zero sigma is invalid!"); | ||
363 | return(5); | 372 | return(5); | ||
364 | } | 373 | } | ||
365 | 374 | | |||
366 | if(radius > 0.0f) | 375 | if(radius > 0.0f) { | ||
367 | return(static_cast<int>(2.0f * std::ceil(radius) + 1.0f)); | 376 | return(static_cast<int>(2.0f * std::ceil(radius) + 1.0f)); | ||
377 | } | ||||
368 | 378 | | |||
369 | matrix_size = 5; | 379 | matrix_size = 5; | ||
370 | do{ | 380 | do{ | ||
371 | normalize = 0.0; | 381 | normalize = 0.0; | ||
372 | for(i=(-matrix_size/2); i <= (matrix_size/2); ++i) | 382 | for(i=(-matrix_size/2); i <= (matrix_size/2); ++i) { | ||
373 | normalize += std::exp(-(static_cast<float> (i*i))/sigma2) / sigmaSQ2PI; | 383 | normalize += std::exp(-(static_cast<float> (i*i))/sigma2) / sigmaSQ2PI; | ||
384 | } | ||||
374 | i = matrix_size/2; | 385 | i = matrix_size/2; | ||
375 | value = std::exp(-(static_cast<float> (i*i))/sigma2) / sigmaSQ2PI / normalize; | 386 | value = std::exp(-(static_cast<float> (i*i))/sigma2) / sigmaSQ2PI / normalize; | ||
376 | matrix_size += 2; | 387 | matrix_size += 2; | ||
377 | } while(static_cast<int>(max*value) > 0); | 388 | } while(static_cast<int>(max*value) > 0); | ||
378 | 389 | | |||
379 | matrix_size-=4; | 390 | matrix_size-=4; | ||
380 | return(matrix_size); | 391 | return(matrix_size); | ||
381 | } | 392 | } | ||
Show All 14 Lines | 397 | { | |||
396 | 407 | | |||
397 | w = img.width(); | 408 | w = img.width(); | ||
398 | h = img.height(); | 409 | h = img.height(); | ||
399 | if(w < 3 || h < 3){ | 410 | if(w < 3 || h < 3){ | ||
400 | qWarning("Blitz::convolve(): Image is too small!"); | 411 | qWarning("Blitz::convolve(): Image is too small!"); | ||
401 | return(img); | 412 | return(img); | ||
402 | } | 413 | } | ||
403 | 414 | | |||
404 | if(img.format() == QImage::Format_ARGB32_Premultiplied) | 415 | if(img.format() == QImage::Format_ARGB32_Premultiplied) { | ||
405 | img = img.convertToFormat(QImage::Format_ARGB32); | 416 | img = img.convertToFormat(QImage::Format_ARGB32); | ||
417 | } | ||||
406 | else if(img.depth() < 32){ | 418 | else if(img.depth() < 32){ | ||
407 | img = img.convertToFormat(img.hasAlphaChannel() ? | 419 | img = img.convertToFormat(img.hasAlphaChannel() ? | ||
408 | QImage::Format_ARGB32 : | 420 | QImage::Format_ARGB32 : | ||
409 | QImage::Format_RGB32); | 421 | QImage::Format_RGB32); | ||
410 | } | 422 | } | ||
411 | QImage buffer(w, h, img.format()); | 423 | QImage buffer(w, h, img.format()); | ||
412 | 424 | | |||
413 | scanblock = new QRgb* [matrix_size]; | 425 | scanblock = new QRgb* [matrix_size]; | ||
414 | normalize_matrix = new float[matrix_size*matrix_size]; | 426 | normalize_matrix = new float[matrix_size*matrix_size]; | ||
415 | 427 | | |||
416 | // create normalized matrix | 428 | // create normalized matrix | ||
417 | normalize = 0.0; | 429 | normalize = 0.0; | ||
418 | for(i=0; i < matrix_size*matrix_size; ++i) | 430 | for(i=0; i < matrix_size*matrix_size; ++i) { | ||
419 | normalize += matrix[i]; | 431 | normalize += matrix[i]; | ||
420 | if(std::abs(normalize) <= static_cast<float> (M_EPSILON)) | 432 | } | ||
433 | if(std::abs(normalize) <= static_cast<float> (M_EPSILON)) { | ||||
421 | normalize = 1.0f; | 434 | normalize = 1.0f; | ||
435 | } | ||||
422 | normalize = 1.0f/normalize; | 436 | normalize = 1.0f/normalize; | ||
423 | for(i=0; i < matrix_size*matrix_size; ++i){ | 437 | for(i=0; i < matrix_size*matrix_size; ++i){ | ||
424 | normalize_matrix[i] = normalize*matrix[i]; | 438 | normalize_matrix[i] = normalize*matrix[i]; | ||
425 | } | 439 | } | ||
426 | 440 | | |||
427 | // apply | 441 | // apply | ||
428 | 442 | | |||
429 | { | 443 | { | ||
▲ Show 20 Lines • Show All 138 Lines • ▼ Show 20 Line(s) | 571 | { | |||
568 | float sigmaPI2 = 2.0f*static_cast<float> (M_PI)*sigma*sigma; | 582 | float sigmaPI2 = 2.0f*static_cast<float> (M_PI)*sigma*sigma; | ||
569 | 583 | | |||
570 | int half = matrix_size/2; | 584 | int half = matrix_size/2; | ||
571 | int x, y, i=0, j=half; | 585 | int x, y, i=0, j=half; | ||
572 | for(y=(-half); y <= half; ++y, --j){ | 586 | for(y=(-half); y <= half; ++y, --j){ | ||
573 | for(x=(-half); x <= half; ++x, ++i){ | 587 | for(x=(-half); x <= half; ++x, ++i){ | ||
574 | alpha = std::exp(-(static_cast<float> (x*x+y*y))/sigma2); | 588 | alpha = std::exp(-(static_cast<float> (x*x+y*y))/sigma2); | ||
575 | matrix[i]=((x < 0) || (y < 0) ? -8.0f : 8.0f)*alpha/sigmaPI2; | 589 | matrix[i]=((x < 0) || (y < 0) ? -8.0f : 8.0f)*alpha/sigmaPI2; | ||
576 | if(x == j) | 590 | if(x == j) { | ||
577 | matrix[i]=0.0; | 591 | matrix[i]=0.0; | ||
578 | } | 592 | } | ||
579 | } | 593 | } | ||
594 | } | ||||
580 | QImage result(convolve(img, matrix_size, matrix)); | 595 | QImage result(convolve(img, matrix_size, matrix)); | ||
581 | delete[] matrix; | 596 | delete[] matrix; | ||
582 | equalize(result); | 597 | equalize(result); | ||
583 | return(result); | 598 | return(result); | ||
584 | } | 599 | } | ||
585 | 600 | | |||
586 | //-------------------------------------------------------------------------------- | 601 | //-------------------------------------------------------------------------------- | ||
587 | 602 | | |||
588 | QImage& Blitz::flatten(QImage &img, const QColor &ca, const QColor &cb) | 603 | QImage& Blitz::flatten(QImage &img, const QColor &ca, const QColor &cb) | ||
589 | { | 604 | { | ||
590 | if(img.isNull()) | 605 | if(img.isNull()) { | ||
591 | return(img); | 606 | return(img); | ||
607 | } | ||||
592 | 608 | | |||
593 | if(img.depth() == 1) { | 609 | if(img.depth() == 1) { | ||
594 | img.setColor(0, ca.rgb()); | 610 | img.setColor(0, ca.rgb()); | ||
595 | img.setColor(1, cb.rgb()); | 611 | img.setColor(1, cb.rgb()); | ||
596 | return(img); | 612 | return(img); | ||
597 | } | 613 | } | ||
598 | 614 | | |||
599 | int r1 = ca.red(); int r2 = cb.red(); | 615 | int r1 = ca.red(); int r2 = cb.red(); | ||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Line(s) | 676 | *data = | |||
661 | convertToPremult(qRgba(static_cast<unsigned char> (sr * (mean - min) + r1 + 0.5f), | 677 | convertToPremult(qRgba(static_cast<unsigned char> (sr * (mean - min) + r1 + 0.5f), | ||
662 | static_cast<unsigned char> (sg * (mean - min) + g1 + 0.5f), | 678 | static_cast<unsigned char> (sg * (mean - min) + g1 + 0.5f), | ||
663 | static_cast<unsigned char> (sb * (mean - min) + b1 + 0.5f), | 679 | static_cast<unsigned char> (sb * (mean - min) + b1 + 0.5f), | ||
664 | qAlpha(*data))); | 680 | qAlpha(*data))); | ||
665 | ++data; | 681 | ++data; | ||
666 | } | 682 | } | ||
667 | } | 683 | } | ||
668 | 684 | | |||
669 | if(img.format() == QImage::Format_Indexed8) | 685 | if(img.format() == QImage::Format_Indexed8) { | ||
670 | img.setColorTable(cTable); | 686 | img.setColorTable(cTable); | ||
687 | } | ||||
671 | return(img); | 688 | return(img); | ||
672 | } | 689 | } | ||
673 | 690 | | |||
674 | //-------------------------------------------------------------------------------- | 691 | //-------------------------------------------------------------------------------- |