예제 #1
0
void FilterEffectRenderer::allocateBackingStoreIfNeeded()
{
    // At this point the effect chain has been built, and the
    // source image sizes set. We just need to attach the graphic
    // buffer if we have not yet done so.
    if (!m_graphicsBufferAttached) {
        IntSize logicalSize(m_sourceDrawingRegion.width(), m_sourceDrawingRegion.height());
        if (!sourceImage() || sourceImage()->logicalSize() != logicalSize)
            setSourceImage(ImageBuffer::create(logicalSize, 1, ColorSpaceDeviceRGB, renderingMode()));
        m_graphicsBufferAttached = true;
    }
}
void FilterEffectRenderer::allocateBackingStoreIfNeeded()
{
    // At this point the effect chain has been built, and the
    // source image sizes set. We just need to attach the graphic
    // buffer if we have not yet done so.
    if (!m_graphicsBufferAttached) {
        IntSize logicalSize(m_sourceDrawingRegion.width(), m_sourceDrawingRegion.height());
        if (!sourceImage() || sourceImage()->size() != logicalSize) {
            OwnPtr<ImageBufferSurface> surface = adoptPtr(new UnacceleratedImageBufferSurface(logicalSize));
            setSourceImage(ImageBuffer::create(surface.release()));
        }
        m_graphicsBufferAttached = true;
    }
}
예제 #3
0
    foreach (QFileInfo sourceInfo, sourceInfoList) {
        QImage sourceImage(sourceInfo.absoluteFilePath());
        QImage scaledSourceImage = sourceImage.scaled(225,225,Qt::KeepAspectRatio);
        int sourceWidth = sourceImage.width();
        int destWidth = scaledSourceImage.width();
        double scaleBackFactor = (double)sourceWidth/destWidth; // as we keep aspect ratio, this is sufficient to scale rectangle back
        qDebug() << sourceInfo.fileName();
        QList<QRect> destRects;
        QFileInfo destFileInfo = makeDestFileInfo(sourceDir, sourceInfo, destDir);
        if (faceCropper->crop(scaledSourceImage,destRects)) {
//            facelookupTable.addFile(sourceInfo, destRects, destFileInfo, scaleBackFactor);
            if (destRects.count()>1) {
                for (int i=0; i< destRects.count(); ++i) {
                    QRect destRect = destRects.at(i);
                    QRect destRectScaled(destRect.topLeft()*scaleBackFactor, destRect.bottomRight()*scaleBackFactor);
                    QImage destImage = sourceImage.copy(destRectScaled);
                    QString destString = destFileInfo.absolutePath();
                    destString.append(QDir::separator());
                    destDir.mkpath(destString);
                    destString.append(destFileInfo.completeBaseName());
                    destString.append("_");
                    destString.append(QString::number(i));
                    destString.append(".");
                    destString.append(destFileInfo.suffix());
                    destImage.save(destString);
                }
            } else if (destRects.count()==1){
                QRect destRect = destRects.first();
                QRect destRectScaled(destRect.topLeft()*scaleBackFactor, destRect.bottomRight()*scaleBackFactor);
                QImage destImage = sourceImage.copy(destRectScaled);
                destDir.mkpath(destFileInfo.absolutePath());
                destImage.save(destFileInfo.absoluteFilePath());
            }
        }
    }
예제 #4
0
void TerrainPageSurfaceLayer::fillImage(const TerrainPageGeometry& geometry, Image& image, unsigned int channel) const
{
	SegmentVector validSegments = geometry.getValidSegments();
	for (SegmentVector::const_iterator I = validSegments.begin(); I != validSegments.end(); ++I) {
		Mercator::Segment* segment = I->segment;
		if (mShader.checkIntersect(*segment)) {
			Mercator::Surface* surface = getSurfaceForSegment(segment);
			if (surface && surface->isValid()) {
				Image::ImageBuffer* textureBitmap = new Image::ImageBuffer(segment->getResolution(), 1);
				auto srcPtr = surface->getData();
				auto dataPtr = textureBitmap->getData();
				auto segmentSize = segment->getSize();
				for (int i = 0; i < segment->getResolution(); ++i) {
					for (int j = 0; j < segment->getResolution(); ++j) {
						//interpolate four samples to get the fragment coverage
						*dataPtr = (unsigned char)((srcPtr[(i * segmentSize) + j] + srcPtr[(i * segmentSize) + j + 1] + srcPtr[((i + 1) * segmentSize) + j] + srcPtr[((i + 1) * segmentSize) + j + 1]) / 4);
						dataPtr++;
					}
				}

				WFImage sourceImage(textureBitmap);
				image.blit(sourceImage, channel, ((int)I->index.x() * segment->getResolution()), ((mTerrainPageSurface.getNumberOfSegmentsPerAxis() - (int)I->index.y() - 1) * segment->getResolution()));
			}
		}
	}
}
예제 #5
0
void girarder::rotarplayer(tam grados)
{

    QPixmap sourceImage(*player->pixmap());
    QPixmap rotatePixmap(sourceImage.size());
    rotatePixmap.fill(Qt::transparent);

    QTransform transform;
    transform.translate(sourceImage.size().width() / 2, sourceImage.size().height() / 2);

    transform.rotate(grados);

    transform.translate(-sourceImage.size().width() / 2, -sourceImage.size().height() / 2);

    QPainter p;

    p.begin(&rotatePixmap);
    p.setTransform(transform);
    p.drawPixmap(0, 0, sourceImage);
    p.end();

    rotatePixmap.save(":/temp.png");

    player->setPixmap(rotatePixmap);
    player->giro = player->giro + grados;

}
//This method defines edges by applying a x and y mask. The magnitude of both directions x and y will be combined resulting a value that represents an edge.
void SobelFilter::CreateSobelImage(Image &destinationImage) {
	Image sourceImage(destinationImage);

	int srcHeight = sourceImage.GetHeight();
	int srcWidth = sourceImage.GetWidth();

	int dstHeight = destinationImage.GetHeight();
	int dstWidth = destinationImage.GetWidth();

	if (srcWidth != dstWidth && srcHeight != dstHeight) {
		std::cout << "Error images are not the same size" << std::endl;
		return;
	}

	//The masks
	double kernelY[3][3] = { {1, 0, -1 },
							{ 2, 0, -2 },
							{ 1, 0, -1 } };

	double kernelX[3][3] = { {	1,	2,  1 },
							 {	0,  0,  0 },
							 { -1, -2, -1 } };

	//For each pixel, apply the masks and combine them.
	for (int x = 1; x < dstWidth - 1; ++x){
		for (int y = 1; y < dstHeight - 1; ++y){
			double magX = 0.0;
			double magY = 0.0;

			//Applying the masks to the pixel resulting a magnitude for both the X and Y direction.
			for (int a = 0; a < 3; a++)
			{
				for (int b = 0; b < 3; b++)
				{
					int xn = x + a - 1;
					int yn = y + b - 1;

					magX += sourceImage.GetPixelRed(xn, yn) * kernelX[a][b];
					magY += sourceImage.GetPixelRed(xn, yn) * kernelY[a][b];
				}
			}

			if (magX < 0) { magX = 0; }
			else if (magX > 255) { magX = 255; }
			if (magY < 0) { magY = 0; }
			else if (magY > 255) { magY = 255; }

			//Combine the masks 
			double mag = sqrt(magX * magX + magY * magY);

			if (mag < 0) { mag = 0; }
			else if (mag > 255) { mag = 255; }

			int mg = (int)mag;
			destinationImage.SetPixel(x, y, mg << redPixelShift | mg << greenPixelShift | mg << bluePixelShift);
		}
	}
}
예제 #7
0
void GLWidget3D::generatePredictedData() {
	QString resultDir = "C:\\Anaconda\\caffe\\data\\pmtree2d\\pmtree2d_predicted\\";
	if (QDir(resultDir).exists()) {
		QDir(resultDir).removeRecursively();
	}
	QDir().mkpath(resultDir);

	QFile file("predicted_results.txt");
	if (file.open(QIODevice::ReadOnly)) {
		QTextStream in(&file);
		int n = 0;
		while (!in.atEnd()) {
			QStringList data = in.readLine().split(",");
			
			std::vector<std::vector<float> > params;
			for (int i = 0; i * 63 < data.size(); ++i) {
				std::vector<float> ps;
				for (int k = 0; k < 63; ++k) {
					ps.push_back(data[i * 63 + k].toFloat());
				}
				params.push_back(ps);
			}

			tree.recover(params);
			
			// 木を生成
			renderManager.removeObjects();
			tree.generateGeometry(&renderManager, false);

			// 画像を生成
			render();

			QImage img = grabFrameBuffer();
			cv::Mat sourceImage(img.height(), img.width(), CV_8UC4, img.bits(), img.bytesPerLine());
			cv::Mat grayImage;
			cv::cvtColor(sourceImage, grayImage, CV_RGB2GRAY);

			// 画像を縮小
			cv::resize(grayImage, grayImage, cv::Size(512, 512));
			cv::threshold(grayImage, grayImage, 200, 255, CV_THRESH_BINARY);
			cv::resize(grayImage, grayImage, cv::Size(256, 256));
			cv::threshold(grayImage, grayImage, 200, 255, CV_THRESH_BINARY);
			cv::resize(grayImage, grayImage, cv::Size(128, 128));
			cv::threshold(grayImage, grayImage, 200, 255, CV_THRESH_BINARY);

			// write the iamge to file
			QString filename = resultDir + QString("image_%1.png").arg(n, 6, 10, QChar('0'));

			cv::imwrite(filename.toUtf8().constData(), grayImage);

			n++;
		}
	}

}
예제 #8
0
void TerrainPageSurfaceLayer::fillImage(const TerrainPageGeometry& geometry, Image& image, unsigned int channel) const
{
	SegmentVector validSegments = geometry.getValidSegments();
	for (SegmentVector::const_iterator I = validSegments.begin(); I != validSegments.end(); ++I) {
		if (mShader.checkIntersect(*I->segment)) {
			Mercator::Surface* surface = getSurfaceForSegment(I->segment);
			if (surface && surface->isValid()) {
				WFImage sourceImage(new Image::ImageBuffer(65, 1, surface->getData()));
				//We need to adjust the position of the x index by one because there's a one pixel offset when converting between the Mercator Segments and the Ogre page.
				image.blit(sourceImage, channel, ((int)I->index.x() * 64) + 1, ((mTerrainPageSurface.getNumberOfSegmentsPerAxis() - (int)I->index.y() - 1) * 64));
			}
		}
	}
}
예제 #9
0
GraphicsContext* FilterEffectRenderer::inputContext()
{
    return sourceImage() ? sourceImage()->context() : 0;
}
예제 #10
0
void ImageBufferData::putData(Uint8ClampedArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize& size, bool accelerateRendering, bool unmultiplied, float resolutionScale)
{
    ASSERT(sourceRect.width() > 0);
    ASSERT(sourceRect.height() > 0);
    
    int originx = sourceRect.x();
    int destx = (destPoint.x() + sourceRect.x()) * resolutionScale;
    ASSERT(destx >= 0);
    ASSERT(destx < size.width());
    ASSERT(originx >= 0);
    ASSERT(originx <= sourceRect.maxX());
    
    int endx = (destPoint.x() + sourceRect.maxX()) * resolutionScale;
    ASSERT(endx <= size.width());
    
    int width = sourceRect.width();
    int destw = endx - destx;

    int originy = sourceRect.y();
    int desty = (destPoint.y() + sourceRect.y()) * resolutionScale;
    ASSERT(desty >= 0);
    ASSERT(desty < size.height());
    ASSERT(originy >= 0);
    ASSERT(originy <= sourceRect.maxY());
    
    int endy = (destPoint.y() + sourceRect.maxY()) * resolutionScale;
    ASSERT(endy <= size.height());

    int height = sourceRect.height();
    int desth = endy - desty;
    
    if (width <= 0 || height <= 0)
        return;
    
    unsigned srcBytesPerRow = 4 * sourceSize.width();
    unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4;
    unsigned destBytesPerRow;
    unsigned char* destRows;
    
    if (!accelerateRendering) {
        destBytesPerRow = 4 * size.width();
        destRows = reinterpret_cast<unsigned char*>(m_data) + desty * destBytesPerRow + destx * 4;
        
#if USE(ACCELERATE)
        if (haveVImageRoundingErrorFix() && unmultiplied) {
            vImage_Buffer src;
            src.height = height;
            src.width = width;
            src.rowBytes = srcBytesPerRow;
            src.data = srcRows;
            
            vImage_Buffer dst;
            dst.height = desth;
            dst.width = destw;
            dst.rowBytes = destBytesPerRow;
            dst.data = destRows;

            if (resolutionScale != 1) {
                vImage_AffineTransform scaleTransform = { resolutionScale, 0, 0, resolutionScale, 0, 0 }; // FIXME: Add subpixel translation.
                Pixel_8888 backgroundColor;
                vImageAffineWarp_ARGB8888(&src, &dst, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend);
                // The premultiplying will be done in-place.
                src = dst;
            }

            vImagePremultiplyData_RGBA8888(&src, &dst, kvImageNoFlags);
            return;
        }
#endif
        if (resolutionScale != 1) {
            RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
            RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get()));
            RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
            CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy);
            CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation.
            if (!unmultiplied)
                return;

            srcRows = destRows;
            srcBytesPerRow = destBytesPerRow;
            width = destw;
            height = desth;
        }

        for (int y = 0; y < height; ++y) {
            for (int x = 0; x < width; x++) {
                int basex = x * 4;
                unsigned char alpha = srcRows[basex + 3];
                if (unmultiplied && alpha != 255) {
                    destRows[basex] = (srcRows[basex] * alpha + 254) / 255;
                    destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255;
                    destRows[basex + 2] = (srcRows[basex + 2] * alpha + 254) / 255;
                    destRows[basex + 3] = alpha;
                } else
                    reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0];
            }
            destRows += destBytesPerRow;
            srcRows += srcBytesPerRow;
        }
    } else {
#if USE(IOSURFACE_CANVAS_BACKING_STORE)
        IOSurfaceRef surface = m_surface.get();
        IOSurfaceLock(surface, 0, 0);
        destBytesPerRow = IOSurfaceGetBytesPerRow(surface);
        destRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + desty * destBytesPerRow + destx * 4;

#if USE(ACCELERATE)
        vImage_Buffer src;
        src.height = height;
        src.width = width;
        src.rowBytes = srcBytesPerRow;
        src.data = srcRows;

        vImage_Buffer dest;
        dest.height = desth;
        dest.width = destw;
        dest.rowBytes = destBytesPerRow;
        dest.data = destRows;

        if (resolutionScale != 1) {
            vImage_AffineTransform scaleTransform = { resolutionScale, 0, 0, resolutionScale, 0, 0 }; // FIXME: Add subpixel translation.
            Pixel_8888 backgroundColor;
            vImageAffineWarp_ARGB8888(&src, &dest, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend);
            // The unpremultiplying and channel-swapping will be done in-place.
            if (unmultiplied) {
                srcRows = destRows;
                width = destw;
                height = desth;
                srcBytesPerRow = destBytesPerRow;
            } else
                src = dest;
        }

        if (unmultiplied) {
            ScanlineData scanlineData;
            scanlineData.scanlineWidth = width;
            scanlineData.srcData = srcRows;
            scanlineData.srcRowBytes = srcBytesPerRow;
            scanlineData.destData = destRows;
            scanlineData.destRowBytes = destBytesPerRow;

            dispatch_apply_f(height, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, premultitplyScanline);
        } else {
            // Swap pixel channels from RGBA to BGRA.
            const uint8_t map[4] = { 2, 1, 0, 3 };
            vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags);
        }
#else
        if (resolutionScale != 1) {
            RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
            RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get()));
            RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
            CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy);
            CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation.

            srcRows = destRows;
            srcBytesPerRow = destBytesPerRow;
            width = destw;
            height = desth;
        }

        for (int y = 0; y < height; ++y) {
            for (int x = 0; x < width; x++) {
                int basex = x * 4;
                unsigned char b = srcRows[basex];
                unsigned char alpha = srcRows[basex + 3];
                if (unmultiplied && alpha != 255) {
                    destRows[basex] = (srcRows[basex + 2] * alpha + 254) / 255;
                    destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255;
                    destRows[basex + 2] = (b * alpha + 254) / 255;
                    destRows[basex + 3] = alpha;
                } else {
                    destRows[basex] = srcRows[basex + 2];
                    destRows[basex + 1] = srcRows[basex + 1];
                    destRows[basex + 2] = b;
                    destRows[basex + 3] = alpha;
                }
            }
            destRows += destBytesPerRow;
            srcRows += srcBytesPerRow;
        }
#endif // USE(ACCELERATE)

        IOSurfaceUnlock(surface, 0, 0);
#else
        ASSERT_NOT_REACHED();
#endif // USE(IOSURFACE_CANVAS_BACKING_STORE)
    }
}
예제 #11
0
PassRefPtr<Uint8ClampedArray> ImageBufferData::getData(const IntRect& rect, const IntSize& size, bool accelerateRendering, bool unmultiplied, float resolutionScale) const
{
    float area = 4.0f * rect.width() * rect.height();
    if (area > static_cast<float>(std::numeric_limits<int>::max()))
        return 0;

    RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4);
    unsigned char* data = result->data();
    
    int endx = ceilf(rect.maxX() * resolutionScale);
    int endy = ceilf(rect.maxY() * resolutionScale);
    if (rect.x() < 0 || rect.y() < 0 || endx > size.width() || endy > size.height())
        result->zeroFill();
    
    int originx = rect.x();
    int destx = 0;
    int destw = rect.width();
    if (originx < 0) {
        destw += originx;
        destx = -originx;
        originx = 0;
    }
    destw = min<int>(destw, ceilf(size.width() / resolutionScale) - originx);
    originx *= resolutionScale;
    if (endx > size.width())
        endx = size.width();
    int width = endx - originx;
    
    int originy = rect.y();
    int desty = 0;
    int desth = rect.height();
    if (originy < 0) {
        desth += originy;
        desty = -originy;
        originy = 0;
    }
    desth = min<int>(desth, ceilf(size.height() / resolutionScale) - originy);
    originy *= resolutionScale;
    if (endy > size.height())
        endy = size.height();
    int height = endy - originy;
    
    if (width <= 0 || height <= 0)
        return result.release();
    
    unsigned destBytesPerRow = 4 * rect.width();
    unsigned char* destRows = data + desty * destBytesPerRow + destx * 4;
    
    unsigned srcBytesPerRow;
    unsigned char* srcRows;
    
    if (!accelerateRendering) {
        srcBytesPerRow = 4 * size.width();
        srcRows = reinterpret_cast<unsigned char*>(m_data) + originy * srcBytesPerRow + originx * 4;
        
#if USE(ACCELERATE)
        if (unmultiplied && haveVImageRoundingErrorFix()) {
            vImage_Buffer src;
            src.height = height;
            src.width = width;
            src.rowBytes = srcBytesPerRow;
            src.data = srcRows;
            
            vImage_Buffer dst;
            dst.height = desth;
            dst.width = destw;
            dst.rowBytes = destBytesPerRow;
            dst.data = destRows;

            if (resolutionScale != 1) {
                vImage_AffineTransform scaleTransform = { 1 / resolutionScale, 0, 0, 1 / resolutionScale, 0, 0 }; // FIXME: Add subpixel translation.
                Pixel_8888 backgroundColor;
                vImageAffineWarp_ARGB8888(&src, &dst, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend);
                // The unpremultiplying will be done in-place.
                src = dst;
            }

            vImageUnpremultiplyData_RGBA8888(&src, &dst, kvImageNoFlags);
            return result.release();
        }
#endif
        if (resolutionScale != 1) {
            RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
            RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get()));
            RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
            CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy);
            CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation.
            if (!unmultiplied)
                return result.release();

            srcRows = destRows;
            srcBytesPerRow = destBytesPerRow;
            width = destw;
            height = desth;
        }
        if (unmultiplied) {
            for (int y = 0; y < height; ++y) {
                for (int x = 0; x < width; x++) {
                    int basex = x * 4;
                    unsigned char alpha = srcRows[basex + 3];
                    if (alpha) {
                        destRows[basex] = (srcRows[basex] * 255) / alpha;
                        destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha;
                        destRows[basex + 2] = (srcRows[basex + 2] * 255) / alpha;
                        destRows[basex + 3] = alpha;
                    } else
                        reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0];
                }
                srcRows += srcBytesPerRow;
                destRows += destBytesPerRow;
            }
        } else {
            for (int y = 0; y < height; ++y) {
                for (int x = 0; x < width * 4; x += 4)
                    reinterpret_cast<uint32_t*>(destRows + x)[0] = reinterpret_cast<uint32_t*>(srcRows + x)[0];
                srcRows += srcBytesPerRow;
                destRows += destBytesPerRow;
            }
        }
    } else {
#if USE(IOSURFACE_CANVAS_BACKING_STORE)
        IOSurfaceRef surface = m_surface.get();
        IOSurfaceLock(surface, kIOSurfaceLockReadOnly, 0);
        srcBytesPerRow = IOSurfaceGetBytesPerRow(surface);
        srcRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + originy * srcBytesPerRow + originx * 4;

#if USE(ACCELERATE)
        vImage_Buffer src;
        src.height = height;
        src.width = width;
        src.rowBytes = srcBytesPerRow;
        src.data = srcRows;

        vImage_Buffer dest;
        dest.height = desth;
        dest.width = destw;
        dest.rowBytes = destBytesPerRow;
        dest.data = destRows;

        if (resolutionScale != 1) {
            vImage_AffineTransform scaleTransform = { 1 / resolutionScale, 0, 0, 1 / resolutionScale, 0, 0 }; // FIXME: Add subpixel translation.
            Pixel_8888 backgroundColor;
            vImageAffineWarp_ARGB8888(&src, &dest, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend);
            // The unpremultiplying and channel-swapping will be done in-place.
            if (unmultiplied) {
                srcRows = destRows;
                width = destw;
                height = desth;
                srcBytesPerRow = destBytesPerRow;
            } else
                src = dest;
        }

        if (unmultiplied) {
            ScanlineData scanlineData;
            scanlineData.scanlineWidth = width;
            scanlineData.srcData = srcRows;
            scanlineData.srcRowBytes = srcBytesPerRow;
            scanlineData.destData = destRows;
            scanlineData.destRowBytes = destBytesPerRow;

            dispatch_apply_f(height, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, unpremultitplyScanline);
        } else {
            // Swap pixel channels from BGRA to RGBA.
            const uint8_t map[4] = { 2, 1, 0, 3 };
            vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags);
        }
#else
        if (resolutionScale != 1) {
            RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
            RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get()));
            RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast));
            CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy);
            CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation.

            srcRows = destRows;
            srcBytesPerRow = destBytesPerRow;
            width = destw;
            height = desth;
        }

        if (unmultiplied) {
            for (int y = 0; y < height; ++y) {
                for (int x = 0; x < width; x++) {
                    int basex = x * 4;
                    unsigned char b = srcRows[basex];
                    unsigned char alpha = srcRows[basex + 3];
                    if (alpha) {
                        destRows[basex] = (srcRows[basex + 2] * 255) / alpha;
                        destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha;
                        destRows[basex + 2] = (b * 255) / alpha;
                        destRows[basex + 3] = alpha;
                    } else {
                        destRows[basex] = srcRows[basex + 2];
                        destRows[basex + 1] = srcRows[basex + 1];
                        destRows[basex + 2] = b;
                        destRows[basex + 3] = srcRows[basex + 3];
                    }
                }
                srcRows += srcBytesPerRow;
                destRows += destBytesPerRow;
            }
        } else {
            for (int y = 0; y < height; ++y) {
                for (int x = 0; x < width; x++) {
                    int basex = x * 4;
                    unsigned char b = srcRows[basex];
                    destRows[basex] = srcRows[basex + 2];
                    destRows[basex + 1] = srcRows[basex + 1];
                    destRows[basex + 2] = b;
                    destRows[basex + 3] = srcRows[basex + 3];
                }
                srcRows += srcBytesPerRow;
                destRows += destBytesPerRow;
            }
        }
#endif // USE(ACCELERATE)
        IOSurfaceUnlock(surface, kIOSurfaceLockReadOnly, 0);
#else
        ASSERT_NOT_REACHED();
#endif // USE(IOSURFACE_CANVAS_BACKING_STORE)
    }
    
    return result.release();
}