1inkusFace commited on
Commit
d6e6cce
·
verified ·
1 Parent(s): 07f2f65

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -43
app.py CHANGED
@@ -45,8 +45,9 @@ import threading
45
  import io
46
  from PIL import Image
47
 
48
- # For Ultra HDR
49
- import pillow_ultrahdr
 
50
 
51
  from google.oauth2 import service_account
52
  from google.cloud import storage
@@ -176,6 +177,36 @@ def srgb_to_linear(img_tensor):
176
  ((img_tensor + 0.055) / 1.055).pow(2.4)
177
  )
178
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  pipe, upscaler_2 = load_model()
180
 
181
  fa_processor = FlashAttentionProcessor()
@@ -207,50 +238,22 @@ def generate_images(duration, prompt, neg_prompt_1, neg_prompt_2, neg_prompt_3,
207
  guidance_scale=guidance, num_inference_steps=steps,
208
  width=width, height=height, generator=generator,
209
  max_sequence_length=384,
210
- output_type="pt" # Request tensor output
211
- ).images
212
 
213
  # Convert the sRGB tensor [0,1] to a PIL Image for display and upscaling
214
  sd_image_pil_srgb = Image.fromarray((sd_image_tensor_srgb.squeeze(0).permute(1, 2, 0).cpu().numpy() * 255).astype(np.uint8))
215
- print('-- got image --')
216
-
217
- # --- Upscaling ---
218
- torch.cuda.empty_cache()
219
- torch.cuda.reset_peak_memory_stats()
220
- with torch.no_grad():
221
- upscale = upscaler_2(sd_image_pil_srgb, tiling=True, tile_width=256, tile_height=256)
222
- upscale2 = upscaler_2(upscale, tiling=True, tile_width=256, tile_height=256)
223
- print('-- got upscaled image --')
224
-
225
- # --- HDR Conversion and Saving ---
226
- # Convert the original sRGB tensor to linear space
227
- sd_image_tensor_linear = srgb_to_linear(sd_image_tensor_srgb)
228
- # Convert the linear tensor to a PIL Image (this will be HDR data)
229
- sd_image_pil_linear = Image.fromarray((sd_image_tensor_linear.squeeze(0).permute(1, 2, 0).clamp(0, 1).cpu().numpy() * 255).astype(np.uint8))
230
-
231
- # Save to a bytes buffer as JPEG Ultra HDR
232
- buffer = io.BytesIO()
233
- pillow_ultrahdr.save_ultrahdr(
234
- sdr=sd_image_pil_srgb, # The standard dynamic range image
235
- hdr=sd_image_pil_linear, # The linear (high dynamic range) image
236
- outfile=buffer,
237
- quality=90 # Standard JPEG quality setting
238
- )
239
- hdr_image_bytes = buffer.getvalue()
240
-
241
- # For the upscaled image, we will do the same
242
- # First convert upscaled PIL image to tensor, normalize to [0,1]
243
- upscaled_tensor_srgb = torch.from_numpy(np.array(upscale2)).float().to(device) / 255.0
244
- upscaled_tensor_srgb = upscaled_tensor_srgb.permute(2, 0, 1).unsqueeze(0) # HWC to BCHW
245
- upscaled_tensor_linear = srgb_to_linear(upscaled_tensor_srgb)
246
- upscaled_pil_linear = Image.fromarray((upscaled_tensor_linear.squeeze(0).permute(1, 2, 0).clamp(0, 1).cpu().numpy() * 255).astype(np.uint8))
247
-
248
- upscaled_buffer = io.BytesIO()
249
- pillow_ultrahdr.save_ultrahdr(sdr=upscale2, hdr=upscaled_pil_linear, outfile=upscaled_buffer, quality=95)
250
- upscaled_hdr_image_bytes = upscaled_buffer.getvalue()
251
-
252
- # Return the sRGB PIL image for display, and the HDR bytes for upload
253
- return sd_image_pil_srgb, hdr_image_bytes, upscaled_hdr_image_bytes, prompt
254
 
255
  return _generate()
256
 
 
45
  import io
46
  from PIL import Image
47
 
48
+ # For HDR
49
+ import pillow_avif
50
+ import cv2
51
 
52
  from google.oauth2 import service_account
53
  from google.cloud import storage
 
177
  ((img_tensor + 0.055) / 1.055).pow(2.4)
178
  )
179
 
180
+ def create_hdr_avif_bytes(sdr_pil_image):
181
+ """Converts an SDR PIL image to a 10-bit HDR AVIF byte buffer."""
182
+ # 1. Convert SDR PIL image to a float tensor [0, 1]
183
+ srgb_tensor = torch.from_numpy(np.array(sdr_pil_image)).float().to(device) / 255.0
184
+ srgb_tensor = srgb_tensor.permute(2, 0, 1).unsqueeze(0) # HWC to BCHW
185
+
186
+ # 2. Convert sRGB tensor to linear space
187
+ linear_tensor = srgb_to_linear(srgb_tensor)
188
+
189
+ # 3. Convert to 16-bit NumPy array for high-bit-depth processing
190
+ linear_numpy_float = linear_tensor.squeeze(0).permute(1, 2, 0).cpu().numpy()
191
+ hdr_16bit_array = (np.clip(linear_numpy_float, 0, 1) * 65535).astype(np.uint16)
192
+
193
+ # 4. Create a PIL image that holds the 16-bit data
194
+ hdr_pil_image = Image.fromarray(hdr_16bit_array)
195
+
196
+ # 5. Save to a bytes buffer as 10-bit AVIF with HDR10 metadata
197
+ buffer = io.BytesIO()
198
+ hdr_pil_image.save(
199
+ buffer,
200
+ format="AVIF",
201
+ quality=90,
202
+ depth=10, # Specify 10-bit depth
203
+ subsampling="4:4:4",
204
+ color_primaries=9, # BT.2020
205
+ transfer_characteristics=16, # PQ (Perceptual Quantizer)
206
+ matrix_coefficients=9, # BT.2020 non-constant luminance
207
+ )
208
+ return buffer.getvalue()
209
+
210
  pipe, upscaler_2 = load_model()
211
 
212
  fa_processor = FlashAttentionProcessor()
 
238
  guidance_scale=guidance, num_inference_steps=steps,
239
  width=width, height=height, generator=generator,
240
  max_sequence_length=384,
241
+ output_type="pil" # Get PIL for display and easy upscaling
242
+ ).images[0]
243
 
244
  # Convert the sRGB tensor [0,1] to a PIL Image for display and upscaling
245
  sd_image_pil_srgb = Image.fromarray((sd_image_tensor_srgb.squeeze(0).permute(1, 2, 0).cpu().numpy() * 255).astype(np.uint8))
246
+ print('-- got image, creating HDR AVIF version --')
247
+ sd_avif_bytes = create_hdr_avif_bytes(sd_image_srgb_pil)
248
+
249
+ print('-- upscaling image --')
250
+ with torch.no_grad():
251
+ upscale = upscaler_2(sd_image_srgb_pil, tiling=True, tile_width=256, tile_height=256)
252
+ upscale2 = upscaler_2(upscale, tiling=True, tile_width=256, tile_height=256)
253
+ print('-- got upscaled image, creating upscaled HDR AVIF --')
254
+ upscaled_avif_bytes = create_hdr_avif_bytes(upscale2)
255
+
256
+ return sd_image_srgb_pil, sd_avif_bytes, upscaled_avif_bytes, prompt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
 
258
  return _generate()
259