Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ImageObject renders scaled when its image input dpi metadata is not 72 #508

Open
typoman opened this issue Feb 4, 2023 · 1 comment
Open

Comments

@typoman
Copy link
Contributor

typoman commented Feb 4, 2023

I found out that if I load an image using the ImageObject it renders small and blurred when the image metadata dpi is 300. If I change the dpi of the image to 72 outside drawbot (without changing the number of pixels) drawbot renders it as the actual image. I found a solution by loading the image using TIFFRepresentation instead of the current method in the _makeBitmapImageRep function. This method always keeps the right size regardless of the input image dpi metadata. This code sample only overrides the function _makeBitmapImageRep to show the difference. I'm not sure what would be the other effects of this change:

import AppKit
from drawBot.misc import DrawBotError, optimizePath
import Quartz
import os
from drawBot import *
from drawBot.context.tools.imageObject import ImageObject

def _makeBitmapImageRep(nsImage=None, pdfPage=None, imageResolution=72.0, antiAliasing=False, colorSpaceName=AppKit.NSCalibratedRGBColorSpace):
    """Construct a bitmap image representation at a given resolution."""
    if nsImage is None and pdfPage is None:
        raise DrawBotError("At least a image or a pdf page must be provided to create a bitmap representaion.")

    if pdfPage is not None:
        mediaBox = pdfPage.boundsForBox_(Quartz.kPDFDisplayBoxMediaBox)
        width, height = mediaBox.size
    elif nsImage is not None:
        width, height = nsImage.size()
    rep = AppKit.NSBitmapImageRep.imageRepWithData_(nsImage.TIFFRepresentation())
    return rep

def _open(self, path):
    """
    Open an image with a given `path`.
    """
    if isinstance(path, AppKit.NSImage):
        im = path
    elif isinstance(path, str):
        path = optimizePath(path)
        if path.startswith("http"):
            url = AppKit.NSURL.URLWithString_(path)
        else:
            if not os.path.exists(path):
                raise DrawBotError("Image path '%s' does not exists." % path)
            url = AppKit.NSURL.fileURLWithPath_(path)
        im = AppKit.NSImage.alloc().initByReferencingURL_(url)
    else:
        raise DrawBotError("Cannot read image path '%s'." % path)
    rep = _makeBitmapImageRep(im)
    ciImage = AppKit.CIImage.alloc().initWithBitmapImageRep_(rep)
    self._merge(ciImage, doCrop=True)

# remove the following line to see the default behavior
ImageObject.open = _open
imagePath = "sampleImage-300dpi.jpg"
i = ImageObject()
i.open(imagePath)
w, h = imageSize(i)
size(w, h)
@typemytype
Copy link
Owner

it used to be the TIFFRrepesentation but that changed here: 137a75e

with the commit message:

  • all image rep must be build with _makeBitmapImageRep
    when the imageObject reads a path, when the imageObjects applies a
    filter

Its not perfect now, I guess the image resolution needs to be checked on open and used while drawing into the imageObject.

Optionally the imageObject could have an imageResolution argument during init when there is no path/image given: ImageObject(imageResolution=144).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants