forked from ucupumar/hdr-2-rgbm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
__init__.py
119 lines (94 loc) · 3.68 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
bl_info = {
"name": "HDR 2 RGBM",
"author": "Yusuf Umar, Henrik Melsom",
"version": (0, 0, 0),
"blender": (2, 80, 0),
"location": "Anywhere",
"description": "Encode (and decode) HDR image into RGBM format",
"wiki_url": "http://twitter.com/ucupumar",
"category": "Material",
}
import bpy, math, os
from bpy.app.handlers import persistent
# function to clamp float
def saturate(num, floats=True):
if num < 0:
num = 0
elif num > (1 if floats else 255):
num = (1 if floats else 255)
return num
class EncodeToRGBM(bpy.types.Operator):
"""Encodes the currently viewed HDR image to RGBM format"""
bl_idname = "image.encode_to_rgbm"
bl_label = "Encode HDR to RGBM"
bl_description = "Encode HDR/float image to RGBM format. Create new image with '_RGBM.png' prefix"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
sima = context.space_data
return sima.type == 'IMAGE_EDITOR' and sima.image and sima.image.is_float
def execute(self, context):
sima = context.space_data
# Image
ima = sima.image
ima_name = ima.name
if ima.colorspace_settings.name != 'Linear':
ima.colorspace_settings.name = 'Linear'
# Removing .exr or .hdr prefix
if ima_name[-4:] == '.exr' or ima_name[-4:] == '.hdr':
ima_name = ima_name[:-4]
target_ima = bpy.data.images.get(ima_name + '_RGBM.png')
if not target_ima:
target_ima = bpy.data.images.new(
name = ima_name + '_RGBM.png',
width = ima.size[0],
height = ima.size[1],
alpha = True,
float_buffer = False
)
num_pixels = len(ima.pixels)
result_pixel = list(ima.pixels)
# Encode to RGBM
for i in range(0,num_pixels,4):
for j in range(3):
result_pixel[i+j] **= 1.0 / 2.2 # Linear to gamma
result_pixel[i+j] *= 1.0 / 6.0
result_pixel[i+3] = saturate(max(result_pixel[i], result_pixel[i+1], result_pixel[i+2], 1e-6))
result_pixel[i+3] = math.ceil(result_pixel[i+3] * 255.0) / 255.0;
for j in range(3):
result_pixel[i+j] /= result_pixel[i+3]
target_ima.pixels = result_pixel
sima.image = target_ima
return {'FINISHED'}
def draw(self, context):
row = self.layout.row()
row.label(text="Convert:")
row = self.layout.row()
row.operator("image.encode_to_rgbm")
def register():
bpy.utils.register_class(EncodeToRGBM)
bpy.types.IMAGE_PT_image_properties.append(draw)
def unregister():
bpy.types.IMAGE_PT_image_properties.remove(draw)
bpy.utils.unregister_class(EncodeToRGBM)
@persistent
def load_node_groups(scene):
root = bpy.utils.script_path_user()
sep = os.sep
# get addons folder
filepath = root + sep + "addons"
# Dealing with two possible name for addon folder
dirs = next(os.walk(filepath))[1]
folder = [x for x in dirs if x == 'hdr-2-rgbm' or x == 'hdr-2-rgbm-master'][0]
# Node groups necessary are in nodegroups_lib.blend
filepath = filepath + sep + folder + sep + "nodegroups_lib.blend"
# Load node groups
with bpy.data.libraries.load(filepath) as (data_from, data_to):
exist_groups = [ng.name for ng in bpy.data.node_groups]
for ng in data_from.node_groups:
if ng not in exist_groups:
data_to.node_groups.append(ng)
# Load decode rgbm node groups after loading blend file
bpy.app.handlers.load_post.append(load_node_groups)
if __name__ == "__main__":
register()