Skip to content

Instantly share code, notes, and snippets.

@jwlawson jwlawson/rescale.py Secret
Last active Mar 13, 2017

Embed
What would you like to do?
Blender add-on which provides a function in the VSE to rescale images to their original aspect ratio.
"""
Blender add-on which provides a function in the VSE to rescale images to their
original aspect ratio.
Due to the inclusion of code licensed under GPLv2, this too is licensed under
GPLv2. See: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
"""
import bpy
import os
import struct, imghdr, re
bl_info = {
"name": "Rescale VSE Images",
"description": "Adds transform layer to image to rescale to original aspect",
"author": "J Lawson",
"version": (1, 0),
"blender": (2, 77, 0),
"location": "?",
"warning": "", # used for warning icon and text in addons panel
"wiki_url": "",
"tracker_url": "",
"support": "COMMUNITY",
"category": "Sequencer"
}
def get_image_size(fname):
"""
Return (width, height) for a given img file content.
This function is heavily based on a similar funtion in `image.py` from the
Draco dynamic web content system in python. Draco is available under the
GPLv2.
There are a number of similar functions floating around stack exchange, with
slight changes to functionality. The version included here is based on
Yantao Xie's version found here:
https://stackoverflow.com/questions/15800704/
python-get-image-size-without-loading-image-into-memory
"""
with open(fname, 'rb') as fhandle:
head = fhandle.read(32)
if len(head) != 32:
return
if imghdr.what(fname) == 'png':
check = struct.unpack('>i', head[4:8])[0]
if check != 0x0d0a1a0a:
return
width, height = struct.unpack('>ii', head[16:24])
elif imghdr.what(fname) == 'gif':
width, height = struct.unpack('<HH', head[6:10])
elif imghdr.what(fname) == 'jpeg':
try:
fhandle.seek(0) # Read 0xff next
size = 2
ftype = 0
while not 0xc0 <= ftype <= 0xcf:
fhandle.seek(size, 1)
byte = fhandle.read(1)
while ord(byte) == 0xff:
byte = fhandle.read(1)
ftype = ord(byte)
size = struct.unpack('>H', fhandle.read(2))[0] - 2
# We are at a SOFn block
fhandle.seek(1, 1) # Skip `precision' byte.
height, width = struct.unpack('>HH', fhandle.read(4))
except Exception: #IGNORE:W0703
return
elif imghdr.what(fname) == 'pgm':
header, width, height, maxval = re.search(
b"(^P5\s(?:\s*#.*[\r\n])*"
b"(\d+)\s(?:\s*#.*[\r\n])*"
b"(\d+)\s(?:\s*#.*[\r\n])*"
b"(\d+)\s(?:\s*#.*[\r\n]\s)*)", head).groups()
width = int(width)
height = int(height)
elif imghdr.what(fname) == 'bmp':
_, width, height, depth = re.search(
b"((\d+)\sx\s"
b"(\d+)\sx\s"
b"(\d+))", str).groups()
width = int(width)
height = int(height)
else:
return
return width, height
class Rescale_VSE_Image(bpy.types.Operator):
bl_label = 'Rescale VSE Image'
bl_idname = 'sequencerextra.rescaleimage'
bl_description = 'Adds transform layer to image to rescale to original aspect'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
""" Ensure that the function is only available for images """
scn = context.scene
strip = scn.sequence_editor.active_strip
if scn and scn.sequence_editor and strip:
return strip.type in ('IMAGE')
else:
return False
def execute(self, context):
"""
1. Get the image path
2. Find the size of the image
3. Apply a transform to scale the image correctly
"""
scn = context.scene
strip = scn.sequence_editor.active_strip
file = os.path.realpath(bpy.data.filepath + "/.." + strip.directory + strip.name)
size = get_image_size(file)
render_setting = scn.render
render_x = render_setting.resolution_x
render_y = render_setting.resolution_y
bpy.ops.sequencer.effect_strip_add(type='TRANSFORM')
transform = scn.sequence_editor.active_strip
transform.scale_start_x = render_y/render_x*size[0]/size[1]
transform.scale_start_y = 1.0
return {'FINISHED'}
def register():
bpy.utils.register_class(Rescale_VSE_Image)
def unregister():
bpy.utils.unregister_class(Rescale_VSE_Image)
"""
Blender add-on which provides a function in the VSE to rescale images to their
original aspect ratio.
"""
import bpy
import os
from PIL import Image
bl_info = {
"name": "Rescale VSE Images",
"description": "Adds transform layer to image to rescale to original aspect",
"author": "J Lawson",
"version": (1, 0),
"blender": (2, 77, 0),
"location": "?",
"warning": "", # used for warning icon and text in addons panel
"wiki_url": "",
"tracker_url": "",
"support": "COMMUNITY",
"category": "Sequencer"
}
def get_image_size(fname):
with Image.open(filename) as img:
return img.size
class Rescale_VSE_Image(bpy.types.Operator):
bl_label = 'Rescale VSE Image'
bl_idname = 'sequencerextra.rescaleimage'
bl_description = 'Adds transform layer to image to rescale to original aspect'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
""" Ensure that the function is only available for images """
scn = context.scene
strip = scn.sequence_editor.active_strip
if scn and scn.sequence_editor and strip:
return strip.type in ('IMAGE')
else:
return False
def execute(self, context):
"""
1. Get the image path
2. Find the size of the image
3. Apply a transform to scale the image correctly
"""
scn = context.scene
strip = scn.sequence_editor.active_strip
file = os.path.realpath(bpy.data.filepath + "/.." + strip.directory + strip.name)
size = get_image_size(file)
render_setting = scn.render
render_x = render_setting.resolution_x
render_y = render_setting.resolution_y
bpy.ops.sequencer.effect_strip_add(type='TRANSFORM')
transform = scn.sequence_editor.active_strip
transform.scale_start_x = render_y/render_x*size[0]/size[1]
transform.scale_start_y = 1.0
return {'FINISHED'}
def register():
bpy.utils.register_class(Rescale_VSE_Image)
def unregister():
bpy.utils.unregister_class(Rescale_VSE_Image)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.