bool PSDImageData::read(QIODevice *io, KisPaintDeviceSP dev ) { psdread(io, &m_compression); quint64 start = io->pos(); m_channelSize = m_header->channelDepth/8; m_channelDataLength = m_header->height * m_header->width * m_channelSize; switch (m_compression) { case 0: // Uncompressed for (int channel = 0; channel < m_header->nChannels; channel++) { m_channelOffsets << 0; ChannelInfo channelInfo; channelInfo.channelId = channel; channelInfo.compressionType = Compression::Uncompressed; channelInfo.channelDataStart = start; channelInfo.channelDataLength = m_header->width * m_header->height * m_channelSize; start += channelInfo.channelDataLength; m_channelInfoRecords.append(channelInfo); } switch (m_header->colormode) { case Bitmap: break; case Grayscale: readGrayscale(io,dev); break; case Indexed: break; case RGB: readRGB(io, dev); break; case CMYK: readCMYK(io, dev); break; case MultiChannel: break; case DuoTone: break; case Lab: readLAB(io, dev); break; case UNKNOWN: break; default: break; } break; case 1: // RLE { quint32 rlelength = 0; // The start of the actual channel data is _after_ the RLE rowlengths block if (m_header->version == 1) { start += m_header->nChannels * m_header->height * 2; } else if (m_header->version == 2) { start += m_header->nChannels * m_header->height * 4; } for (int channel = 0; channel < m_header->nChannels; channel++) { m_channelOffsets << 0; quint32 sumrlelength = 0; ChannelInfo channelInfo; channelInfo.channelId = channel; channelInfo.channelDataStart = start; channelInfo.compressionType = Compression::RLE; for (quint32 row = 0; row < m_header->height; row++ ) { if (m_header->version == 1) { psdread(io,(quint16*)&rlelength); } else if (m_header->version == 2) { psdread(io,&rlelength); } channelInfo.rleRowLengths.append(rlelength); sumrlelength += rlelength; } channelInfo.channelDataLength = sumrlelength; start += channelInfo.channelDataLength; m_channelInfoRecords.append(channelInfo); } switch (m_header->colormode) { case Bitmap: break; case Grayscale: readGrayscale(io,dev); break; case Indexed: break; case RGB: readRGB(io, dev); break; case CMYK: readCMYK(io, dev); break; case MultiChannel: break; case DuoTone: break; case Lab: readLAB(io, dev); break; case UNKNOWN: break; default: break; } break; } case 2: // ZIP without prediction switch (m_header->colormode) { case Bitmap: break; case Grayscale: break; case Indexed: break; case RGB: break; case CMYK: break; case MultiChannel: break; case DuoTone: break; case Lab: break; case UNKNOWN: break; default: break; } break; case 3: // ZIP with prediction switch (m_header->colormode) { case Bitmap: break; case Grayscale: break; case Indexed: break; case RGB: break; case CMYK: break; case MultiChannel: break; case DuoTone: break; case Lab: break; case UNKNOWN: break; default: break; } break; default: break; } return true; }
bool ScImgDataLoader_GMagick::loadPicture(const QString& fn, int /*page*/, int res, bool thumbnail) { if (!QFile::exists(fn)) return false; bool valid = m_imageInfoRecord.isRequest; QMap<int, ImageLoadRequest> req = m_imageInfoRecord.RequestProps; initialize(); m_imageInfoRecord.RequestProps = req; m_imageInfoRecord.isRequest = valid; m_imageInfoRecord.type = ImageTypeOther; m_imageInfoRecord.exifDataValid = false; m_imageInfoRecord.layerInfo.clear(); m_imageInfoRecord.PDSpathData.clear(); initGraphicsMagick(); ExceptionInfo exception; GetExceptionInfo(&exception); ImageInfo *image_info = CloneImageInfo(0); strcpy(image_info->filename, fn.toUtf8().data()); image_info->units = PixelsPerInchResolution; Image *image = ReadImage(image_info, &exception); if (exception.severity != UndefinedException) CatchException(&exception); if (!image) { qCritical() << "Failed to read image" << fn; return false; } int width = image->columns; int height = image->rows; double xres = image->x_resolution; double yres = image->y_resolution; if (thumbnail) image = FlattenImages(image, &exception); else { struct PSDLayer layer; layerCount = 0; Image *flatten_image = CloneImage(image, 0, 0, true, &exception); Image *next; if ((flatten_image != (Image *) NULL) && (image->next != (Image *) NULL)) { bool visible = true; double opacity = 1.0; QString compositeOp = blendModeToString(flatten_image->compose); QString layerName = QString("layer%1").arg(layerCount+1); if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerCount))) opacity = m_imageInfoRecord.RequestProps[layerCount].opacity / 255.0; if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerCount))) visible = m_imageInfoRecord.RequestProps[layerCount].visible; if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerCount))) compositeOp = m_imageInfoRecord.RequestProps[layerCount].blend; layer.layerName = layerName; layer.channelType.clear(); layer.channelLen.clear(); layer.opacity = qRound(opacity * 255); layer.blend = compositeOp; layer.maskYpos = 0; layer.maskXpos = 0; layer.maskHeight = 0; layer.maskWidth = 0; layer.flags = visible ? 0 : 2; QImage imt; if (image->colorspace == CMYKColorspace) { RawImage r2_image; readCMYK(flatten_image, &r2_image, width, height); imt = r2_image.convertToQImage(true); } else { m_useRawImage = false; imt = QImage(width, height, QImage::Format_ARGB32); readRGB(flatten_image, &imt, width, height); } double sx = imt.width() / 40.0; double sy = imt.height() / 40.0; layer.thumb = sy < sx ? imt.scaled(qRound(imt.width() / sx), qRound(imt.height() / sx), Qt::IgnoreAspectRatio, Qt::SmoothTransformation) : imt.scaled(qRound(imt.width() / sy), qRound(imt.height() / sy), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); m_imageInfoRecord.layerInfo.append(layer); layerCount++; if (!visible) { (void)CompositeImage(flatten_image, ClearCompositeOp, flatten_image, flatten_image->page.x, flatten_image->page.y); } for (next = image->next; next != (Image*)NULL; next = next->next) { visible = true; opacity = 1.0; compositeOp = blendModeToString(next->compose); layerName = QString("layer%1").arg(layerCount+1); if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerCount))) opacity = m_imageInfoRecord.RequestProps[layerCount].opacity / 255.0; if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerCount))) visible = m_imageInfoRecord.RequestProps[layerCount].visible; if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerCount))) compositeOp = m_imageInfoRecord.RequestProps[layerCount].blend; layer.layerName = layerName; layer.channelType.clear(); layer.channelLen.clear(); layer.opacity = qRound(opacity * 255); layer.blend = compositeOp; layer.maskYpos = 0; layer.maskXpos = 0; layer.maskHeight = 0; layer.maskWidth = 0; layer.flags = visible ? 0 : 2; if (image->colorspace == CMYKColorspace) { RawImage r2_image; readCMYK(next, &r2_image, width, height); imt = r2_image.convertToQImage(true); } else { m_useRawImage = false; imt = QImage(width, height, QImage::Format_ARGB32); readRGB(next, &imt, width, height); } double sx = imt.width() / 40.0; double sy = imt.height() / 40.0; layer.thumb = sy < sx ? imt.scaled(qRound(imt.width() / sx), qRound(imt.height() / sx), Qt::IgnoreAspectRatio, Qt::SmoothTransformation) : imt.scaled(qRound(imt.width() / sy), qRound(imt.height() / sy), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); m_imageInfoRecord.layerInfo.append(layer); layerCount++; if (visible) (void)CompositeImage(flatten_image, (CompositeOperator)blendModeToInt(compositeOp), next, next->page.x, next->page.y); } image = CloneImage(flatten_image, 0, 0, true, &exception); } } if (image->colorspace == CMYKColorspace) { m_useRawImage = true; if (!readCMYK(image, &r_image, width, height)) return false; m_imageInfoRecord.colorspace = ColorSpaceCMYK; m_pixelFormat = (r_image.channels() == 5) ? Format_CMYKA_8 : Format_CMYK_8; } else { m_useRawImage = false; m_image = QImage(width, height, QImage::Format_ARGB32); if (!readRGB(image, &m_image, width, height)) return false; m_imageInfoRecord.colorspace = ColorSpaceRGB; m_pixelFormat = Format_BGRA_8; } m_imageInfoRecord.exifDataValid = false; if (thumbnail) { m_imageInfoRecord.exifDataValid = true; m_imageInfoRecord.exifInfo.thumbnail = m_image; m_imageInfoRecord.exifInfo.height = height; m_imageInfoRecord.exifInfo.width = width; } m_imageInfoRecord.type = ImageTypeOther; m_imageInfoRecord.xres = qMax(72, qRound(xres)); m_imageInfoRecord.yres = qMax(72, qRound(yres)); m_imageInfoRecord.BBoxX = 0; m_imageInfoRecord.BBoxH = m_image.height(); m_imageInfoRecord.valid = true; return true; }