void DkThumbNail::removeBlackBorder(QImage& img) { int rIdx = 0; bool nonblack = false; for ( ; rIdx < qRound(img.height()*0.1); rIdx++) { const QRgb* pixel = (QRgb*)(img.constScanLine(rIdx)); for (int cIdx = 0; cIdx < img.width(); cIdx++, pixel++) { // > 50 due to jpeg (normally we would want it to be != 0) if (qRed(*pixel) > 50 || qBlue(*pixel) > 50 || qGreen(*pixel) > 50) { nonblack = true; break; } } if (nonblack) break; } // non black border? if (rIdx == -1 || rIdx > 15) return; int rIdxB = img.height()-1; nonblack = false; for ( ; rIdxB >= qRound(img.height()*0.9f); rIdxB--) { const QRgb* pixel = (QRgb*)(img.constScanLine(rIdxB)); for (int cIdx = 0; cIdx < img.width(); cIdx++, pixel++) { if (qRed(*pixel) > 50 || qBlue(*pixel) > 50 || qGreen(*pixel) > 50) { nonblack = true; break; } } if (nonblack) { rIdxB--; break; } } // remove black borders if (rIdx < rIdxB) img = img.copy(0, rIdx, img.width(), rIdxB-rIdx); }
void BlurElementPrivate::integralImage(const QImage &image, int oWidth, int oHeight, PixelU32 *integral) { for (int y = 1; y < oHeight; y++) { auto line = reinterpret_cast<const QRgb *>(image.constScanLine(y - 1)); // Reset current line summation. PixelU32 sum; for (int x = 1; x < oWidth; x++) { QRgb pixel = line[x - 1]; // Accumulate pixels in current line. sum += pixel; // Offset to the current line. int offset = x + y * oWidth; // Offset to the previous line. // equivalent to x + (y - 1) * oWidth; int offsetPrevious = offset - oWidth; // Accumulate current line and previous line. integral[offset] = sum + integral[offsetPrevious]; } } }
inline QImage threshold(const QImage &src, const QVector<int> &thresholds, const QVector<int> &colors) { QImage dst(src.size(), src.format()); QVector<quint8> colorTable(256); int j = 0; for (int i = 0; i < colorTable.size(); i++) { if (j < thresholds.size() && i >= thresholds[j]) j++; colorTable[i] = quint8(colors[j]); } for (int y = 0; y < src.height(); y++) { const quint8 *srcLine = src.constScanLine(y); quint8 *dstLine = dst.scanLine(y); for (int x = 0; x < src.width(); x++) dstLine[x] = colorTable[srcLine[x]]; } return dst; }
QColor QgsCompoundColorWidget::averageColor( const QImage &image ) const { QRgb tmpRgb; int colorCount = 0; int sumRed = 0; int sumBlue = 0; int sumGreen = 0; //scan through image and sum rgb components for ( int heightIndex = 0; heightIndex < image.height(); ++heightIndex ) { QRgb *scanLine = ( QRgb * )image.constScanLine( heightIndex ); for ( int widthIndex = 0; widthIndex < image.width(); ++widthIndex ) { tmpRgb = scanLine[widthIndex]; sumRed += qRed( tmpRgb ); sumBlue += qBlue( tmpRgb ); sumGreen += qGreen( tmpRgb ); colorCount++; } } //calculate average components as floats double avgRed = ( double )sumRed / ( 255.0 * colorCount ); double avgGreen = ( double )sumGreen / ( 255.0 * colorCount ); double avgBlue = ( double )sumBlue / ( 255.0 * colorCount ); //create a new color representing the average return QColor::fromRgbF( avgRed, avgGreen, avgBlue ); }
QList<QImage> split(const QImage& img) { QVector<bool> emptyLines(img.height(), true); for (int y = 0; y < img.height(); ++y) { const uchar* it = img.constScanLine(y); const uchar* end = it + img.width(); while (it < end) { if (*it++ > 10) { emptyLines[y] = false; break; } } } QList<QImage> lines; for (int y = 0; y < img.height();) { if (emptyLines[y]) { ++y; continue; } QRect r(0, y, img.width(), 1); int height = 0; for (; y < img.height() && !emptyLines[y]; ++y) ++height; r.setHeight(height); if (height > 60 && height < 80) { lines += splitPath(img.copy(r)); } else { lines << img.copy(r); } } return lines; }
static void placeImage(QImage& dst,int x,int y,const QImage& src) { int size = src.width()*4; for (int yy=0;yy<src.height();yy++) { const uchar* src_d = src.constScanLine(yy); uchar* dst_d = dst.scanLine(y+yy); dst_d += x*4; ::memcpy(dst_d,src_d,size); } }
static bool writeWBMPData(QIODevice *iodev, const QImage &image) { if (iodev) { int h = image.height(); int bpl = (image.width() + 7) / 8; for (int l=0; l<h; l++) { if (iodev->write(reinterpret_cast<const char *>(image.constScanLine(l)), bpl) != bpl) return false; } return true; } return false; }
QImage qmainstackwidget::toGray(QImage image) { int height = image.height(); int width = image.width(); QImage ret(width, height, QImage::Format_Indexed8); ret.setColorCount(256); for (int i = 0; i < 256; i++) { ret.setColor(i, qRgb(i, i, i)); } switch (image.format()) { case QImage::Format_Indexed8: for (int i = 0; i < height; i++) { const uchar *pSrc = (uchar *)image.constScanLine(i); uchar *pDest = (uchar *)ret.scanLine(i); memcpy(pDest, pSrc, width); } break; case QImage::Format_RGB32: case QImage::Format_ARGB32: case QImage::Format_ARGB32_Premultiplied: for (int i = 0; i < height; i++) { const QRgb *pSrc = (QRgb *)image.constScanLine(i); uchar *pDest = (uchar *)ret.scanLine(i); for (int j = 0; j < width; j++) { pDest[j] = qGray(pSrc[j]); } } break; } return ret; }
void TestInvocation::dumpPixelsAndCompareWithExpected(WKImageRef imageRef, WKArrayRef repaintRects) { QImage image; if (PlatformWebView::windowShapshotEnabled()) { WKPageRef page = TestController::shared().mainWebView()->page(); WKPageForceRepaint(page, this, &forceRepaintDoneCallback); TestController::shared().runUntil(m_gotRepaint, TestController::ShortTimeout); if (m_gotRepaint) image = WKImageCreateQImage(TestController::shared().mainWebView()->windowSnapshotImage().get()); else { m_error = true; m_errorMessage = "Timed out waiting for repaint\n"; m_webProcessIsUnresponsive = true; return; } } else image = WKImageCreateQImage(imageRef); if (repaintRects) { QImage mask(image.size(), image.format()); mask.fill(QColor(0, 0, 0, 0.66 * 255)); QPainter maskPainter(&mask); maskPainter.setCompositionMode(QPainter::CompositionMode_Source); size_t count = WKArrayGetSize(repaintRects); for (size_t i = 0; i < count; ++i) { WKRect wkRect = WKRectGetValue(static_cast<WKRectRef>(WKArrayGetItemAtIndex(repaintRects, i))); QRectF rect(wkRect.origin.x, wkRect.origin.y, wkRect.size.width, wkRect.size.height); maskPainter.fillRect(rect, Qt::transparent); } QPainter painter(&image); painter.drawImage(image.rect(), mask); } QCryptographicHash hash(QCryptographicHash::Md5); for (unsigned row = 0; row < image.height(); ++row) hash.addData(reinterpret_cast<const char*>(image.constScanLine(row)), image.bytesPerLine()); QByteArray actualHash = hash.result().toHex(); ASSERT(actualHash.size() == 32); if (!compareActualHashToExpectedAndDumpResults(actualHash)) { image.setText("checksum", actualHash); dumpImage(image); } }
void FilterOp::filterHorizontally(QImage &src, QRgb *trg, const QRgb *rgba) { const uchar* pixels = src.constScanLine(0); int sourcePitch = src.bytesPerLine(); for (int k = 0; k < srcHeight; ++k) { int destOfsY = dstWidth * k; for (int i = dstWidth - 1; i >= 0 ; --i) { float red = 0; float green = 0; float blue = 0; float alpha = 0; int max = horizontalSubsamplingData.numberOfSamples[i]; int index = i * horizontalSubsamplingData.matrixWidth; for (int j = max - 1; j >= 0; --j) { int ofsX = horizontalSubsamplingData.pixelPositions[index]; int palIdx = pixels[ofsX] & 0xff; float w = horizontalSubsamplingData.weights[index]; red += qRed(rgba[palIdx]) * w; green += qGreen(rgba[palIdx]) * w; blue+= qBlue(rgba[palIdx]) * w; alpha += qAlpha(rgba[palIdx]) * w; index++; } int ri = std::max((int)red, 0); ri = std::min(ri, 255); int gi = std::max((int)green, 0); gi = std::min(gi, 255); int bi = std::max((int)blue, 0); bi = std::min(bi, 255); int ai = std::max((int)alpha, 0); ai = std::min(ai, 255); trg[i + destOfsY] = qRgba(ri, gi, bi, ai); } pixels += sourcePitch; } }
inline QVector<int> histogram(const QImage &image) { QVector<int> histogram(256, 0); for (int y = 0; y < image.height(); y++) { const quint8 *line = reinterpret_cast<const quint8 *>(image.constScanLine(y)); for (int x = 0; x < image.width(); x++) histogram[line[x]]++; } // Since we use sum tables add one more to avoid unexistent colors. for (int i = 0; i < histogram.size(); i++) histogram[i]++; return histogram; }
void TestInvocation::dumpPixelsAndCompareWithExpected(WKImageRef imageRef, WKArrayRef repaintRects) { //FIXME: https://bugs.webkit.org/show_bug.cgi?id=68870 UNUSED_PARAM(repaintRects); QImage image = WKImageCreateQImage(imageRef); QCryptographicHash hash(QCryptographicHash::Md5); for (unsigned row = 0; row < image.height(); ++row) hash.addData(reinterpret_cast<const char*>(image.constScanLine(row)), image.bytesPerLine()); QByteArray actualHash = hash.result().toHex(); ASSERT(actualHash.size() == 32); if (!compareActualHashToExpectedAndDumpResults(actualHash)) { image.setText("checksum", actualHash); dumpImage(image); } }
static void addImage( FlifEncoder& encoder, const QImage& in ) { FlifImage img( in.width(), in.height() ); auto buffer = std::make_unique<uint8_t[]>( in.width() * 4 ); for( int iy=0; iy<in.height(); iy++ ) { auto line = (const QRgb*)in.constScanLine( iy ); for( int ix=0; ix<in.width(); ix++ ) { buffer[ix*4+0] = qRed( line[ix] ); buffer[ix*4+1] = qGreen( line[ix] ); buffer[ix*4+2] = qBlue( line[ix] ); buffer[ix*4+3] = qAlpha( line[ix] ); } img.writeRowRgba8( iy, buffer.get(), in.width() * 4 ); } encoder.addImage( img ); //TODO: investigate memory model }
QColor get_average_color(QImage src){ if (src.depth() < 32) src = src.convertToFormat(QImage::Format_ARGB32); quint64 avg[3] = {0}; unsigned pixel_count=0; for (auto y = src.height() * 0; y < src.height(); y++){ const uchar *p = src.constScanLine(y); for (auto x = src.width() * 0; x < src.width(); x++){ avg[0] += quint64(p[2]) * quint64(p[3]) / 255; avg[1] += quint64(p[1]) * quint64(p[3]) / 255; avg[2] += quint64(p[0]) * quint64(p[3]) / 255; p += 4; pixel_count++; } } for (int a = 0; a < 3; a++) avg[a] /= pixel_count; return QColor(avg[0], avg[1], avg[2]); }
QImage imageForPixbuf(const GdkPixbuf* pixbuf, const QString &name) { QImage result; if (gdk_pixbuf_get_n_channels(pixbuf) == 3 && gdk_pixbuf_get_bits_per_sample(pixbuf) == 8 && !gdk_pixbuf_get_has_alpha(pixbuf)) { const QImage image = QImage(gdk_pixbuf_get_pixels(pixbuf), gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), gdk_pixbuf_get_rowstride(pixbuf), QImage::QImage::Format_RGB888); result = image.convertToFormat(QImage::Format_ARGB32); } else { if (gdk_pixbuf_get_n_channels(pixbuf) != 4 || gdk_pixbuf_get_bits_per_sample(pixbuf) != 8 || !gdk_pixbuf_get_has_alpha(pixbuf)) { UQ_WARNING << "Pixbuf is not in the expected format. Trying to load it anyway, will most likely fail" << name; } const QImage image = QImage(gdk_pixbuf_get_pixels(pixbuf), gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), gdk_pixbuf_get_rowstride(pixbuf), QImage::Format_ARGB32); #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN /* ABGR → ARGB */ result = image.rgbSwapped(); #else /* ABGR → BGRA */ /* Reference: https://bugs.launchpad.net/unity-2d/+bug/758782 */ result = QImage(image.size(), image.format()); for (int i = 0; i < swappedImage.height(); ++i) { QRgb* p = (QRgb*) image.constScanLine(i); QRgb* q = (QRgb*) swappedImage.scanLine(i); QRgb* end = p + image.width(); while (p < end) { *q = qRgba(qAlpha(*p), qRed(*p), qGreen(*p), qBlue(*p)); p++; q++; } } #endif } return result; }
QImage GaussianFilter::gaussianBlur(const QImage &img) const { QImage result(img.size(), QImage::Format_Indexed8); { QVector<QRgb> colorTable; colorTable.reserve(256); for (int i = 0; i < 256; i++) { colorTable << qRgb(i, i, i); } result.setColorTable(colorTable); } const int kernelSize = mHalfSize * 2 + 1; for (int y = 0; y < img.height(); y++) { for (int x = 0; x < img.width(); x++) { qreal sum = 0; for (int ky = -mHalfSize; ky <= mHalfSize; ky++) { const int yTemp = y + ky; int yIdx = yTemp; if (yTemp >= img.height()) { yIdx = img.height() - (yTemp - img.height()) - 1; } else if (yTemp < 0) { yIdx = -yTemp; } const uchar *dy = img.constScanLine(yIdx); for (int kx = -mHalfSize; kx <= mHalfSize; kx++) { const int xTemp = x + kx; int xIdx = xTemp; if (xTemp >= img.width()) { xIdx = img.width() - (xTemp - img.width()) - 1; } else if (xTemp < 0) { xIdx = -xTemp; } sum += dy[xIdx] * mKernel.at((ky + mHalfSize) * kernelSize + kx + mHalfSize); } } sum *= mScale; const int iSum = sum; //qBound(0, sum, 255) result.setPixel(x, y, iSum); } } return result; }
jobject createBitmap(QImage img, JNIEnv *env) { if (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_RGB16) img = img.convertToFormat(QImage::Format_ARGB32); jobject bitmap = env->CallStaticObjectMethod(m_bitmapClass, m_createBitmapMethodID, img.width(), img.height(), img.format() == QImage::Format_ARGB32 ? m_ARGB_8888_BitmapConfigValue : m_RGB_565_BitmapConfigValue); if (!bitmap) return 0; AndroidBitmapInfo info; if (AndroidBitmap_getInfo(env, bitmap, &info) < 0) { env->DeleteLocalRef(bitmap); return 0; } void *pixels; if (AndroidBitmap_lockPixels(env, bitmap, &pixels) < 0) { env->DeleteLocalRef(bitmap); return 0; } if (info.stride == uint(img.bytesPerLine()) && info.width == uint(img.width()) && info.height == uint(img.height())) { memcpy(pixels, img.constBits(), info.stride * info.height); } else { uchar *bmpPtr = static_cast<uchar *>(pixels); const unsigned width = qMin(info.width, (uint)img.width()); //should be the same const unsigned height = qMin(info.height, (uint)img.height()); //should be the same for (unsigned y = 0; y < height; y++, bmpPtr += info.stride) memcpy(bmpPtr, img.constScanLine(y), width); } AndroidBitmap_unlockPixels(env, bitmap); return bitmap; }
const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& validAlpha, bool& alphaAsMask) { QImage image = srcImage; validAlpha = false; alphaAsMask = true; const uint8 OPAQUE_ALPHA = 255; const uint8 TRANSPARENT_ALPHA = 0; if (image.hasAlphaChannel()) { std::map<uint8, uint32> alphaHistogram; if (image.format() != QImage::Format_ARGB32) { image = image.convertToFormat(QImage::Format_ARGB32); } // Actual alpha channel? create the histogram for (int y = 0; y < image.height(); ++y) { const QRgb* data = reinterpret_cast<const QRgb*>(image.constScanLine(y)); for (int x = 0; x < image.width(); ++x) { auto alpha = qAlpha(data[x]); alphaHistogram[alpha] ++; validAlpha = validAlpha || (alpha != OPAQUE_ALPHA); } } // If alpha was meaningfull refine if (validAlpha && (alphaHistogram.size() > 1)) { auto totalNumPixels = image.height() * image.width(); auto numOpaques = alphaHistogram[OPAQUE_ALPHA]; auto numTransparents = alphaHistogram[TRANSPARENT_ALPHA]; auto numTranslucents = totalNumPixels - numOpaques - numTransparents; alphaAsMask = ((numTranslucents / (double)totalNumPixels) < 0.05); } } if (!validAlpha && image.format() != QImage::Format_RGB888) { image = image.convertToFormat(QImage::Format_RGB888); } return image; }
void CaViewerCore::beginCalcIntensity(QList<QGraphicsPixmapItem*> lRoi) { // static const QString sProgressFormat = QObject::tr("Calculating... %p%"); m_lockImage->lockForRead(); QList<QList<QImage> > maskByHeight; QList<QList<QGraphicsPixmapItem*> > lRef; QList<QList<QPoint> > lPos; QList<QList<EigenRealVector*> > lIntensityRef; QList<EigenRealVector*> lRetIntensity; for(int count = 0; count < m_lImage->size(); ++count) { maskByHeight << QList<QImage>(); lRef << QList<QGraphicsPixmapItem*>(); lPos << QList<QPoint>(); lIntensityRef << QList<EigenRealVector*>(); } // Set group by height const int timeSize = m_lImage->first().size(); for(int count = 0; count < lRoi.size(); ++count) { QGraphicsPixmapItem* const roi = lRoi.at(count); const int height = roi->zValue(); maskByHeight[height] << roi->pixmap().toImage(); lRef[height] << lRoi.at(count); lPos[height] << roi->pos().toPoint(); EigenRealVector* vec = new EigenRealVector(); *vec = EigenRealVector::Zero(timeSize); lRetIntensity << vec; lIntensityRef[height] << vec; } // Sum for(int height = 0; height < maskByHeight.size(); ++height) { //#pragma omp parallel for schedule(static) for(int time = 0; time < timeSize; ++time) { const cv::Mat_<quint16> image = m_lImage->at(height).at(time); for(int count = 0; count < maskByHeight[height].size(); ++count) { const QImage mask = maskByHeight.at(height).at(count); qreal* const buf = static_cast<qreal*>(lIntensityRef.at(height).at(count)->data()); const QPoint offset = lPos.at(height).at(count); for(int row = 0; row < mask.height(); ++row) { const QRgb* const maskVal = reinterpret_cast<const QRgb*>(mask.constScanLine(row)); const quint16* const imgVal = reinterpret_cast<const quint16*>(image.data + (row + offset.y()) * image.step); for(int col = 0; col < mask.width(); ++col) buf[time] += static_cast<qreal>(imgVal[col + offset.x()]) * qAlpha(maskVal[col]); } } } // emit changedProgressValue(100.0 * height / maskByHeight.size(), sProgressFormat); } m_lockImage->unlock(); // Normalize for(int count = 0; count < lRetIntensity.size(); ++count) { EigenRealVector* const intensity = lRetIntensity.at(count); intensity->array() -= intensity->minCoeff(); *intensity /= intensity->maxCoeff(); // std::stringstream stream; // stream << "Roi " << height << count << ":\n" << *intensity << "\n"; // qDebug() << QString(stream.str().c_str()); } emit finishedCalcIntensity(lRoi, lRetIntensity); // beginCalcFrenetFrame(lRetIntensity); beginCalcPCA(lRetIntensity); }
static bool write_jpeg_image(const QImage &image, QIODevice *device, int sourceQuality) { bool success = false; const QVector<QRgb> cmap = image.colorTable(); struct jpeg_compress_struct cinfo; JSAMPROW row_pointer[1]; row_pointer[0] = 0; struct my_jpeg_destination_mgr *iod_dest = new my_jpeg_destination_mgr(device); struct my_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jerr.error_exit = my_error_exit; if (!setjmp(jerr.setjmp_buffer)) { // WARNING: // this if loop is inside a setjmp/longjmp branch // do not create C++ temporaries here because the destructor may never be called // if you allocate memory, make sure that you can free it (row_pointer[0]) jpeg_create_compress(&cinfo); cinfo.dest = iod_dest; cinfo.image_width = image.width(); cinfo.image_height = image.height(); bool gray=false; switch (image.format()) { case QImage::Format_Mono: case QImage::Format_MonoLSB: case QImage::Format_Indexed8: gray = true; for (int i = image.colorCount(); gray && i--;) { gray = gray & (qRed(cmap[i]) == qGreen(cmap[i]) && qRed(cmap[i]) == qBlue(cmap[i])); } cinfo.input_components = gray ? 1 : 3; cinfo.in_color_space = gray ? JCS_GRAYSCALE : JCS_RGB; break; default: cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; } jpeg_set_defaults(&cinfo); qreal diffInch = qAbs(image.dotsPerMeterX()*2.54/100. - qRound(image.dotsPerMeterX()*2.54/100.)) + qAbs(image.dotsPerMeterY()*2.54/100. - qRound(image.dotsPerMeterY()*2.54/100.)); qreal diffCm = (qAbs(image.dotsPerMeterX()/100. - qRound(image.dotsPerMeterX()/100.)) + qAbs(image.dotsPerMeterY()/100. - qRound(image.dotsPerMeterY()/100.)))*2.54; if (diffInch < diffCm) { cinfo.density_unit = 1; // dots/inch cinfo.X_density = qRound(image.dotsPerMeterX()*2.54/100.); cinfo.Y_density = qRound(image.dotsPerMeterY()*2.54/100.); } else { cinfo.density_unit = 2; // dots/cm cinfo.X_density = (image.dotsPerMeterX()+50) / 100; cinfo.Y_density = (image.dotsPerMeterY()+50) / 100; } int quality = sourceQuality >= 0 ? qMin(sourceQuality,100) : 75; #if defined(Q_OS_UNIXWARE) jpeg_set_quality(&cinfo, quality, B_TRUE /* limit to baseline-JPEG values */); jpeg_start_compress(&cinfo, B_TRUE); #else jpeg_set_quality(&cinfo, quality, true /* limit to baseline-JPEG values */); jpeg_start_compress(&cinfo, true); #endif row_pointer[0] = new uchar[cinfo.image_width*cinfo.input_components]; int w = cinfo.image_width; while (cinfo.next_scanline < cinfo.image_height) { uchar *row = row_pointer[0]; switch (image.format()) { case QImage::Format_Mono: case QImage::Format_MonoLSB: if (gray) { const uchar* data = image.constScanLine(cinfo.next_scanline); if (image.format() == QImage::Format_MonoLSB) { for (int i=0; i<w; i++) { bool bit = !!(*(data + (i >> 3)) & (1 << (i & 7))); row[i] = qRed(cmap[bit]); } } else { for (int i=0; i<w; i++) { bool bit = !!(*(data + (i >> 3)) & (1 << (7 -(i & 7)))); row[i] = qRed(cmap[bit]); } } } else { const uchar* data = image.constScanLine(cinfo.next_scanline); if (image.format() == QImage::Format_MonoLSB) { for (int i=0; i<w; i++) { bool bit = !!(*(data + (i >> 3)) & (1 << (i & 7))); *row++ = qRed(cmap[bit]); *row++ = qGreen(cmap[bit]); *row++ = qBlue(cmap[bit]); } } else { for (int i=0; i<w; i++) { bool bit = !!(*(data + (i >> 3)) & (1 << (7 -(i & 7)))); *row++ = qRed(cmap[bit]); *row++ = qGreen(cmap[bit]); *row++ = qBlue(cmap[bit]); } } }
void VideoThumbnailer::Private::slotProcessframe(QVideoFrame frm) { if (player->mediaStatus() != QMediaPlayer::BufferedMedia || player->position() <= 0) { if (++errorCount > 1000) { qCDebug(DIGIKAM_GENERAL_LOG) << "Error: Video data are corrupted from " << fileName(); isReady = true; player->setMedia(QMediaContent()); dd->emit signalThumbnailFailed(filePath()); return; } else { player->setPosition(++position); return; } } qCDebug(DIGIKAM_GENERAL_LOG) << "Video frame extraction from " << fileName() << " at position " << position; if (!frm.isValid()) { qCDebug(DIGIKAM_GENERAL_LOG) << "Error: Video frame is not valid."; isReady = true; player->setMedia(QMediaContent()); dd->emit signalThumbnailFailed(filePath()); return; } QImage img = imageFromVideoFrame(frm); if (!img.isNull()) { img = img.scaled(thumbSize, thumbSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); if (createStrip && img.width() > strip.width() && img.height() > strip.height()) { // Add a video strip on the left side of video thumb. for (int y = 0; y < img.height(); y += strip.height()) { for (int ys = 0 ; ys < strip.height() ; ys++) { int pos = y + ys; if (pos < img.height()) { memcpy((void*)img.constScanLine(pos), (void*)strip.constScanLine(ys), strip.bytesPerLine()); } } } } qCDebug(DIGIKAM_GENERAL_LOG) << "Video frame extracted with size " << img.size(); isReady = true; player->setMedia(QMediaContent()); dd->emit signalThumbnailDone(filePath(), img.copy()); } else { qCDebug(DIGIKAM_GENERAL_LOG) << "Video frame format is not supported: " << frm; isReady = true; player->setMedia(QMediaContent()); dd->emit signalThumbnailFailed(filePath()); } }
QVector<float> AutoCorrelation::extract(const QImage &data, const int &x, const int &y) const { const int w = mSize.width(); const int h = mSize.height(); const int dw = data.width(); const int dh = data.height(); ComplexArray *ca = new ComplexArray(boost::extents[w][h]); for (int ay = 0; ay < h; ay++) { int py = (y - h / 2 + ay) + dh; while (py >= dh) { py -= dh; } #ifdef HAS_IMAGE_CONSTSCANLINE const uchar *d = data.constScanLine(py); #else const uchar *d = data.scanLine(py); #endif for (int ax = 0; ax < w; ax++) { int px = (x - w / 2 + ax) + dw; while (px >= dw) { px -= dw; } (*ca)[ay][ax] = Complex(d[px], 0); } } perform(ca); float minm = 0; float maxm = 0; for (int j = 0; j < w; j++) { for (int k = 0; k < h; k++) { float magnitude = (*ca)[j][k].abs(); if (magnitude > maxm) { maxm = magnitude; } else if (magnitude < minm) { minm = magnitude; } } } float c = 255.0 / log(1.0 + abs(maxm - minm)); TwoDArray *img = new TwoDArray(boost::extents[w][h]); TwoDArray *flip = new TwoDArray(boost::extents[w][h]); for (int ay = 0; ay < h; ay++) { int py = (y - h / 2 + ay) + dh; while (py >= dh) { py -= dh; } #ifdef HAS_IMAGE_CONSTSCANLINE const uchar *d = data.constScanLine(py); #else const uchar *d = data.scanLine(py); #endif for (int ax = 0; ax < w; ax++) { int px = (x - w / 2 + ax) + dw; while (px >= dw) { px -= dw; } const float f = c * log(1.0 + (*ca)[ay][ax].abs()); //const float f = d[px]; (*img)[ay][ax] = f; (*flip)[ay][w - ax - 1] = f; } } QVector<float> result(h); float *resultPtr = result.data(); for (int i = 0; i < h; i++) { for (int ay = 0; ay < h; ay++) { for (int ax = 0; ax < w; ax++) { const float f = float((*img)[ay][ax] * (*flip)[ay][(ax + i + w - 1) % w]) / float(65535); resultPtr[i] += f; } } } delete ca; delete img; delete flip; return result; }
DtwImagePrivate::DtwImagePrivate(DtwImage *q, QImage img) : q_ptr(q), size(img.size()), NM(size.height() * size.width()), colors(NM), cells(NM), startingCell(0) { BENCHMARK_START(); if (img.format() != q->DTW_FORMAT) img = img.convertToFormat(q->DTW_FORMAT, Qt::AutoColor); const int height = size.height(); const int width = size.width(); if (height < 3 || width < 3) throw std::invalid_argument("Incorrect image dimensions"); //Fillin colors { int k = 0; for (int i = 0; i < height; i++) { const QRgb* rawLine = reinterpret_cast<const QRgb*>(img.constScanLine(i)); for (int j = 0; j < width; j++) { colors[k++] = rawLine[j]; } } } //Establish connections and calculate energy { const int down = width; const int right = 1; cells[0].neighbours[LEFT] = INVALID_INDEX; cells[0].neighbours[UP] = INVALID_INDEX; cells[0].neighbours[RIGHT] = right; cells[0].neighbours[DOWN] = down; #ifdef DIAGONAL_NEIGHBOURS cells[0].neighbours[DOWN_LEFT] = INVALID_INDEX; cells[0].neighbours[UP_LEFT] = INVALID_INDEX; cells[0].neighbours[UP_RIGHT] = INVALID_INDEX; cells[0].neighbours[DOWN_RIGHT] = down + 1; #endif cells[0].energy = dualGradientEnergy(0, right, 0, down); } for (int j = 1; j < width - 1; j++) { const int down = j + width; const int right = j + 1; const int left = j - 1; cells[j].neighbours[UP] = INVALID_INDEX; cells[j].neighbours[RIGHT] = right; cells[j].neighbours[DOWN] = down; cells[j].neighbours[LEFT] = left; #ifdef DIAGONAL_NEIGHBOURS cells[j].neighbours[UP_LEFT] = INVALID_INDEX; cells[j].neighbours[UP_RIGHT] = INVALID_INDEX; cells[j].neighbours[DOWN_RIGHT] = down + 1; cells[j].neighbours[DOWN_LEFT] = down - 1; #endif cells[j].energy = dualGradientEnergy(left, right, j, down); } { int k = width - 1; const int down = k + width;; const int left = k - 1; cells[k].neighbours[UP] = INVALID_INDEX; cells[k].neighbours[RIGHT] = INVALID_INDEX; cells[k].neighbours[DOWN] = down; cells[k].neighbours[LEFT] = left; #ifdef DIAGONAL_NEIGHBOURS cells[k].neighbours[UP_LEFT] = INVALID_INDEX; cells[k].neighbours[UP_RIGHT] = INVALID_INDEX; cells[k].neighbours[DOWN_RIGHT] = INVALID_INDEX; cells[k].neighbours[DOWN_LEFT] = down - 1; #endif cells[k].energy = dualGradientEnergy( left, k, k, down ); } int k = width; for (int i = 1; i < height - 1; i++) { { const int up = k - width; const int down = k + width; const int right = k + 1; cells[k].neighbours[LEFT] = INVALID_INDEX; cells[k].neighbours[UP] = up; cells[k].neighbours[RIGHT] = right; cells[k].neighbours[DOWN] = down; #ifdef DIAGONAL_NEIGHBOURS cells[k].neighbours[DOWN_LEFT] = INVALID_INDEX; cells[k].neighbours[UP_LEFT] = INVALID_INDEX; cells[k].neighbours[DOWN_RIGHT] = down + 1; cells[k].neighbours[UP_RIGHT] = up + 1; #endif cells[k].energy = dualGradientEnergy( k, right, up, down ); k++; } for (int j = 1; j < width - 1; j++) { const int up = k - width; const int down = k + width; const int left = k - 1; const int right = k + 1; cells[k].neighbours[UP] = up; cells[k].neighbours[RIGHT] = right; cells[k].neighbours[DOWN] = down; cells[k].neighbours[LEFT] = left; #ifdef DIAGONAL_NEIGHBOURS cells[k].neighbours[UP_LEFT] = up - 1; cells[k].neighbours[UP_RIGHT] = up + 1; cells[k].neighbours[DOWN_RIGHT] = down + 1; cells[k].neighbours[DOWN_LEFT] = down - 1; #endif cells[k].energy = dualGradientEnergy( left, right, up, down ); k++; } { const int up = k - width; const int down = k + width; const int left = k - 1; cells[k].neighbours[UP] = up; cells[k].neighbours[RIGHT] = INVALID_INDEX; cells[k].neighbours[DOWN] = down; cells[k].neighbours[LEFT] = left; #ifdef DIAGONAL_NEIGHBOURS cells[k].neighbours[UP_LEFT] = up - 1; cells[k].neighbours[UP_RIGHT] = INVALID_INDEX; cells[k].neighbours[DOWN_RIGHT] = INVALID_INDEX; cells[k].neighbours[DOWN_LEFT] = down - 1; #endif cells[k].energy = dualGradientEnergy( left, k, up, down ); k++; } } { const int up = k - width; const int right = k + 1; cells[k].neighbours[LEFT] = INVALID_INDEX; cells[k].neighbours[UP] = up; cells[k].neighbours[RIGHT] = right; cells[k].neighbours[DOWN] = INVALID_INDEX; #ifdef DIAGONAL_NEIGHBOURS cells[k].neighbours[DOWN_LEFT] = INVALID_INDEX; cells[k].neighbours[UP_LEFT] = INVALID_INDEX; cells[k].neighbours[UP_RIGHT] = up + 1; cells[k].neighbours[DOWN_RIGHT] = INVALID_INDEX; #endif cells[k].energy = dualGradientEnergy( k, right, up, k ); k++; } for (int j = 1; j < width - 1; j++) { const int up = k - width; const int left = k - 1; const int right = k + 1; cells[k].neighbours[UP] = up; cells[k].neighbours[RIGHT] = right; cells[k].neighbours[DOWN] = INVALID_INDEX; cells[k].neighbours[LEFT] = left; #ifdef DIAGONAL_NEIGHBOURS cells[k].neighbours[UP_LEFT] = up - 1; cells[k].neighbours[UP_RIGHT] = up + 1; cells[k].neighbours[DOWN_RIGHT] = INVALID_INDEX; cells[k].neighbours[DOWN_LEFT] = INVALID_INDEX; #endif cells[k].energy = dualGradientEnergy( left, right, up, k ); k++; } { const int up = k - width; const int left = k - 1; cells[k].neighbours[UP] = up; cells[k].neighbours[RIGHT] = INVALID_INDEX; cells[k].neighbours[DOWN] = INVALID_INDEX; cells[k].neighbours[LEFT] = left; #ifdef DIAGONAL_NEIGHBOURS cells[k].neighbours[UP_LEFT] = up - 1; cells[k].neighbours[UP_RIGHT] = INVALID_INDEX; cells[k].neighbours[DOWN_RIGHT] = INVALID_INDEX; cells[k].neighbours[DOWN_LEFT] = INVALID_INDEX; #endif cells[k].energy = dualGradientEnergy( left, k, up, k ); } Q_ASSERT(++k == NM); BENCHMARK_STOP(); }
void QgsCubicRasterResampler::resample( const QImage& srcImage, QImage& dstImage ) { int nCols = srcImage.width(); int nRows = srcImage.height(); int pos = 0; QRgb px; int *redMatrix = new int[ nCols * nRows ]; int *greenMatrix = new int[ nCols * nRows ]; int *blueMatrix = new int[ nCols * nRows ]; int *alphaMatrix = new int[ nCols * nRows ]; for ( int heightIndex = 0; heightIndex < nRows; ++heightIndex ) { QRgb* scanLine = ( QRgb* )srcImage.constScanLine( heightIndex ); for ( int widthIndex = 0; widthIndex < nCols; ++widthIndex ) { px = scanLine[widthIndex]; int alpha = qAlpha( px ); alphaMatrix[pos] = alpha; redMatrix[pos] = qRed( px ); greenMatrix[pos] = qGreen( px ); blueMatrix[pos] = qBlue( px ); pos++; } } //derivative x double* xDerivativeMatrixRed = new double[ nCols * nRows ]; xDerivativeMatrix( nCols, nRows, xDerivativeMatrixRed, redMatrix ); double* xDerivativeMatrixGreen = new double[ nCols * nRows ]; xDerivativeMatrix( nCols, nRows, xDerivativeMatrixGreen, greenMatrix ); double* xDerivativeMatrixBlue = new double[ nCols * nRows ]; xDerivativeMatrix( nCols, nRows, xDerivativeMatrixBlue, blueMatrix ); double* xDerivativeMatrixAlpha = new double[ nCols * nRows ]; xDerivativeMatrix( nCols, nRows, xDerivativeMatrixAlpha, alphaMatrix ); //derivative y double* yDerivativeMatrixRed = new double[ nCols * nRows ]; yDerivativeMatrix( nCols, nRows, yDerivativeMatrixRed, redMatrix ); double* yDerivativeMatrixGreen = new double[ nCols * nRows ]; yDerivativeMatrix( nCols, nRows, yDerivativeMatrixGreen, greenMatrix ); double* yDerivativeMatrixBlue = new double[ nCols * nRows ]; yDerivativeMatrix( nCols, nRows, yDerivativeMatrixBlue, blueMatrix ); double* yDerivativeMatrixAlpha = new double[ nCols * nRows ]; yDerivativeMatrix( nCols, nRows, yDerivativeMatrixAlpha, alphaMatrix ); //compute output double nSrcPerDstX = ( double ) srcImage.width() / ( double ) dstImage.width(); double nSrcPerDstY = ( double ) srcImage.height() / ( double ) dstImage.height(); double currentSrcRow = nSrcPerDstY / 2.0 - 0.5; double currentSrcCol; int currentSrcColInt; int currentSrcRowInt; int lastSrcColInt = -100; int lastSrcRowInt = -100; //bernstein polynomials double bp0u, bp1u, bp2u, bp3u, bp0v, bp1v, bp2v, bp3v; double u, v; for ( int y = 0; y < dstImage.height(); ++y ) { currentSrcRowInt = floor( currentSrcRow ); v = currentSrcRow - currentSrcRowInt; currentSrcCol = nSrcPerDstX / 2.0 - 0.5; QRgb* scanLine = ( QRgb* )dstImage.scanLine( y ); for ( int x = 0; x < dstImage.width(); ++x ) { currentSrcColInt = floor( currentSrcCol ); u = currentSrcCol - currentSrcColInt; //handle eight edge-cases if (( currentSrcRowInt < 0 || currentSrcRowInt >= ( srcImage.height() - 1 ) || currentSrcColInt < 0 || currentSrcColInt >= ( srcImage.width() - 1 ) ) ) { QRgb px1, px2; //pixels at the border of the source image needs to be handled in a special way if ( currentSrcRowInt < 0 && currentSrcColInt < 0 ) { scanLine[x] = srcImage.pixel( 0, 0 ); } else if ( currentSrcRowInt < 0 && currentSrcColInt >= ( srcImage.width() - 1 ) ) { scanLine[x] = srcImage.pixel( srcImage.width() - 1, 0 ); } else if ( currentSrcRowInt >= ( srcImage.height() - 1 ) && currentSrcColInt >= ( srcImage.width() - 1 ) ) { scanLine[x] = srcImage.pixel( srcImage.width() - 1, srcImage.height() - 1 ); } else if ( currentSrcRowInt >= ( srcImage.height() - 1 ) && currentSrcColInt < 0 ) { scanLine[x] = srcImage.pixel( 0, srcImage.height() - 1 ); } else if ( currentSrcRowInt < 0 ) { px1 = srcImage.pixel( currentSrcColInt, 0 ); px2 = srcImage.pixel( currentSrcColInt + 1, 0 ); scanLine[x] = curveInterpolation( px1, px2, u, xDerivativeMatrixRed[ currentSrcColInt ], xDerivativeMatrixGreen[ currentSrcColInt ], xDerivativeMatrixBlue[ currentSrcColInt ], xDerivativeMatrixAlpha[ currentSrcColInt ], xDerivativeMatrixRed[ currentSrcColInt + 1 ], xDerivativeMatrixGreen[ currentSrcColInt + 1 ], xDerivativeMatrixBlue[ currentSrcColInt + 1 ], xDerivativeMatrixAlpha[ currentSrcColInt + 1 ] ); } else if ( currentSrcRowInt >= ( srcImage.height() - 1 ) ) { int idx = ( srcImage.height() - 1 ) * srcImage.width() + currentSrcColInt; px1 = srcImage.pixel( currentSrcColInt, srcImage.height() - 1 ); px2 = srcImage.pixel( currentSrcColInt + 1, srcImage.height() - 1 ); scanLine[x] = curveInterpolation( px1, px2, u, xDerivativeMatrixRed[ idx ], xDerivativeMatrixGreen[ idx ], xDerivativeMatrixBlue[idx], xDerivativeMatrixAlpha[idx], xDerivativeMatrixRed[ idx + 1 ], xDerivativeMatrixGreen[ idx + 1 ], xDerivativeMatrixBlue[idx + 1], xDerivativeMatrixAlpha[idx + 1] ); } else if ( currentSrcColInt < 0 ) { int idx1 = currentSrcRowInt * srcImage.width(); int idx2 = idx1 + srcImage.width(); px1 = srcImage.pixel( 0, currentSrcRowInt ); px2 = srcImage.pixel( 0, currentSrcRowInt + 1 ); scanLine[x] = curveInterpolation( px1, px2, v, yDerivativeMatrixRed[ idx1 ], yDerivativeMatrixGreen[ idx1 ], yDerivativeMatrixBlue[ idx1], yDerivativeMatrixAlpha[ idx1], yDerivativeMatrixRed[ idx2 ], yDerivativeMatrixGreen[ idx2 ], yDerivativeMatrixBlue[ idx2], yDerivativeMatrixAlpha[ idx2] ); } else if ( currentSrcColInt >= ( srcImage.width() - 1 ) ) { int idx1 = currentSrcRowInt * srcImage.width() + srcImage.width() - 1; int idx2 = idx1 + srcImage.width(); px1 = srcImage.pixel( srcImage.width() - 1, currentSrcRowInt ); px2 = srcImage.pixel( srcImage.width() - 1, currentSrcRowInt + 1 ); scanLine[x] = curveInterpolation( px1, px2, v, yDerivativeMatrixRed[ idx1 ], yDerivativeMatrixGreen[ idx1 ], yDerivativeMatrixBlue[ idx1], yDerivativeMatrixAlpha[ idx1], yDerivativeMatrixRed[ idx2 ], yDerivativeMatrixGreen[ idx2 ], yDerivativeMatrixBlue[ idx2], yDerivativeMatrixAlpha[ idx2] ); } currentSrcCol += nSrcPerDstX; continue; } //first update the control points if necessary if ( currentSrcColInt != lastSrcColInt || currentSrcRowInt != lastSrcRowInt ) { calculateControlPoints( nCols, nRows, currentSrcRowInt, currentSrcColInt, redMatrix, greenMatrix, blueMatrix, alphaMatrix, xDerivativeMatrixRed, xDerivativeMatrixGreen, xDerivativeMatrixBlue, xDerivativeMatrixAlpha, yDerivativeMatrixRed, yDerivativeMatrixGreen, yDerivativeMatrixBlue, yDerivativeMatrixAlpha ); } //bernstein polynomials bp0u = calcBernsteinPolyN3( 0, u ); bp1u = calcBernsteinPolyN3( 1, u ); bp2u = calcBernsteinPolyN3( 2, u ); bp3u = calcBernsteinPolyN3( 3, u ); bp0v = calcBernsteinPolyN3( 0, v ); bp1v = calcBernsteinPolyN3( 1, v ); bp2v = calcBernsteinPolyN3( 2, v ); bp3v = calcBernsteinPolyN3( 3, v ); //then calculate value based on bernstein form of Bezier patch //todo: move into function int r = bp0u * bp0v * cRed00 + bp1u * bp0v * cRed10 + bp2u * bp0v * cRed20 + bp3u * bp0v * cRed30 + bp0u * bp1v * cRed01 + bp1u * bp1v * cRed11 + bp2u * bp1v * cRed21 + bp3u * bp1v * cRed31 + bp0u * bp2v * cRed02 + bp1u * bp2v * cRed12 + bp2u * bp2v * cRed22 + bp3u * bp2v * cRed32 + bp0u * bp3v * cRed03 + bp1u * bp3v * cRed13 + bp2u * bp3v * cRed23 + bp3u * bp3v * cRed33; int g = bp0u * bp0v * cGreen00 + bp1u * bp0v * cGreen10 + bp2u * bp0v * cGreen20 + bp3u * bp0v * cGreen30 + bp0u * bp1v * cGreen01 + bp1u * bp1v * cGreen11 + bp2u * bp1v * cGreen21 + bp3u * bp1v * cGreen31 + bp0u * bp2v * cGreen02 + bp1u * bp2v * cGreen12 + bp2u * bp2v * cGreen22 + bp3u * bp2v * cGreen32 + bp0u * bp3v * cGreen03 + bp1u * bp3v * cGreen13 + bp2u * bp3v * cGreen23 + bp3u * bp3v * cGreen33; int b = bp0u * bp0v * cBlue00 + bp1u * bp0v * cBlue10 + bp2u * bp0v * cBlue20 + bp3u * bp0v * cBlue30 + bp0u * bp1v * cBlue01 + bp1u * bp1v * cBlue11 + bp2u * bp1v * cBlue21 + bp3u * bp1v * cBlue31 + bp0u * bp2v * cBlue02 + bp1u * bp2v * cBlue12 + bp2u * bp2v * cBlue22 + bp3u * bp2v * cBlue32 + bp0u * bp3v * cBlue03 + bp1u * bp3v * cBlue13 + bp2u * bp3v * cBlue23 + bp3u * bp3v * cBlue33; int a = bp0u * bp0v * cAlpha00 + bp1u * bp0v * cAlpha10 + bp2u * bp0v * cAlpha20 + bp3u * bp0v * cAlpha30 + bp0u * bp1v * cAlpha01 + bp1u * bp1v * cAlpha11 + bp2u * bp1v * cAlpha21 + bp3u * bp1v * cAlpha31 + bp0u * bp2v * cAlpha02 + bp1u * bp2v * cAlpha12 + bp2u * bp2v * cAlpha22 + bp3u * bp2v * cAlpha32 + bp0u * bp3v * cAlpha03 + bp1u * bp3v * cAlpha13 + bp2u * bp3v * cAlpha23 + bp3u * bp3v * cAlpha33; scanLine[x] = createPremultipliedColor( r, g, b, a ); lastSrcColInt = currentSrcColInt; currentSrcCol += nSrcPerDstX; } lastSrcRowInt = currentSrcRowInt; currentSrcRow += nSrcPerDstY; } //cleanup memory delete[] redMatrix; delete[] greenMatrix; delete[] blueMatrix; delete[] alphaMatrix; delete[] xDerivativeMatrixRed; delete[] xDerivativeMatrixGreen; delete[] xDerivativeMatrixBlue; delete[] xDerivativeMatrixAlpha; delete[] yDerivativeMatrixRed; delete[] yDerivativeMatrixGreen; delete[] yDerivativeMatrixBlue; delete[] yDerivativeMatrixAlpha; }
static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QByteArray &sourceFormat) { QByteArray str; QImage image = sourceImage; QByteArray format = sourceFormat; format = format.left(3); // ignore RAW part bool gray = format == "pgm"; if (format == "pbm") { image = image.convertToFormat(QImage::Format_Mono); } else if (gray) { image = image.convertToFormat(QImage::Format_Grayscale8); } else { switch (image.format()) { case QImage::Format_Mono: case QImage::Format_MonoLSB: image = image.convertToFormat(QImage::Format_Indexed8); break; case QImage::Format_Indexed8: case QImage::Format_RGB32: case QImage::Format_ARGB32: break; default: if (image.hasAlphaChannel()) image = image.convertToFormat(QImage::Format_ARGB32); else image = image.convertToFormat(QImage::Format_RGB32); break; } } if (image.depth() == 1 && image.colorCount() == 2) { if (qGray(image.color(0)) < qGray(image.color(1))) { // 0=dark/black, 1=light/white - invert image.detach(); for (int y=0; y<image.height(); y++) { uchar *p = image.scanLine(y); uchar *end = p + image.bytesPerLine(); while (p < end) *p++ ^= 0xff; } } } uint w = image.width(); uint h = image.height(); str = "P\n"; str += QByteArray::number(w); str += ' '; str += QByteArray::number(h); str += '\n'; switch (image.depth()) { case 1: { str.insert(1, '4'); if (out->write(str, str.length()) != str.length()) return false; w = (w+7)/8; for (uint y=0; y<h; y++) { uchar* line = image.scanLine(y); if (w != (uint)out->write((char*)line, w)) return false; } } break; case 8: { str.insert(1, gray ? '5' : '6'); str.append("255\n"); if (out->write(str, str.length()) != str.length()) return false; uint bpl = w * (gray ? 1 : 3); uchar *buf = new uchar[bpl]; if (image.format() == QImage::Format_Indexed8) { QVector<QRgb> color = image.colorTable(); for (uint y=0; y<h; y++) { const uchar *b = image.constScanLine(y); uchar *p = buf; uchar *end = buf+bpl; if (gray) { while (p < end) { uchar g = (uchar)qGray(color[*b++]); *p++ = g; } } else { while (p < end) { QRgb rgb = color[*b++]; *p++ = qRed(rgb); *p++ = qGreen(rgb); *p++ = qBlue(rgb); } } if (bpl != (uint)out->write((char*)buf, bpl)) return false; } } else { for (uint y=0; y<h; y++) { const uchar *b = image.constScanLine(y); uchar *p = buf; uchar *end = buf + bpl; if (gray) { while (p < end) *p++ = *b++; } else { while (p < end) { uchar color = *b++; *p++ = color; *p++ = color; *p++ = color; } } if (bpl != (uint)out->write((char*)buf, bpl)) return false; } } delete [] buf; break; } case 32: { str.insert(1, '6'); str.append("255\n"); if (out->write(str, str.length()) != str.length()) return false; uint bpl = w * 3; uchar *buf = new uchar[bpl]; for (uint y=0; y<h; y++) { const QRgb *b = reinterpret_cast<const QRgb *>(image.constScanLine(y)); uchar *p = buf; uchar *end = buf+bpl; while (p < end) { QRgb rgb = *b++; *p++ = qRed(rgb); *p++ = qGreen(rgb); *p++ = qBlue(rgb); } if (bpl != (uint)out->write((char*)buf, bpl)) return false; } delete [] buf; break; } default: return false; } return true; }
// return average value of fft power iterating over r values QVector<float> FFT::extract(const QImage &data, const int &x, const int &y) const { // the array created here might be bigger than image size - it has to be // a square of side length 2^n const int w = mSize.width(); const int h = mSize.height(); const int dw = data.width(); const int dh = data.height(); ComplexArray *ca = new ComplexArray(boost::extents[w][h]); // fill only the data that exists in the image for (int ay = 0; ay < h; ay++) { int py = (y - h / 2 + ay) + dh; while (py >= dh) { py -= dh; } const float wY = mWindow.at(ay); #ifdef HAS_IMAGE_CONSTSCANLINE const uchar *d = data.constScanLine(py); #else const uchar *d = data.scanLine(py); #endif for (int ax = 0; ax < w; ax++) { const float wX = mWindow.at(ax); int px = (x - w / 2 + ax) + dw; while (px >= dw) { px -= dw; } (*ca)[ay][ax] = Complex(d[px] * wX * wY, 0); } } perform(ca); float minm = 0; float maxm = 0; for (int j = 0; j < w; j++) { for (int k = 0; k < h; k++) { float magnitude = (*ca)[j][k].abs(); if (magnitude > maxm) { maxm = magnitude; } else if (magnitude < minm) { minm = magnitude; } } } float c = 255.0 / log(1.0 + abs(maxm - minm)); QVector<float> result; const int maxR = w / 2; #ifdef HAS_VECTOR_RESERVE result.reserve(maxR); #endif for (int r = 1; r < maxR; r++) { int count = 0; float sum = 0; for (int i = 0; i < 360; i += 5) { const int x = r * cos(i) + maxR; const int y = r * sin(i) + maxR; float p = (*ca)[x][y].abs(); p = c * log(1.0 + p); sum += p; count++; } result.append(sum / count); } delete ca; return result; }
void KisBrush::generateMaskAndApplyMaskOrCreateDab(KisFixedPaintDeviceSP dst, ColoringInformation* coloringInformation, double scaleX, double scaleY, double angle, const KisPaintInformation& info_, double subPixelX, double subPixelY, qreal softnessFactor) const { Q_ASSERT(valid()); Q_UNUSED(info_); Q_UNUSED(softnessFactor); angle += d->angle; // Make sure the angle stay in [0;2*M_PI] if (angle < 0) angle += 2 * M_PI; if (angle > 2 * M_PI) angle -= 2 * M_PI; scaleX *= d->scale; scaleY *= d->scale; double scale = 0.5 * (scaleX + scaleY); prepareBrushPyramid(); QImage outputImage = d->brushPyramid->createImage(scale, -angle, subPixelX, subPixelY); qint32 maskWidth = outputImage.width(); qint32 maskHeight = outputImage.height(); dst->setRect(QRect(0, 0, maskWidth, maskHeight)); dst->initialize(); quint8* color = 0; if (coloringInformation) { if (dynamic_cast<PlainColoringInformation*>(coloringInformation)) { color = const_cast<quint8*>(coloringInformation->color()); } } const KoColorSpace *cs = dst->colorSpace(); qint32 pixelSize = cs->pixelSize(); quint8 *dabPointer = dst->data(); quint8 *rowPointer = dabPointer; quint8 *alphaArray = new quint8[maskWidth]; bool hasColor = this->hasColor(); for (int y = 0; y < maskHeight; y++) { #if QT_VERSION >= 0x040700 const quint8* maskPointer = outputImage.constScanLine(y); #else const quint8* maskPointer = outputImage.scanLine(y); #endif if (coloringInformation) { for (int x = 0; x < maskWidth; x++) { if (color) { memcpy(dabPointer, color, pixelSize); } else { memcpy(dabPointer, coloringInformation->color(), pixelSize); coloringInformation->nextColumn(); } dabPointer += pixelSize; } } if (hasColor) { const quint8 *src = maskPointer; quint8 *dst = alphaArray; for (int x = 0; x < maskWidth; x++) { const QRgb *c = reinterpret_cast<const QRgb*>(src); *dst = KoColorSpaceMaths<quint8>::multiply(255 - qGray(*c), qAlpha(*c)); src += 4; dst++; } } else { const quint8 *src = maskPointer; quint8 *dst = alphaArray; for (int x = 0; x < maskWidth; x++) { const QRgb *c = reinterpret_cast<const QRgb*>(src); *dst = KoColorSpaceMaths<quint8>::multiply(255 - *src, qAlpha(*c)); src += 4; dst++; } } cs->applyAlphaU8Mask(rowPointer, alphaArray, maskWidth); rowPointer += maskWidth * pixelSize; dabPointer = rowPointer; if (!color && coloringInformation) { coloringInformation->nextRow(); } } delete alphaArray; }
bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, const QString &description, int off_x_in, int off_y_in) { QPoint offset = image.offset(); int off_x = off_x_in + offset.x(); int off_y = off_y_in + offset.y(); png_structp png_ptr; png_infop info_ptr; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { return false; } png_set_error_fn(png_ptr, 0, 0, qt_png_warning); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, 0); return false; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); return false; } int quality = quality_in; if (quality >= 0) { if (quality > 9) { qWarning("PNG: Quality %d out of range", quality); quality = 9; } png_set_compression_level(png_ptr, quality); } png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn); int color_type = 0; if (image.colorCount()) { if (image.isGrayscale()) color_type = PNG_COLOR_TYPE_GRAY; else color_type = PNG_COLOR_TYPE_PALETTE; } else if (image.format() == QImage::Format_Grayscale8) color_type = PNG_COLOR_TYPE_GRAY; else if (image.hasAlphaChannel()) color_type = PNG_COLOR_TYPE_RGB_ALPHA; else color_type = PNG_COLOR_TYPE_RGB; png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(), image.depth() == 1 ? 1 : 8, // per channel color_type, 0, 0, 0); // sets #channels if (gamma != 0.0) { png_set_gAMA(png_ptr, info_ptr, 1.0/gamma); } if (image.format() == QImage::Format_MonoLSB) png_set_packswap(png_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE) { // Paletted int num_palette = qMin(256, image.colorCount()); png_color palette[256]; png_byte trans[256]; int num_trans = 0; for (int i=0; i<num_palette; i++) { QRgb rgba=image.color(i); palette[i].red = qRed(rgba); palette[i].green = qGreen(rgba); palette[i].blue = qBlue(rgba); trans[i] = qAlpha(rgba); if (trans[i] < 255) { num_trans = i+1; } } png_set_PLTE(png_ptr, info_ptr, palette, num_palette); if (num_trans) { png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0); } } // Swap ARGB to RGBA (normal PNG format) before saving on // BigEndian machines if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { png_set_swap_alpha(png_ptr); } // Qt==ARGB==Big(ARGB)==Little(BGRA). But RGB888 is RGB regardless if (QSysInfo::ByteOrder == QSysInfo::LittleEndian && image.format() != QImage::Format_RGB888) { png_set_bgr(png_ptr); } if (off_x || off_y) { png_set_oFFs(png_ptr, info_ptr, off_x, off_y, PNG_OFFSET_PIXEL); } if (frames_written > 0) png_set_sig_bytes(png_ptr, 8); if (image.dotsPerMeterX() > 0 || image.dotsPerMeterY() > 0) { png_set_pHYs(png_ptr, info_ptr, image.dotsPerMeterX(), image.dotsPerMeterY(), PNG_RESOLUTION_METER); } set_text(image, png_ptr, info_ptr, description); png_write_info(png_ptr, info_ptr); if (image.depth() != 1) png_set_packing(png_ptr); if (color_type == PNG_COLOR_TYPE_RGB && image.format() != QImage::Format_RGB888) png_set_filler(png_ptr, 0, QSysInfo::ByteOrder == QSysInfo::BigEndian ? PNG_FILLER_BEFORE : PNG_FILLER_AFTER); if (looping >= 0 && frames_written == 0) { uchar data[13] = "NETSCAPE2.0"; // 0123456789aBC data[0xB] = looping%0x100; data[0xC] = looping/0x100; png_write_chunk(png_ptr, const_cast<png_bytep>((const png_byte *)"gIFx"), data, 13); } if (ms_delay >= 0 || disposal!=Unspecified) { uchar data[4]; data[0] = disposal; data[1] = 0; data[2] = (ms_delay/10)/0x100; // hundredths data[3] = (ms_delay/10)%0x100; png_write_chunk(png_ptr, const_cast<png_bytep>((const png_byte *)"gIFg"), data, 4); } int height = image.height(); int width = image.width(); switch (image.format()) { case QImage::Format_Mono: case QImage::Format_MonoLSB: case QImage::Format_Indexed8: case QImage::Format_Grayscale8: case QImage::Format_RGB32: case QImage::Format_ARGB32: case QImage::Format_RGB888: { png_bytep* row_pointers = new png_bytep[height]; for (int y=0; y<height; y++) row_pointers[y] = const_cast<png_bytep>(image.constScanLine(y)); png_write_image(png_ptr, row_pointers); delete [] row_pointers; } break; default: { QImage::Format fmt = image.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32; QImage row; png_bytep row_pointers[1]; for (int y=0; y<height; y++) { row = image.copy(0, y, width, 1).convertToFormat(fmt); row_pointers[0] = const_cast<png_bytep>(row.constScanLine(0)); png_write_rows(png_ptr, row_pointers, 1); } } break; } png_write_end(png_ptr, info_ptr); frames_written++; png_destroy_write_struct(&png_ptr, &info_ptr); return true; }
void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subPixelPosition) { QImage mask = textureMapForGlyph(g, subPixelPosition); #ifdef CACHE_DEBUG printf("fillTexture of %dx%d at %d,%d in the cache of %dx%d\n", c.w, c.h, c.x, c.y, m_image.width(), m_image.height()); if (mask.width() > c.w || mask.height() > c.h) { printf(" ERROR; mask is bigger than reserved space! %dx%d instead of %dx%d\n", mask.width(), mask.height(), c.w,c.h); return; } #endif if (m_format == QFontEngine::Format_A32 || m_format == QFontEngine::Format_ARGB) { QImage ref(m_image.bits() + (c.x * 4 + c.y * m_image.bytesPerLine()), qMax(mask.width(), c.w), qMax(mask.height(), c.h), m_image.bytesPerLine(), m_image.format()); QPainter p(&ref); p.setCompositionMode(QPainter::CompositionMode_Source); p.fillRect(0, 0, c.w, c.h, QColor(0,0,0,0)); // TODO optimize this p.drawImage(0, 0, mask); p.end(); } else if (m_format == QFontEngine::Format_Mono) { if (mask.depth() > 1) { // TODO optimize this mask = mask.alphaChannel(); mask.invertPixels(); mask = mask.convertToFormat(QImage::Format_Mono); } int mw = qMin(mask.width(), c.w); int mh = qMin(mask.height(), c.h); uchar *d = m_image.bits(); int dbpl = m_image.bytesPerLine(); for (int y = 0; y < c.h; ++y) { uchar *dest = d + (c.y + y) *dbpl + c.x/8; if (y < mh) { const uchar *src = mask.constScanLine(y); for (int x = 0; x < c.w/8; ++x) { if (x < (mw+7)/8) dest[x] = src[x]; else dest[x] = 0; } } else { for (int x = 0; x < c.w/8; ++x) dest[x] = 0; } } } else { // A8 int mw = qMin(mask.width(), c.w); int mh = qMin(mask.height(), c.h); uchar *d = m_image.bits(); int dbpl = m_image.bytesPerLine(); if (mask.depth() == 1) { for (int y = 0; y < c.h; ++y) { uchar *dest = d + (c.y + y) *dbpl + c.x; if (y < mh) { const uchar *src = mask.constScanLine(y); for (int x = 0; x < c.w; ++x) { if (x < mw) dest[x] = (src[x >> 3] & (1 << (7 - (x & 7)))) > 0 ? 255 : 0; } } } } else if (mask.depth() == 8) { for (int y = 0; y < c.h; ++y) { uchar *dest = d + (c.y + y) *dbpl + c.x; if (y < mh) { const uchar *src = mask.constScanLine(y); for (int x = 0; x < c.w; ++x) { if (x < mw) dest[x] = src[x]; } } } } }
Q_SLOT void imgSlot(const QImage & img) { qDebug() << __FUNCTION__ << name(img.constScanLine(0)); }