vgalin / html2image

A package acting as a wrapper around the headless mode of existing web browsers to generate images from URLs and from HTML+CSS strings or files.
MIT License
342 stars 43 forks source link

Please add auto compression if a file is too large to convert. Or make larger files be able to convert, please. #73

Closed JackGreenEarth closed 1 year ago

vgalin commented 1 year ago

Hello, could you provide some additional details to this issue? I fail to understand what is the problem you encountered. Could you for example provide some code where html2image cannot handle a "large file"?

JackGreenEarth commented 1 year ago

Imports

from random import randint
from string import Template
from math import ceil, floor
import datetime
from html2image import Html2Image
hti = Html2Image(size=(10000, 10000), output_path='Wallpapers')
import os
import json

Functions

def randomChance(num):
    return 1 == randint(1, num)`

def currentDateTime():
    return datetime.datetime.now().strftime("%I:%M:%S%p%Y-%m-%d")`

def safeRemoveFile(path):
    if os.path.exists(path):
        os.remove(path)`

Data

cell_width = 70
cell_height = 70
cell_spacing = 6
with open('options.json', 'r') as options:
    to_dict = json.load(options)
    width = min(to_dict['width'], 128)
    height = to_dict['height']
    return_as = to_dict['return_as']
    hti.size = ((width * cell_width) + ((width + 1) * cell_spacing), (height * cell_height) + ((height + 1) * cell_spacing))`

chances = [500, 200, 150, 100, 75, 50, 30, 18, 11, 8, 5, 3]
if height > 128 and return_as == 'img':
    # Create matrices
    grids = []
    grid_no = 0
    # Create all first matrices
    for i in range(floor(height / 128)):

        grid = []
        for y in range(128):
            grid.append([])
            for x in range(width):
                cell = '0000'
                for i in range(12):
                    if randomChance(chances[i]):
                        cell = 2 ** (12 - i)

                grid[y].append(cell)
        grids.append(grid)
        grid_no += 1`

    # Last grid
    if not height % 128 == 0:
        grid = []
        for y in range(height % 128):
            grid.append([])
            for x in range(width):
                cell = '0000'
                for i in range(12):
                    if randomChance(chances[i]):
                        cell = 2 ** (12 - i)

                grid[y].append(cell)
        grids.append(grid)
        grid_no += 128 / (height % 128)`

     rand_grid = randint(0, len(grids) - 1)
    grids[rand_grid][randint(0, len(grids[rand_grid]) - 1)][randint(0, width - 1)] = 8192

     print('Created {no} grids'.format(no=grid_no))`

    # Turn all grids into html
    grids_as_html = []
    for grid in grids:
        grid_as_html = '<table>\n'
        for row in grid:
            grid_as_html += '   <tr>\n'
            for cell in row:
                grid_as_html += '       <td class="s' + str(cell) + '">' + str(cell) + '</td>\n'
            grid_as_html += '   </tr>\n'
        grid_as_html += '</table>'

        with open('template.html', 'r') as template:
            src = Template(template.read())
            grid_as_html = src.substitute({'table': grid_as_html})

        grids_as_html.append(grid_as_html)`

     print('Converted all grids into html')`

    # Save file
    foldername = '2048Wallpaper {date} {x}x{y}'.format(date=currentDateTime(), x=width, y=height)
    os.mkdir('Wallpapers/{name}'.format(name=foldername))
    hti.output_path = 'Wallpapers/{name}'.format(name=foldername)

    file_number = 0
    for grid_as_html in grids_as_html:
        hti.size = ((width * cell_width) + ((width + 1) * cell_spacing), (len(grids[file_number]) * cell_height) + ((len(grids[file_number]) + 1) * cell_spacing))
        hti.screenshot(html_str=grid_as_html, save_as='{no}.png'.format(no=str(file_number)))
        file_number += 1`

 else:
    # Create matrix
    grid = []
    for y in range(height):
        grid.append([])
        for x in range(width):
            cell = '0000'
            for i in range(12):
                if randomChance(chances[i]):
                    cell = 2 ** (12 - i)

            grid[y].append(cell)
    grid[randint(0, height - 1)][randint(0, width - 1)] = 8192

    print('Created grid')

    # Convert matrix to html
    grid_as_html = '<table>\n'
    for row in grid:
        grid_as_html += '   <tr>\n'
        for cell in row:
            grid_as_html += '       <td class="s' + str(cell) + '">' + str(cell) + '</td>\n'
        grid_as_html += '   </tr>\n'
    grid_as_html += '</table>'

    with open('template.html', 'r') as template:
        src = Template(template.read())
        grid_as_html = src.substitute({'table': grid_as_html})

    print('Created html')

    # Save file
    def filename(type, include):
        return '{parent}{name}.{type}'.format(parent='Wallpapers/' if include else '', name='2048Wallpaper {date} {x}x{y}-'.format(date=currentDateTime(), x=width, y=height), type=type)

    if return_as == 'html':
        with open(filename('html', True), 'w') as html:
            html.write(grid_as_html)
            print('Saved file as html')
    elif return_as == 'img':
        hti.screenshot(html_str=grid_as_html, save_as=filename('png', False))
        print('Saved file as img')

print('All done. Check Wallpapers folder.')

Not sure if that code is too long, basically, I needed to split up the image into smaller images to prevent getting the error:

[0901/181556.250520:ERROR:angle_platform_impl.cc(43)] Display.cpp:1006 (initialize): ANGLE Display::initialize error 0: Internal Vulkan error (-3): Initialization of an object could not be completed for implementation-specific reasons, in ../../third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp, initialize:1297.
[0901/181556.250673:ERROR:gl_surface_egl.cc(822)] EGL Driver message (Critical) eglInitialize: Internal Vulkan error (-3): Initialization of an object could not be completed for implementation-specific reasons, in ../../third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp, initialize:1297.
[0901/181556.250697:ERROR:gl_surface_egl.cc(1352)] eglInitialize SwANGLE failed with error EGL_NOT_INITIALIZED
[0901/181556.250724:ERROR:gl_ozone_egl.cc(21)] GLSurfaceEGL::InitializeOneOff failed.
[0901/181556.252746:ERROR:viz_main_impl.cc(186)] Exiting GPU process due to errors during initialization
[0901/181556.271142:WARNING:bluez_dbus_manager.cc(247)] Floss manager not present, cannot set Floss enable/disable.
[0901/181556.280683:ERROR:angle_platform_impl.cc(43)] Display.cpp:1006 (initialize): ANGLE Display::initialize error 0: Internal Vulkan error (-3): Initialization of an object could not be completed for implementation-specific reasons, in ../../third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp, initialize:1297.
[0901/181556.280783:ERROR:gl_surface_egl.cc(822)] EGL Driver message (Critical) eglInitialize: Internal Vulkan error (-3): Initialization of an object could not be completed for implementation-specific reasons, in ../../third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp, initialize:1297.
[0901/181556.280812:ERROR:gl_surface_egl.cc(1352)] eglInitialize SwANGLE failed with error EGL_NOT_INITIALIZED
[0901/181556.280840:ERROR:gl_ozone_egl.cc(21)] GLSurfaceEGL::InitializeOneOff failed.
[0901/181556.282236:ERROR:viz_main_impl.cc(186)] Exiting GPU process due to errors during initialization
[0901/181556.293746:ERROR:angle_platform_impl.cc(43)] Display.cpp:1006 (initialize): ANGLE Display::initialize error 0: Internal Vulkan error (-3): Initialization of an object could not be completed for implementation-specific reasons, in ../../third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp, initialize:1297.
[0901/181556.293875:ERROR:gl_surface_egl.cc(822)] EGL Driver message (Critical) eglInitialize: Internal Vulkan error (-3): Initialization of an object could not be completed for implementation-specific reasons, in ../../third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp, initialize:1297.
[0901/181556.293975:ERROR:gl_surface_egl.cc(1352)] eglInitialize SwANGLE failed with error EGL_NOT_INITIALIZED
[0901/181556.294037:ERROR:gl_ozone_egl.cc(21)] GLSurfaceEGL::InitializeOneOff failed.
[0901/181556.296132:ERROR:viz_main_impl.cc(186)] Exiting GPU process due to errors during initialization
[0901/181556.304228:ERROR:gpu_init.cc(486)] Passthrough is not supported, GL is disabled, ANGLE is 
[0901/181603.420651:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181603.463815:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181603.470868:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181603.782953:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181603.797931:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181603.855075:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181603.860402:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181605.298380:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181605.319576:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181605.381860:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181605.386971:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181606.854612:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181606.875266:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181606.935684:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181606.940904:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181608.414470:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181608.433068:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181608.481420:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181608.507104:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181608.511707:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181608.516502:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181622.381356:ERROR:gpu_process_host.cc(975)] GPU process exited unexpectedly: exit_code=133
[0901/181622.382396:WARNING:gpu_process_host.cc(1277)] The GPU process has crashed 1 time(s)
[0901/181622.404796:ERROR:gpu_init.cc(486)] Passthrough is not supported, GL is disabled, ANGLE is 
[0901/181622.470167:WARNING:gpu_process_host.cc(998)] Reinitialized the GPU process after a crash. The reported initialization time was 0 ms
[0901/181624.320788:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181624.371848:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181624.380380:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181705.097550:ERROR:gpu_process_host.cc(975)] GPU process exited unexpectedly: exit_code=133
[0901/181705.097568:WARNING:gpu_process_host.cc(1277)] The GPU process has crashed 2 time(s)
[0901/181705.110907:ERROR:gpu_init.cc(486)] Passthrough is not supported, GL is disabled, ANGLE is 
[0901/181705.167147:WARNING:gpu_process_host.cc(998)] Reinitialized the GPU process after a crash. The reported initialization time was 0 ms
[0901/181707.024655:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181707.079437:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181707.084937:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw
[0901/181715.707501:ERROR:gpu_process_host.cc(975)] GPU process exited unexpectedly: exit_code=133
[0901/181715.707520:WARNING:gpu_process_host.cc(1277)] The GPU process has crashed 3 time(s)
[0901/181715.707535:FATAL:gpu_data_manager_impl_private.cc(451)] GPU process isn't usable. Goodbye.
Saved file as img
JackGreenEarth commented 1 year ago

Not to say that otherwise I am not very pleased with this library - I am.

vgalin commented 1 year ago

Hello,

Your example is very detailed, but it is incomplete and I can't test it on my machine. The errors and warnings you're seeing come directly from Chrome/Chromium and are not directly related to Html2Image. Could you try to add the following flags to see if that fixes the issue ? --disable-software-rasterizer, --disable-gpu

You can add them like so, anytime before taking a screenshot:

hti.browser.flags.extend(['--disable-software-rasterizer', '--disable-gpu'])
JackGreenEarth commented 1 year ago

I added the flags, and still got this error:

[0904/170221.066356:ERROR:gpu_init.cc(486)] Passthrough is not supported, GL is disabled, ANGLE is [0904/170221.112086:WARNING:bluez_dbus_manager.cc(247)] Floss manager not present, cannot set Floss enable/disable. [0904/170227.087723:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170227.098913:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170227.197267:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170227.204016:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170227.239898:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170227.244365:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170228.707586:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170228.725228:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170228.788953:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170228.793568:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170230.482312:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170230.498721:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170230.562093:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170230.567393:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170232.340582:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170232.355006:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170232.393031:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170232.418766:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170232.423412:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170232.428409:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170240.501397:ERROR:gpu_process_host.cc(975)] GPU process exited unexpectedly: exit_code=133 [0904/170240.501460:WARNING:gpu_process_host.cc(1277)] The GPU process has crashed 1 time(s) [0904/170240.510762:ERROR:gpu_init.cc(486)] Passthrough is not supported, GL is disabled, ANGLE is [0904/170240.556236:WARNING:gpu_process_host.cc(998)] Reinitialized the GPU process after a crash. The reported initialization time was 0 ms [0904/170242.507122:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170242.538026:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170242.543919:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170249.508450:ERROR:gpu_process_host.cc(975)] GPU process exited unexpectedly: exit_code=133 [0904/170249.508502:WARNING:gpu_process_host.cc(1277)] The GPU process has crashed 2 time(s) [0904/170249.517680:ERROR:gpu_init.cc(486)] Passthrough is not supported, GL is disabled, ANGLE is [0904/170249.568724:WARNING:gpu_process_host.cc(998)] Reinitialized the GPU process after a crash. The reported initialization time was 0 ms [0904/170251.454175:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170251.485215:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170251.491110:ERROR:tile_manager.cc(827)] WARNING: tile memory limits exceeded, some content may not draw [0904/170320.806100:ERROR:gpu_process_host.cc(975)] GPU process exited unexpectedly: exit_code=133 [0904/170320.806125:WARNING:gpu_process_host.cc(1277)] The GPU process has crashed 3 time(s) [0904/170320.806147:FATAL:gpu_data_manager_impl_private.cc(451)] GPU process isn't usable. Goodbye.

What did you mean the example is incomplete?

You can download the project here. Choose '2048 Wallpaper'.

vgalin commented 1 year ago

"Minimal reproducible examples" (you can read about it here) are usually appreciated when asking for help online with code or debugging.

In our case, I'm missing the options.json and template.html files, so the code can't be run. It's not a big deal for the json file, but it's more problematic for the html file.

Concerning the errors, I don't think there is anything I can really do. Html2Image is only but a wrapper around the headless mode of existing browsers, such as Chrome. The errors that are displayed in your console are printed by Chrome, meaning the browser has some issues with the files you gave it (or the configuration of the browser itself, or maybe there is a bug with this version, etc.).

When searching for WARNING: tile memory limits exceeded, you can find threads such as this one suggesting to update your chrome version for force a specific version. If this doesn't help, I'm afraid that I won't be able to help more, the only things that could be done are:

If you have the template.html file, I could try to see if i get the same errors.

JackGreenEarth commented 1 year ago

I gave you a link to download the whole project, including the other files.

vgalin commented 1 year ago

The only file I can see in the archive is Code Generator.py (+ an .idea and a venv folder).

JackGreenEarth commented 1 year ago

Did you open it in Pycharm?

JackGreenEarth commented 1 year ago

https://drive.google.com/drive/folders/1NvXKcudcNjMAR3h5eyh95XnLpJyLdjZD?usp=sharing