From 1327646900994c033155100adf7bbaad7654ff50 Mon Sep 17 00:00:00 2001 From: Artemy Gordon Date: Thu, 26 Jan 2023 18:01:09 +0000 Subject: Add handling matte entry in cairo backend --- poppler/CairoOutputDev.cc | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc index 946cb1a4..2c0e0672 100644 --- a/poppler/CairoOutputDev.cc +++ b/poppler/CairoOutputDev.cc @@ -2763,12 +2763,35 @@ cleanup: delete imgStr; } +static inline void getMatteColorRgb(GfxImageColorMap *colorMap, const GfxColor *matteColorIn, GfxRGB *matteColorRgb) +{ + colorMap->getColorSpace()->getRGB(matteColorIn, matteColorRgb); + matteColorRgb->r = colToByte(matteColorRgb->r); + matteColorRgb->g = colToByte(matteColorRgb->g); + matteColorRgb->b = colToByte(matteColorRgb->b); +} + +static inline void applyMask(unsigned int *imagePointer, int length, GfxRGB matteColor, unsigned char *alphaPointer) +{ + unsigned char *p, r, g, b; + int i; + + for (i = 0, p = (unsigned char *)imagePointer; i < length; i++, p += 4, alphaPointer++) { + if (*alphaPointer) { + b = std::clamp(matteColor.b + (int)(p[0] - matteColor.b) * 255 / *alphaPointer, 0, 255); + g = std::clamp(matteColor.g + (int)(p[1] - matteColor.g) * 255 / *alphaPointer, 0, 255); + r = std::clamp(matteColor.r + (int)(p[2] - matteColor.r) * 255 / *alphaPointer, 0, 255); + imagePointer[i] = (r << 16) | (g << 8) | (b << 0); + } + } +} + // XXX: is this affect by AIS(alpha is shape)? void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, bool interpolate, Stream *maskStr, int maskWidth, int maskHeight, GfxImageColorMap *maskColorMap, bool maskInterpolate) { ImageStream *maskImgStr, *imgStr; - ptrdiff_t row_stride; + ptrdiff_t row_stride, mask_row_stride; unsigned char *maskBuffer, *buffer; unsigned char *maskDest; unsigned int *dest; @@ -2779,6 +2802,12 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s int y; cairo_filter_t filter; cairo_filter_t maskFilter; + GfxRGB matteColorRgb; + + const GfxColor *matteColor = maskColorMap->getMatteColor(); + if (matteColor != nullptr) { + getMatteColorRgb(colorMap, matteColor, &matteColorRgb); + } maskImgStr = new ImageStream(maskStr, maskWidth, maskColorMap->getNumPixelComps(), maskColorMap->getBits()); maskImgStr->reset(); @@ -2791,9 +2820,9 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s } maskBuffer = cairo_image_surface_get_data(maskImage); - row_stride = cairo_image_surface_get_stride(maskImage); + mask_row_stride = cairo_image_surface_get_stride(maskImage); for (y = 0; y < maskHeight; y++) { - maskDest = (unsigned char *)(maskBuffer + y * row_stride); + maskDest = (unsigned char *)(maskBuffer + y * mask_row_stride); pix = maskImgStr->getLine(); if (likely(pix != nullptr)) { maskColorMap->getGrayLine(pix, maskDest, maskWidth); @@ -2835,14 +2864,22 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s for (y = 0; y < height; y++) { dest = reinterpret_cast(buffer + y * row_stride); pix = imgStr->getLine(); - colorMap->getRGBLine(pix, dest, width); + if (likely(pix != nullptr)) { + colorMap->getRGBLine(pix, dest, width); + if (matteColor != nullptr) { + maskDest = (unsigned char *)(maskBuffer + y * mask_row_stride); + applyMask(dest, width, matteColorRgb, maskDest); + } + } } filter = getFilterForSurface(image, interpolate); cairo_surface_mark_dirty(image); - setMimeData(state, str, ref, colorMap, image, height); + if (matteColor == nullptr) { + setMimeData(state, str, ref, colorMap, image, height); + } pattern = cairo_pattern_create_for_surface(image); cairo_surface_destroy(image); -- cgit v1.2.3