mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2026-06-22 06:29:10 -04:00
Add support for CD-I IFF images
This commit is contained in:
@@ -262,14 +262,21 @@ static void addMetadata(QImage &img, const IFOR_Chunk *form)
|
||||
|
||||
// if no explicit resolution was found, apply the aspect ratio to the default one
|
||||
if (!resChanged) {
|
||||
auto headers = IFFChunk::searchT<BMHDChunk>(form);
|
||||
if (!headers.isEmpty()) {
|
||||
auto xr = headers.first()->xAspectRatio();
|
||||
auto yr = headers.first()->yAspectRatio();
|
||||
if (xr > 0 && yr > 0 && xr > yr) {
|
||||
img.setDotsPerMeterX(img.dotsPerMeterX() * yr / xr);
|
||||
} else if (xr > 0 && yr > 0 && xr < yr) {
|
||||
img.setDotsPerMeterY(img.dotsPerMeterY() * xr / yr);
|
||||
if (form->formType() == IMAG_FORM_TYPE) {
|
||||
auto params = IFFChunk::searchT<IPARChunk>(form);
|
||||
if (!params.isEmpty()) {
|
||||
img.setDotsPerMeterY(img.dotsPerMeterY() * params.first()->aspectRatio());
|
||||
}
|
||||
} else {
|
||||
auto headers = IFFChunk::searchT<BMHDChunk>(form);
|
||||
if (!headers.isEmpty()) {
|
||||
auto xr = headers.first()->xAspectRatio();
|
||||
auto yr = headers.first()->yAspectRatio();
|
||||
if (xr > 0 && yr > 0 && xr > yr) {
|
||||
img.setDotsPerMeterX(img.dotsPerMeterX() * yr / xr);
|
||||
} else if (xr > 0 && yr > 0 && xr < yr) {
|
||||
img.setDotsPerMeterY(img.dotsPerMeterY() * xr / yr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -475,6 +482,67 @@ bool IFFHandler::readMayaImage(QImage *image)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IFFHandler::readCDIImage(QImage *image)
|
||||
{
|
||||
auto forms = d->searchForms<FORMChunk>();
|
||||
if (forms.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
auto cin = qBound(0, currentImageNumber(), int(forms.size() - 1));
|
||||
auto &&form = forms.at(cin);
|
||||
|
||||
// show the first one (I don't have a sample with many images)
|
||||
auto headers = IFFChunk::searchT<IHDRChunk>(form);
|
||||
if (headers.isEmpty()) {
|
||||
qCWarning(LOG_IFFPLUGIN) << "IFFHandler::readCDIImage(): no supported image found";
|
||||
return false;
|
||||
}
|
||||
|
||||
// create the image
|
||||
auto &&header = headers.first();
|
||||
auto img = imageAlloc(header->size(), form->format());
|
||||
if (img.isNull()) {
|
||||
qCWarning(LOG_IFFPLUGIN) << "IFFHandler::readCDIImage(): error while allocating the image";
|
||||
return false;
|
||||
}
|
||||
|
||||
// set the palette
|
||||
if (img.format() == QImage::Format_Indexed8) {
|
||||
auto pltes = IFFChunk::searchT<PLTEChunk>(form);
|
||||
if (!pltes.isEmpty()) {
|
||||
img.setColorTable(pltes.first()->palette());
|
||||
}
|
||||
}
|
||||
|
||||
// decoding the image
|
||||
auto bodies = IFFChunk::searchT<IDATChunk>(form);
|
||||
if (bodies.isEmpty()) {
|
||||
img.fill(0);
|
||||
} else {
|
||||
auto &&body = bodies.first();
|
||||
if (!body->resetStrideRead(device())) {
|
||||
qCWarning(LOG_IFFPLUGIN) << "IFFHandler::readCDIImage(): error while reading image data";
|
||||
return false;
|
||||
}
|
||||
auto pars = IFFChunk::searchT<IPARChunk>(form);
|
||||
for (auto y = 0, h = img.height(); y < h; ++y) {
|
||||
auto line = reinterpret_cast<char*>(img.scanLine(y));
|
||||
auto ba = body->strideRead(device(), y, header, pars.isEmpty() ? nullptr : pars.first());
|
||||
if (ba.isEmpty()) {
|
||||
qCWarning(LOG_IFFPLUGIN) << "IFFHandler::readCDIImage(): error while reading image scanline";
|
||||
return false;
|
||||
}
|
||||
memcpy(line, ba.constData(), std::min(img.bytesPerLine(), ba.size()));
|
||||
}
|
||||
}
|
||||
|
||||
// set metadata (including image resolution)
|
||||
addMetadata(img, form);
|
||||
|
||||
*image = img;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IFFHandler::read(QImage *image)
|
||||
{
|
||||
if (!d->readStructure(device())) {
|
||||
@@ -490,6 +558,10 @@ bool IFFHandler::read(QImage *image)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (readCDIImage(image)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
qCWarning(LOG_IFFPLUGIN) << "IFFHandler::read(): no supported image found";
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user