DColor ImageIface::colorInfoFromOriginal(const QPoint& point) const { if (!original() || original()->isNull()) { kWarning() << "No image data available!"; return DColor(); } if (point.x() > originalSize().width() || point.y() > originalSize().height()) { kWarning() << "Coordinate out of range!"; return DColor(); } return original()->getPixelColor(point.x(), point.y()); }
size_t PrecompressorBlock:: writeBlockHeader(OutStream* out, MetaData metadata) const { size_t bytes = 0; size_t integersToPack[2]; size_t elems; if(metadata == PRECOMP_ORIGINAL_SIZE) { integersToPack[0] = originalSize(); integersToPack[1] = slices(); elems = 2; } else if(metadata == PRECOMP_COMPRESSED_SIZE) { integersToPack[0] = size(); elems = 1; } for(size_t j = 0; j < elems; ++j) { int bytesNeeded; uint64 packedInteger = utils::packInteger(integersToPack[j], &bytesNeeded); for(int i = 0; i < bytesNeeded; ++i) { out->writeByte(packedInteger & 0xff); packedInteger >>= 8; } bytes += bytesNeeded; } bytes += m_grammar.writeGrammar(out); return bytes; }
void Image::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio) { #if PLATFORM(IOS) intrinsicRatio = originalSize(); #else intrinsicRatio = size(); #endif intrinsicWidth = Length(intrinsicRatio.width(), Fixed); intrinsicHeight = Length(intrinsicRatio.height(), Fixed); }
void patternWindow::constructActions() { backHistoryAction_ = new QAction(QIcon(":leftArrow.png"), tr("Undo"), this); backHistoryAction_->setShortcut(QKeySequence("Ctrl+z")); backHistoryAction_->setEnabled(false); connect(backHistoryAction_, SIGNAL(triggered()), this, SLOT(backHistoryActionSlot())); forwardHistoryAction_ = new QAction(QIcon(":rightArrow.png"), tr("Redo"), this); forwardHistoryAction_->setShortcut(QKeySequence("Ctrl+y")); forwardHistoryAction_->setEnabled(false); connect(forwardHistoryAction_, SIGNAL(triggered()), this, SLOT(forwardHistoryActionSlot())); switchAction_ = new QAction(QIcon(":switchImages.png"), tr("Switch between pattern and square images"), this); connect(switchAction_, SIGNAL(triggered()), this, SLOT(switchActionSlot())); gridAction_ = new QAction(QIcon(":grid.png"), tr("Turn grid on/off"), this); gridAction_->setCheckable(true); gridAction_->setChecked(true); imageLabel_->setGridOn(true); connect(gridAction_, SIGNAL(triggered(bool )), this, SLOT(processGridChange(bool ))); deleteImageAction_ = new QAction(tr("Delete image"), this); connect(deleteImageAction_, SIGNAL(triggered()), this, SLOT(processDelete())); gridColorAction_ = new QAction(tr("Change grid color"), this); connect(gridColorAction_, SIGNAL(triggered()), this, SLOT(processGridColorChange())); connect(originalSizeAction(), SIGNAL(triggered()), this, SLOT(originalSize())); setPdfViewerAction_ = new QAction(tr("Set pdf viewer"), this); connect(setPdfViewerAction_, SIGNAL(triggered()), this, SLOT(updatePdfViewerOptions())); }
bool PGFLoader::load(const QString& filePath, DImgLoaderObserver* const observer) { m_observer = observer; readMetadata(filePath, DImg::PGF); FILE* file = fopen(QFile::encodeName(filePath).constData(), "rb"); if (!file) { qCWarning(DIGIKAM_DIMG_LOG_PGF) << "Error: Could not open source file."; loadingFailed(); return false; } unsigned char header[3]; if (fread(&header, 3, 1, file) != 1) { fclose(file); loadingFailed(); return false; } unsigned char pgfID[3] = { 0x50, 0x47, 0x46 }; if (memcmp(&header[0], &pgfID, 3) != 0) { // not a PGF file fclose(file); loadingFailed(); return false; } fclose(file); // ------------------------------------------------------------------- // Initialize PGF API. #ifdef WIN32 #ifdef UNICODE HANDLE fd = CreateFile((LPCWSTR)(QFile::encodeName(filePath).constData()), GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); #else HANDLE fd = CreateFile(QFile::encodeName(filePath).constData(), GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); #endif if (fd == INVALID_HANDLE_VALUE) { loadingFailed(); return false; } #else int fd = open(QFile::encodeName(filePath).constData(), O_RDONLY); if (fd == -1) { loadingFailed(); return false; } #endif CPGFFileStream stream(fd); CPGFImage pgf; int colorModel = DImg::COLORMODELUNKNOWN; try { // open pgf image pgf.Open(&stream); switch (pgf.Mode()) { case ImageModeRGBColor: case ImageModeRGB48: m_hasAlpha = false; colorModel = DImg::RGB; break; case ImageModeRGBA: m_hasAlpha = true; colorModel = DImg::RGB; break; default: qCWarning(DIGIKAM_DIMG_LOG_PGF) << "Cannot load PGF image: color mode not supported (" << pgf.Mode() << ")"; loadingFailed(); return false; break; } switch (pgf.Channels()) { case 3: case 4: break; default: qCWarning(DIGIKAM_DIMG_LOG_PGF) << "Cannot load PGF image: color channels number not supported (" << pgf.Channels() << ")"; loadingFailed(); return false; break; } int bitDepth = pgf.BPP(); switch (bitDepth) { case 24: // RGB 8 bits. case 32: // RGBA 8 bits. m_sixteenBit = false; break; case 48: // RGB 16 bits. case 64: // RGBA 16 bits. m_sixteenBit = true; break; default: qCWarning(DIGIKAM_DIMG_LOG_PGF) << "Cannot load PGF image: color bits depth not supported (" << bitDepth << ")"; loadingFailed(); return false; break; } if(DIGIKAM_DIMG_LOG_PGF().isDebugEnabled()) { const PGFHeader* header = pgf.GetHeader(); qCDebug(DIGIKAM_DIMG_LOG_PGF) << "PGF width = " << header->width; qCDebug(DIGIKAM_DIMG_LOG_PGF) << "PGF height = " << header->height; qCDebug(DIGIKAM_DIMG_LOG_PGF) << "PGF bbp = " << header->bpp; qCDebug(DIGIKAM_DIMG_LOG_PGF) << "PGF channels = " << header->channels; qCDebug(DIGIKAM_DIMG_LOG_PGF) << "PGF quality = " << header->quality; qCDebug(DIGIKAM_DIMG_LOG_PGF) << "PGF mode = " << header->mode; qCDebug(DIGIKAM_DIMG_LOG_PGF) << "Has Alpha = " << m_hasAlpha; qCDebug(DIGIKAM_DIMG_LOG_PGF) << "Is 16 bits = " << m_sixteenBit; } // NOTE: see bug #273765 : Loading PGF thumbs with OpenMP support through a separated thread do not work properlly with libppgf 6.11.24 pgf.ConfigureDecoder(false); int width = pgf.Width(); int height = pgf.Height(); uchar* data = 0; QSize originalSize(width, height); if (m_loadFlags & LoadImageData) { // ------------------------------------------------------------------- // Find out if we do the fast-track loading with reduced size. PGF specific. int level = 0; QVariant attribute = imageGetAttribute(QLatin1String("scaledLoadingSize")); if (attribute.isValid() && pgf.Levels() > 0) { int scaledLoadingSize = attribute.toInt(); int i, w, h; for (i = pgf.Levels() - 1 ; i >= 0 ; --i) { w = pgf.Width(i); h = pgf.Height(i); if (qMin(w, h) >= scaledLoadingSize) { break; } } if (i >= 0) { width = w; height = h; level = i; qCDebug(DIGIKAM_DIMG_LOG_PGF) << "Loading PGF scaled version at level " << i << " (" << w << " x " << h << ") for size " << scaledLoadingSize; } } if (m_sixteenBit) { data = new_failureTolerant(width, height, 8); // 16 bits/color/pixel } else { data = new_failureTolerant(width, height, 4); // 8 bits/color/pixel } // Fill all with 255 including alpha channel. memset(data, 0xFF, width * height * (m_sixteenBit ? 8 : 4)); pgf.Read(level, CallbackForLibPGF, this); pgf.GetBitmap(m_sixteenBit ? width * 8 : width * 4, (UINT8*)data, m_sixteenBit ? 64 : 32, NULL, CallbackForLibPGF, this); if (observer) { observer->progressInfo(m_image, 1.0); } } // ------------------------------------------------------------------- // Get ICC color profile. if (m_loadFlags & LoadICCData) { // TODO: Implement proper storage in PGF for color profiles checkExifWorkingColorSpace(); } imageWidth() = width; imageHeight() = height; imageData() = data; imageSetAttribute(QLatin1String("format"), QLatin1String("PGF")); imageSetAttribute(QLatin1String("originalColorModel"), colorModel); imageSetAttribute(QLatin1String("originalBitDepth"), bitDepth); imageSetAttribute(QLatin1String("originalSize"), originalSize); #ifdef WIN32 CloseHandle(fd); #else close(fd); #endif return true; } catch (IOException& e) { int err = e.error; if (err >= AppError) { err -= AppError; } qCWarning(DIGIKAM_DIMG_LOG_PGF) << "Error: Opening and reading PGF image failed (" << err << ")!"; #ifdef WIN32 CloseHandle(fd); #else close(fd); #endif loadingFailed(); return false; } catch (std::bad_alloc& e) { qCWarning(DIGIKAM_DIMG_LOG_PGF) << "Failed to allocate memory for loading" << filePath << e.what(); #ifdef WIN32 CloseHandle(fd); #else close(fd); #endif loadingFailed(); return false; } return true; }
/// 画像ファイルから読みこみ HRslt Texture::setUp(const _TCHAR *fname) { if(!fname) return E_INVALIDARG; HRslt hr; D3DXIMAGE_INFO info; hr = ::D3DXGetImageInfoFromFile(fname, &info); if(hr) { if(info.MipLevels == 1) { hr = setUp(NORMAL, info.Width, info.Height, info.Format, 1); if(hr) { dx::IDirect3DSurfacePtr surf; ptr_->GetSurfaceLevel(0, &surf); if(no_scaling_) { RECT rect = {0, 0, info.Width, info.Height}; hr = ::D3DXLoadSurfaceFromFile(surf, 0, &rect, fname, 0, D3DX_FILTER_NONE, 0, 0); } else { hr = ::D3DXLoadSurfaceFromFile(surf, 0, 0, fname, 0, (size() != originalSize() ? D3DX_DEFAULT : D3DX_FILTER_NONE), 0, 0); } } if(!hr) { ptr_ = 0; PRNN(_T("D3DXCreateTextureFromFileを使用します")); no_scaling_ = false; hr = ::D3DXCreateTextureFromFile(device().impl(), fname, &ptr_); int retry_count = 0; while(hr == E_OUTOFMEMORY && ++retry_count < 100) { // …めんどいんで100回試行することにする… ::Sleep(1); hr = ::D3DXCreateTextureFromFile(device().impl(), fname, &ptr_); } } } else { no_scaling_ = false; hr = ::D3DXCreateTextureFromFile(device().impl(), fname, &ptr_); int retry_count = 0; while(hr == E_OUTOFMEMORY && ++retry_count < 100) { // …めんどいんで100回試行することにする… ::Sleep(1); hr = ::D3DXCreateTextureFromFile(device().impl(), fname, &ptr_); } } } else { PRNN(_T("Win32リソース検索 ") << TURI(fname).basename()); hr = ::D3DXGetImageInfoFromResource(NULL, TURI(fname).basename().c_str(), &info); if(!hr) return hr; if(info.MipLevels == 1) { hr = setUp(NORMAL, info.Width, info.Height, info.Format, 1); if(hr) { dx::IDirect3DSurfacePtr surf; ptr_->GetSurfaceLevel(0, &surf); if(no_scaling_) { RECT rect = {0, 0, info.Width, info.Height}; hr = ::D3DXLoadSurfaceFromResource(surf, 0, &rect, NULL, TURI(fname).basename().c_str(), 0, D3DX_FILTER_NONE, 0, 0); } else { hr = ::D3DXLoadSurfaceFromResource(surf, 0, 0, NULL, TURI(fname).basename().c_str(), 0, (size() != originalSize() ? D3DX_DEFAULT : D3DX_FILTER_NONE), 0, 0); } } if(!hr) { ptr_ = 0; PRNN(_T("D3DXCreateTextureFromResourceを使用します")); no_scaling_ = false; hr = ::D3DXCreateTextureFromResource(device().impl(), NULL, TURI(fname).basename().c_str(), &ptr_); int retry_count = 0; while(hr == E_OUTOFMEMORY && ++retry_count < 100) { // …めんどいんで100回試行することにする… ::Sleep(1); hr = ::D3DXCreateTextureFromResource(device().impl(), NULL, TURI(fname).basename().c_str(), &ptr_); } } } else { no_scaling_ = false; hr = ::D3DXCreateTextureFromResource(device().impl(), NULL, TURI(fname).basename().c_str(), &ptr_); int retry_count = 0; while(hr == E_OUTOFMEMORY && ++retry_count < 100) { // …めんどいんで100回試行することにする… ::Sleep(1); hr = ::D3DXCreateTextureFromResource(device().impl(), NULL, TURI(fname).basename().c_str(), &ptr_); } } } if(!hr) GCTP_ERRORINFO(hr<<" / fname:"<<fname); if(ptr_) { D3DSURFACE_DESC desc; hr = ptr_->GetLevelDesc(0, &desc); if(!hr) PRNN(hr); type_ = NORMAL; org_width_ = info.Width; org_height_ = info.Height; org_format_ = (int)info.Format; org_miplevel_ = info.MipLevels; //PRNN("Texture "<<fname<<" "<<info<<" Desc {"<<desc.Width<<","<<desc.Height<<","<<desc.Format<<"}"); } else type_ = NONE; return hr; }
/// メモリから読みこみ HRslt Texture::setUp(const void *memory, size_t size) { if(!memory || size <= 0) return E_INVALIDARG; HRslt hr; D3DXIMAGE_INFO info; hr = ::D3DXGetImageInfoFromFileInMemory(memory, (UINT)size, &info); if(hr) { if(info.MipLevels == 1) { hr = setUp(NORMAL, info.Width, info.Height, info.Format, 1); if(hr) { dx::IDirect3DSurfacePtr surf; ptr_->GetSurfaceLevel(0, &surf); if(no_scaling_) { RECT rect = {0, 0, info.Width, info.Height}; hr = ::D3DXLoadSurfaceFromFileInMemory(surf, 0, &rect, memory, (UINT)size, 0, D3DX_FILTER_NONE, 0, 0); } else { hr = ::D3DXLoadSurfaceFromFileInMemory(surf, 0, 0, memory, (UINT)size, 0, (this->size() != originalSize() ? D3DX_DEFAULT : D3DX_FILTER_NONE), 0, 0); } } if(!hr) { ptr_ = 0; PRNN(_T("D3DXCreateTextureFromInMemoryを使用します")); no_scaling_ = false; hr = ::D3DXCreateTextureFromFileInMemory(device().impl(), memory, (UINT)size, &ptr_); } } else { no_scaling_ = false; hr = ::D3DXCreateTextureFromFileInMemory(device().impl(), memory, (UINT)size, &ptr_); } } if(!hr) GCTP_ERRORINFO(hr<<" / memory"); if(ptr_) { D3DSURFACE_DESC desc; hr = ptr_->GetLevelDesc(0, &desc); if(!hr) PRNN(hr); type_ = NORMAL; org_width_ = info.Width; org_height_ = info.Height; org_format_ = (int)info.Format; org_miplevel_ = info.MipLevels; //PRNN("Texture memory "<<info<<" Desc {"<<desc.Width<<","<<desc.Height<<","<<desc.Format<<"}"); } else type_ = NONE; return hr; }
void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode) { if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, destRect, solidColor(), op); return; } ASSERT(!isBitmapImage() || notSolidColor()); #if PLATFORM(IOS) FloatSize intrinsicTileSize = originalSize(); #else FloatSize intrinsicTileSize = size(); #endif if (hasRelativeWidth()) intrinsicTileSize.setWidth(scaledTileSize.width()); if (hasRelativeHeight()) intrinsicTileSize.setHeight(scaledTileSize.height()); FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(), scaledTileSize.height() / intrinsicTileSize.height()); FloatRect oneTileRect; FloatSize actualTileSize(scaledTileSize.width() + spacing.width(), scaledTileSize.height() + spacing.height()); oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), actualTileSize.width()) - actualTileSize.width(), actualTileSize.width())); oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), actualTileSize.height()) - actualTileSize.height(), actualTileSize.height())); oneTileRect.setSize(scaledTileSize); // Check and see if a single draw of the image can cover the entire area we are supposed to tile. if (oneTileRect.contains(destRect) && !ctxt.drawLuminanceMask()) { FloatRect visibleSrcRect; visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width()); visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height()); visibleSrcRect.setWidth(destRect.width() / scale.width()); visibleSrcRect.setHeight(destRect.height() / scale.height()); draw(ctxt, destRect, visibleSrcRect, op, blendMode, ImageOrientationDescription()); return; } #if PLATFORM(IOS) // When using accelerated drawing on iOS, it's faster to stretch an image than to tile it. if (ctxt.isAcceleratedContext()) { if (size().width() == 1 && intersection(oneTileRect, destRect).height() == destRect.height()) { FloatRect visibleSrcRect; visibleSrcRect.setX(0); visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height()); visibleSrcRect.setWidth(1); visibleSrcRect.setHeight(destRect.height() / scale.height()); draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, ImageOrientationDescription()); return; } if (size().height() == 1 && intersection(oneTileRect, destRect).width() == destRect.width()) { FloatRect visibleSrcRect; visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width()); visibleSrcRect.setY(0); visibleSrcRect.setWidth(destRect.width() / scale.width()); visibleSrcRect.setHeight(1); draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, ImageOrientationDescription()); return; } } #endif // Patterned images and gradients can use lots of memory for caching when the // tile size is large (<rdar://problem/4691859>, <rdar://problem/6239505>). // Memory consumption depends on the transformed tile size which can get // larger than the original tile if user zooms in enough. #if PLATFORM(IOS) const float maxPatternTilePixels = 512 * 512; #else const float maxPatternTilePixels = 2048 * 2048; #endif FloatRect transformedTileSize = ctxt.getCTM().mapRect(FloatRect(FloatPoint(), scaledTileSize)); float transformedTileSizePixels = transformedTileSize.width() * transformedTileSize.height(); FloatRect currentTileRect = oneTileRect; if (transformedTileSizePixels > maxPatternTilePixels) { GraphicsContextStateSaver stateSaver(ctxt); ctxt.clip(destRect); currentTileRect.shiftYEdgeTo(destRect.y()); float toY = currentTileRect.y(); while (toY < destRect.maxY()) { currentTileRect.shiftXEdgeTo(destRect.x()); float toX = currentTileRect.x(); while (toX < destRect.maxX()) { FloatRect toRect(toX, toY, currentTileRect.width(), currentTileRect.height()); FloatRect fromRect(toFloatPoint(currentTileRect.location() - oneTileRect.location()), currentTileRect.size()); fromRect.scale(1 / scale.width(), 1 / scale.height()); draw(ctxt, toRect, fromRect, op, BlendModeNormal, ImageOrientationDescription()); toX += currentTileRect.width(); currentTileRect.shiftXEdgeTo(oneTileRect.x()); } toY += currentTileRect.height(); currentTileRect.shiftYEdgeTo(oneTileRect.y()); } return; } AffineTransform patternTransform = AffineTransform().scaleNonUniform(scale.width(), scale.height()); FloatRect tileRect(FloatPoint(), intrinsicTileSize); drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), spacing, op, destRect, blendMode); #if PLATFORM(IOS) startAnimation(DoNotCatchUp); #else startAnimation(); #endif }