1# Copyright 2018-2019 The glTF-Blender-IO authors.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import bpy
16import os
17import tempfile
18from os.path import dirname, join, isfile, basename, normpath
19import urllib.parse
20import re
21
22from ...io.imp.gltf2_io_binary import BinaryData
23
24
25# Note that Image is not a glTF2.0 object
26class BlenderImage():
27    """Manage Image."""
28    def __new__(cls, *args, **kwargs):
29        raise RuntimeError("%s should not be instantiated" % cls)
30
31    @staticmethod
32    def create(gltf, img_idx):
33        """Image creation."""
34        img = gltf.data.images[img_idx]
35        img_name = img.name
36
37        if img.blender_image_name is not None:
38            # Image is already used somewhere
39            return
40
41        tmp_dir = None
42        try:
43            if img.uri is not None and not img.uri.startswith('data:'):
44                # Image stored in a file
45                img_from_file = True
46                path = join(dirname(gltf.filename), _uri_to_path(img.uri))
47                img_name = img_name or basename(path)
48                if not isfile(path):
49                    gltf.log.error("Missing file (index " + str(img_idx) + "): " + img.uri)
50                    return
51            else:
52                # Image stored as data => create a tempfile, pack, and delete file
53                img_from_file = False
54                img_data = BinaryData.get_image_data(gltf, img_idx)
55                if img_data is None:
56                    return
57                img_name = img_name or 'Image_%d' % img_idx
58                tmp_dir = tempfile.TemporaryDirectory(prefix='gltfimg-')
59                filename = _filenamify(img_name) or 'Image_%d' % img_idx
60                filename += _img_extension(img)
61                path = join(tmp_dir.name, filename)
62                with open(path, 'wb') as f:
63                    f.write(img_data)
64
65            num_images = len(bpy.data.images)
66            blender_image = bpy.data.images.load(os.path.abspath(path), check_existing=img_from_file)
67            if len(bpy.data.images) != num_images:  # If created a new image
68                blender_image.name = img_name
69                if gltf.import_settings['import_pack_images'] or not img_from_file:
70                    blender_image.pack()
71
72            img.blender_image_name = blender_image.name
73
74        finally:
75            if tmp_dir is not None:
76                tmp_dir.cleanup()
77
78def _uri_to_path(uri):
79    uri = urllib.parse.unquote(uri)
80    return normpath(uri)
81
82def _img_extension(img):
83    if img.mime_type == 'image/png':
84        return '.png'
85    if img.mime_type == 'image/jpeg':
86        return '.jpg'
87    return ''
88
89def _filenamify(s):
90    s = s.strip().replace(' ', '_')
91    return re.sub(r'(?u)[^-\w.]', '', s)
92