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

Modify Wand builder and replace Imagemagick and Pillow with it #274

Merged
merged 25 commits into from
Nov 18, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9a87fb5
modify image__wand builder so that it is like common thumbnail genera…
a523 Oct 19, 2021
2c8c8e6
enable wand builder and disable others
a523 Oct 19, 2021
24463a1
reintroduce white background for file with transparency
a523 Oct 22, 2021
1af97cc
test case for transparent img
a523 Oct 22, 2021
7572911
deprecate Pillow and ImageMagick (command line) builder
a523 Oct 22, 2021
6dbd8d3
support progressive JPEG
a523 Oct 22, 2021
15aeab2
rename
a523 Oct 22, 2021
4720aa4
add doc about how to enable eps format support
a523 Oct 30, 2021
8c08a72
refactor wand build
a523 Oct 31, 2021
bfeb419
format
a523 Oct 31, 2021
a4ccee1
update supported mimetypes
a523 Oct 31, 2021
3aa7c7a
fix supported mimetype table and weight
inkhey Nov 3, 2021
4e4ba63
Merge branch 'develop' of github.com:algoo/preview-generator into wand
inkhey Nov 3, 2021
2a73bd8
reintroduce raw/xcf support
inkhey Nov 3, 2021
5409818
add test for raw file without extension
inkhey Nov 3, 2021
6198027
support file that without extension
a523 Nov 13, 2021
946e66c
fix: merge layers
a523 Nov 13, 2021
e6091f0
make sure transparency turns white
a523 Nov 15, 2021
32ec567
fix test case of heic
a523 Nov 15, 2021
33126d5
misc: add concourse ci
inkhey Nov 15, 2021
445bf66
fix(backend): enforce office mimetype and add better exception
inkhey Nov 16, 2021
40a1450
v0.26
inkhey Nov 16, 2021
a6b1139
fix readme
inkhey Nov 16, 2021
33962c6
fix: Repair loading builders without pytest and make code more explic…
inkhey Nov 16, 2021
edcf565
Merge remote-tracking branch 'algoo/develop' into wand
a523 Nov 18, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions preview_generator/preview/builder/cad__vtk.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from preview_generator.exception import BuilderDependencyNotFound
from preview_generator.exception import UnsupportedMimeType
from preview_generator.extension import mimetypes_storage
from preview_generator.preview.builder.image__pillow import ImagePreviewBuilderPillow # nopep8
from preview_generator.preview.builder.image__wand import ImagePreviewBuilderWand # nopep8
from preview_generator.preview.generic_preview import PreviewBuilder
from preview_generator.utils import ImgDims
from preview_generator.utils import MimetypeMapping
Expand Down Expand Up @@ -188,7 +188,7 @@ def build_jpeg_preview(
writer.SetInputConnection(windowto_image_filter.GetOutputPort())
writer.Write()

return ImagePreviewBuilderPillow().build_jpeg_preview(
return ImagePreviewBuilderWand().build_jpeg_preview(
tmp_png.name, preview_name, cache_path, page_id, extension, size, mimetype
)

Expand Down
4 changes: 2 additions & 2 deletions preview_generator/preview/builder/document__drawio.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from preview_generator.exception import BuilderDependencyNotFound
from preview_generator.exception import IntermediateFileBuildingFailed
from preview_generator.preview.builder.image__pillow import ImagePreviewBuilderPillow
from preview_generator.preview.builder.image__wand import ImagePreviewBuilderWand
from preview_generator.preview.generic_preview import PreviewBuilder
from preview_generator.utils import ImgDims
from preview_generator.utils import MimetypeMapping
Expand Down Expand Up @@ -87,7 +87,7 @@ def build_jpeg_preview(
"failed with status {}".format(build_jpg_result_code)
)

ImagePreviewBuilderPillow().build_jpeg_preview(
ImagePreviewBuilderWand().build_jpeg_preview(
tmp_jpg.name, preview_name, cache_path, page_id, extension, size, mimetype
)

Expand Down
4 changes: 2 additions & 2 deletions preview_generator/preview/builder/document__sketch.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import typing
import zipfile

from preview_generator.preview.builder.image__pillow import ImagePreviewBuilderPillow # nopep8
from preview_generator.preview.builder.image__wand import ImagePreviewBuilderWand # nopep8
from preview_generator.preview.generic_preview import PreviewBuilder
from preview_generator.utils import ImgDims
from preview_generator.utils import MimetypeMapping
Expand Down Expand Up @@ -46,7 +46,7 @@ def build_jpeg_preview(
zip.extract("previews/preview.png", tmp_dir)
zip.close()

ImagePreviewBuilderPillow().build_jpeg_preview(
ImagePreviewBuilderWand().build_jpeg_preview(
tmp_dir + "/previews/preview.png",
preview_name,
cache_path,
Expand Down
4 changes: 2 additions & 2 deletions preview_generator/preview/builder/image__cairosvg.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

# HACK - G.M - 2020-12-26 - Hack to allow loading modules without cairosvg installed
from preview_generator.exception import BuilderDependencyNotFound
from preview_generator.preview.builder.image__pillow import ImagePreviewBuilderPillow # nopep8
from preview_generator.preview.builder.image__wand import ImagePreviewBuilderWand # nopep8
from preview_generator.preview.generic_preview import ImagePreviewBuilder
from preview_generator.utils import ImgDims

Expand Down Expand Up @@ -55,7 +55,7 @@ def build_jpeg_preview(
) as tmp_png:
cairosvg.svg2png(url=file_path, write_to=tmp_png.name, dpi=96)

return ImagePreviewBuilderPillow().build_jpeg_preview(
return ImagePreviewBuilderWand().build_jpeg_preview(
tmp_png.name, preview_name, cache_path, page_id, extension, size, mimetype
)

Expand Down
2 changes: 1 addition & 1 deletion preview_generator/preview/builder/image__imconvert.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class ImagePreviewBuilderIMConvert(ImagePreviewBuilder):
MimetypeMapping("image/heic", ".heif"),
]

weight = 30
weight = 0
inkhey marked this conversation as resolved.
Show resolved Hide resolved

@classmethod
def get_label(cls) -> str:
Expand Down
4 changes: 2 additions & 2 deletions preview_generator/preview/builder/image__inkscape.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from preview_generator.exception import BuilderDependencyNotFound
from preview_generator.exception import IntermediateFileBuildingFailed
from preview_generator.preview.builder.image__pillow import ImagePreviewBuilderPillow # nopep8
from preview_generator.preview.builder.image__wand import ImagePreviewBuilderWand # nopep8
from preview_generator.preview.generic_preview import ImagePreviewBuilder
from preview_generator.utils import ImgDims
from preview_generator.utils import executable_is_available
Expand Down Expand Up @@ -68,6 +68,6 @@ def build_jpeg_preview(
"failed with status {}".format(build_png_result_code)
)

return ImagePreviewBuilderPillow().build_jpeg_preview(
return ImagePreviewBuilderWand().build_jpeg_preview(
tmp_png.name, preview_name, cache_path, page_id, extension, size, mimetype
)
75 changes: 20 additions & 55 deletions preview_generator/preview/builder/image__wand.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
# -*- coding: utf-8 -*-

from io import BytesIO
import os
import typing

from wand.image import Color
from wand.image import Image as WImage
import wand.version

from preview_generator.preview.builder.image__imconvert import ImagePreviewBuilderIMConvert
from preview_generator.preview.generic_preview import ImagePreviewBuilder
from preview_generator.utils import ImgDims
from preview_generator.utils import compute_resize_dims
from preview_generator.utils import imagemagick_supported_mimes


class ImagePreviewBuilderWand(ImagePreviewBuilder):
"""
WARNING : This builder is deprecated, prefer ImagePreviewBuilderIMConvert instead which
support the same list of format.
"""

weight = 10
weight = 40
MIMETYPES = [] # type: typing.List[str]

@classmethod
Expand Down Expand Up @@ -48,15 +40,7 @@ def get_supported_mimetypes(cls) -> typing.List[str]:
ImagePreviewBuilderWand.MIMETYPES = cls.__load_mimetypes()
mimetypes = ImagePreviewBuilderWand.MIMETYPES

# INFO - G.M - 2021-04-30
# Disable support for postscript,xcf and raw image format in wand, to ensure
# proper builder is used (either imagemagick convert or pillow)

invalid_mimetypes = ["application/postscript", "application/x-xcf", "image/x-xcf"]
for (
mimetype_mapping
) in ImagePreviewBuilderIMConvert().SUPPORTED_RAW_CAMERA_MIMETYPE_MAPPING:
invalid_mimetypes.append(mimetype_mapping.mimetype)

for invalid_mimetype in invalid_mimetypes:
try:
Expand All @@ -77,41 +61,22 @@ def build_jpeg_preview(
) -> None:
if not size:
size = self.default_size
with open(file_path, "rb") as img:
result = self.image_to_jpeg_wand(img, ImgDims(width=size.width, height=size.height))

with open(
"{path}{extension}".format(path=cache_path + preview_name, extension=extension),
"wb",
) as jpeg:
buffer = result.read(1024)
while buffer:
jpeg.write(buffer)
buffer = result.read(1024)

def image_to_jpeg_wand(
self, jpeg: typing.Union[str, typing.IO[bytes]], preview_dims: ImgDims
) -> BytesIO:
"""
for jpeg, gif and bmp
:param jpeg:
:param size:
:return:
"""
self.logger.info("Converting image to jpeg using wand")

with WImage(file=jpeg, background=Color("white")) as image:

preview_dims = ImgDims(width=preview_dims.width, height=preview_dims.height)

resize_dim = compute_resize_dims(
dims_in=ImgDims(width=image.size[0], height=image.size[1]), dims_out=preview_dims
preview_name = preview_name + extension
dest_path = os.path.join(cache_path, preview_name)
with WImage(filename=file_path) as img:
# https://legacy.imagemagick.org/Usage/thumbnails/
img.auto_orient()
img.merge_layers("merge")
img.strip()
img.sample()
if img.width < size.width and img.height < size.height:
flag = "<"
else:
flag = ">"
resize_arg = "{width}x{height}{flag}".format(
width=size.width,
height=size.height,
flag=flag
)
image.resize(resize_dim.width, resize_dim.height)
# INFO - jumenzel - 2019-03-12 - remove metadata, color-profiles from this image.
image.strip()
content_as_bytes = image.make_blob("jpeg")
output = BytesIO()
output.write(content_as_bytes)
output.seek(0, 0)
return output
img.transform(resize=resize_arg)
img.save(filename=dest_path)
4 changes: 0 additions & 4 deletions preview_generator/preview/builder_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,6 @@ def load_builders(self, force: bool = False) -> None:
if is_abstract(cls):
# INFO - G.M - 2021-06-22 - Skip abstract classes from loaded builders
pass
elif cls.__name__ == "ImagePreviewBuilderWand":
self.logger.info(
"ImagePreviewBuilderWand builder is deprecated and is not registered by default. Consider using ImagePreviewBuilderIMConvert instead"
)
else:
self.register_builder(cls, overwrite=False)

Expand Down
34 changes: 34 additions & 0 deletions tests/builders/test_image_wand_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import os
import pytest
from PIL import Image
from preview_generator.preview.builder.image__wand import ImagePreviewBuilderWand
from preview_generator.utils import ImgDims

CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
CACHE_DIR = "/tmp/preview-generator-tests/cache"


def test_build_jpeg_preview() -> None:
wand_builder = ImagePreviewBuilderWand()
test_orient_path = os.path.join(CURRENT_DIR, "the_img.png")
extension = ".jpg"
preview_name = "preview_the_img"
width = 512
height = 256
size = ImgDims(width=width, height=height)
wand_builder.build_jpeg_preview(
file_path=test_orient_path,
preview_name=preview_name,
cache_path=CACHE_DIR,
page_id=-1,
size=size,
extension=extension
)
preview_name = preview_name + extension
dest_path = os.path.join(CACHE_DIR, preview_name)
print(dest_path)
assert os.path.exists(dest_path)
assert os.path.getsize(dest_path) > 0
with Image.open(dest_path) as jpg:
assert jpg.height == height
assert jpg.width in range(288, 290)
Binary file added tests/builders/the_img.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.