79QImageIOPlugin::Capabilities
QIIOFHelpers::systemCapabilities(
const QString &uti)
81 QImageIOPlugin::Capabilities res;
84 QCFType<CFArrayRef> cfSourceTypes = CGImageSourceCopyTypeIdentifiers();
85 CFIndex len = CFArrayGetCount(cfSourceTypes);
86 if (CFArrayContainsValue(cfSourceTypes, CFRangeMake(0, len), cfUti))
87 res |= QImageIOPlugin::CanRead;
89 QCFType<CFArrayRef> cfDestTypes = CGImageDestinationCopyTypeIdentifiers();
90 len = CFArrayGetCount(cfDestTypes);
91 if (CFArrayContainsValue(cfDestTypes, CFRangeMake(0, len), cfUti))
92 res |= QImageIOPlugin::CanWrite;
118 if (!q_ptr || !q_ptr->device())
121 if (QBuffer *b = qobject_cast<QBuffer *>(q_ptr->device())) {
123 const void *rawData = b->data().constData() + b->pos();
124 cgDataProvider = CGDataProviderCreateWithData(
nullptr, rawData, size_t(b->data().size() - b->pos()),
nullptr);
126 static const CGDataProviderSequentialCallbacks cgCallbacks = {
130 cgDataProvider = CGDataProviderCreateSequential(q_ptr->device(), &cgCallbacks);
133 cgImageSource = CGImageSourceCreateWithDataProvider(cgDataProvider,
nullptr);
136 auto primaryIndex = CGImageSourceGetPrimaryImageIndex(cgImageSource);
137 cfImageDict = CGImageSourceCopyPropertiesAtIndex(cgImageSource, primaryIndex,
nullptr);
140 qCInfo(lcImageIO) <<
"Initialized source" << cgImageSource
141 <<
"with" << CGImageSourceGetCount(cgImageSource) <<
"images"
142 <<
"and primary index" << CGImageSourceGetPrimaryImageIndex(cgImageSource);
144 return (cgImageSource);
152 auto primaryIndex = CGImageSourceGetPrimaryImageIndex(cgImageSource);
153 QCFType<CGImageRef> cgImage = CGImageSourceCreateImageAtIndex(cgImageSource, primaryIndex,
nullptr);
155 qCInfo(lcImageIO) <<
"Read image at index" << primaryIndex
156 <<
"with properties" << cfImageDict <<
"and got" << cgImage;
161 *out = qt_mac_toQImage(cgImage);
166 if (getIntProperty(kCGImagePropertyDPIWidth, &dpi))
167 out->setDotsPerMeterX(qRound(dpi / 0.0254f));
168 if (getIntProperty(kCGImagePropertyDPIHeight, &dpi))
169 out->setDotsPerMeterY(qRound(dpi / 0.0254f));
193 switch (exifOrientation) {
195 return QImageIOHandler::TransformationNone;
197 return QImageIOHandler::TransformationMirror;
199 return QImageIOHandler::TransformationRotate180;
201 return QImageIOHandler::TransformationFlip;
203 return QImageIOHandler::TransformationFlipAndRotate90;
205 return QImageIOHandler::TransformationRotate90;
207 return QImageIOHandler::TransformationMirrorAndRotate90;
209 return QImageIOHandler::TransformationRotate270;
211 return QImageIOHandler::TransformationNone;
214static int qt2Exif(QImageIOHandler::Transformations transformation)
216 switch (transformation) {
217 case QImageIOHandler::TransformationNone:
219 case QImageIOHandler::TransformationMirror:
221 case QImageIOHandler::TransformationRotate180:
223 case QImageIOHandler::TransformationFlip:
225 case QImageIOHandler::TransformationFlipAndRotate90:
227 case QImageIOHandler::TransformationRotate90:
229 case QImageIOHandler::TransformationMirrorAndRotate90:
231 case QImageIOHandler::TransformationRotate270:
234 qWarning(
"Invalid Qt image transformation");
244 case QImageIOHandler::Size: {
246 if (getIntProperty(kCGImagePropertyPixelWidth, &sz.rwidth())
247 && getIntProperty(kCGImagePropertyPixelHeight, &sz.rheight())) {
252 case QImageIOHandler::ImageTransformation: {
254 if (getIntProperty(kCGImagePropertyOrientation, &orient))
255 return int(exif2Qt(orient));
274 static const CGDataConsumerCallbacks cgCallbacks = { &cbPutBytes,
nullptr };
276 if (!q_ptr || !q_ptr->device() || in.isNull())
279 QCFType<CGImageRef> cgImage = qt_mac_toCGImage(in);
280 QCFType<CGDataConsumerRef> cgDataConsumer = CGDataConsumerCreate(q_ptr->device(), &cgCallbacks);
281 QCFType<CFStringRef> cfUti = uti.toCFString();
282 QCFType<CGImageDestinationRef> cgImageDest = CGImageDestinationCreateWithDataConsumer(cgDataConsumer, cfUti, 1,
nullptr);
283 if (!cgImageDest || !cgImage)
286 QCFType<CFNumberRef> cfQuality =
nullptr;
287 QCFType<CFNumberRef> cfOrientation =
nullptr;
288 const void *dictKeys[2];
289 const void *dictVals[2];
292 if (q_ptr->supportsOption(QImageIOHandler::Quality)) {
294 int writeQuality = writeOptions.value(QImageIOHandler::Quality).toInt(&ok);
296 float quality = (ok && writeQuality >= 0 ? (qMin(writeQuality, 100)) : 75) / 100.0f;
297 cfQuality = CFNumberCreate(
nullptr, kCFNumberFloatType, &quality);
298 dictKeys[dictSize] =
static_cast<
const void *>(kCGImageDestinationLossyCompressionQuality);
299 dictVals[dictSize] =
static_cast<
const void *>(cfQuality);
302 if (q_ptr->supportsOption(QImageIOHandler::ImageTransformation)) {
303 int orient = qt2Exif(
static_cast<QImageIOHandler::Transformation>(writeOptions.value(QImageIOHandler::ImageTransformation).toInt()));
304 cfOrientation = CFNumberCreate(
nullptr, kCFNumberIntType, &orient);
305 dictKeys[dictSize] =
static_cast<
const void *>(kCGImagePropertyOrientation);
306 dictVals[dictSize] =
static_cast<
const void *>(cfOrientation);
310 QCFType<CFDictionaryRef> cfProps =
nullptr;
312 cfProps = CFDictionaryCreate(
nullptr, dictKeys, dictVals, dictSize,
313 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
315 qCInfo(lcImageIO) <<
"Writing" << cgImage <<
"\nwith properties" << cfProps;
317 CGImageDestinationAddImage(cgImageDest, cgImage, cfProps);
318 return CGImageDestinationFinalize(cgImageDest);