! \internal Updates the internal map image buffer by going through the internal \ref QCPColorMapData and turning the data values into color pixels with \ref QCPColorGradient::colorize. This method is called by \ref QCPColorMap::draw if either the data has been modified or the map image has been invalidated for a different reason (e.g. a change of the data range with \ref setDataRan
| 25962 | setInterpolate is true. |
| 25963 | */ |
| 25964 | void QCPColorMap::updateMapImage() |
| 25965 | { |
| 25966 | QCPAxis *keyAxis = mKeyAxis.data(); |
| 25967 | if (!keyAxis) return; |
| 25968 | if (mMapData->isEmpty()) return; |
| 25969 | |
| 25970 | const QImage::Format format = QImage::Format_ARGB32_Premultiplied; |
| 25971 | const int keySize = mMapData->keySize(); |
| 25972 | const int valueSize = mMapData->valueSize(); |
| 25973 | int keyOversamplingFactor = mInterpolate ? 1 : (int)(1.0+100.0/(double)keySize); // make mMapImage have at least size 100, factor becomes 1 if size > 200 or interpolation is on |
| 25974 | int valueOversamplingFactor = mInterpolate ? 1 : (int)(1.0+100.0/(double)valueSize); // make mMapImage have at least size 100, factor becomes 1 if size > 200 or interpolation is on |
| 25975 | |
| 25976 | // resize mMapImage to correct dimensions including possible oversampling factors, according to key/value axes orientation: |
| 25977 | if (keyAxis->orientation() == Qt::Horizontal && (mMapImage.width() != keySize*keyOversamplingFactor || mMapImage.height() != valueSize*valueOversamplingFactor)) |
| 25978 | mMapImage = QImage(QSize(keySize*keyOversamplingFactor, valueSize*valueOversamplingFactor), format); |
| 25979 | else if (keyAxis->orientation() == Qt::Vertical && (mMapImage.width() != valueSize*valueOversamplingFactor || mMapImage.height() != keySize*keyOversamplingFactor)) |
| 25980 | mMapImage = QImage(QSize(valueSize*valueOversamplingFactor, keySize*keyOversamplingFactor), format); |
| 25981 | |
| 25982 | if (mMapImage.isNull()) |
| 25983 | { |
| 25984 | qDebug() << Q_FUNC_INFO << "Couldn't create map image (possibly too large for memory)"; |
| 25985 | mMapImage = QImage(QSize(10, 10), format); |
| 25986 | mMapImage.fill(Qt::black); |
| 25987 | } else |
| 25988 | { |
| 25989 | QImage *localMapImage = &mMapImage; // this is the image on which the colorization operates. Either the final mMapImage, or if we need oversampling, mUndersampledMapImage |
| 25990 | if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1) |
| 25991 | { |
| 25992 | // resize undersampled map image to actual key/value cell sizes: |
| 25993 | if (keyAxis->orientation() == Qt::Horizontal && (mUndersampledMapImage.width() != keySize || mUndersampledMapImage.height() != valueSize)) |
| 25994 | mUndersampledMapImage = QImage(QSize(keySize, valueSize), format); |
| 25995 | else if (keyAxis->orientation() == Qt::Vertical && (mUndersampledMapImage.width() != valueSize || mUndersampledMapImage.height() != keySize)) |
| 25996 | mUndersampledMapImage = QImage(QSize(valueSize, keySize), format); |
| 25997 | localMapImage = &mUndersampledMapImage; // make the colorization run on the undersampled image |
| 25998 | } else if (!mUndersampledMapImage.isNull()) |
| 25999 | mUndersampledMapImage = QImage(); // don't need oversampling mechanism anymore (map size has changed) but mUndersampledMapImage still has nonzero size, free it |
| 26000 | |
| 26001 | const double *rawData = mMapData->mData; |
| 26002 | const unsigned char *rawAlpha = mMapData->mAlpha; |
| 26003 | if (keyAxis->orientation() == Qt::Horizontal) |
| 26004 | { |
| 26005 | const int lineCount = valueSize; |
| 26006 | const int rowCount = keySize; |
| 26007 | for (int line=0; line<lineCount; ++line) |
| 26008 | { |
| 26009 | QRgb* pixels = reinterpret_cast<QRgb*>(localMapImage->scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system) |
| 26010 | if (rawAlpha) |
| 26011 | mGradient.colorize(rawData+line*rowCount, rawAlpha+line*rowCount, mDataRange, pixels, rowCount, 1, mDataScaleType==QCPAxis::stLogarithmic); |
| 26012 | else |
| 26013 | mGradient.colorize(rawData+line*rowCount, mDataRange, pixels, rowCount, 1, mDataScaleType==QCPAxis::stLogarithmic); |
| 26014 | } |
| 26015 | } else // keyAxis->orientation() == Qt::Vertical |
| 26016 | { |
| 26017 | const int lineCount = keySize; |
| 26018 | const int rowCount = valueSize; |
| 26019 | for (int line=0; line<lineCount; ++line) |
| 26020 | { |
| 26021 | QRgb* pixels = reinterpret_cast<QRgb*>(localMapImage->scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system) |