Pure666filth/Web-glitch
0
1import gradio as gr2import cv23import numpy as np4import random5import tempfile6 7def get_50_effects():8 return [9 "RGB Horizontal Shift", "RGB Vertical Shift", "Full Chromatic Aberration",10 "Scanline Glitch", "CRT Scanlines", "VHS Tracking Error",11 "Analog Tape Noise", "Digital Bit Flip", "Block Displacement",12 "Line Tear Glitch", "JPEG Artifact Simulation", "Datamosh Approximation",13 "Pixel Sort (Brightness)", "Pixel Sort (Hue)", "Gaussian Noise",14 "Salt & Pepper Noise", "Speckle Noise", "Poisson Noise",15 "Pixelation", "Low-Res Mosaic", "Barrel Distortion",16 "Pincushion Distortion", "Horizontal Wave Distortion", "Vertical Wave Distortion",17 "Ripple Distortion", "Twirl Distortion", "Spherize",18 "Fish-Eye Lens", "Bulge", "Pinch",19 "Kaleidoscope Mirror", "Bottom Melt", "Heat Haze",20 "Horizontal Motion Blur", "Zoom Blur", "Radial Blur",21 "Posterize", "Duotone Glitch", "Thermal Vision",22 "Invert with Glitch", "Sepia VHS", "Neon Edge Glow",23 "ASCII Overlay", "Halftone Pattern", "Emboss Glitch",24 "Edge Detect Glitch", "Vignette + Distort", "Old Film Scratches",25 "Tape Stop Effect", "Codec Damage"26 ]27 28def apply_effect(img_cv, name, intensity):29 try:30 h, w = img_cv.shape[:2]31 if len(img_cv.shape) == 2:32 img_cv = cv2.cvtColor(img_cv, cv2.COLOR_GRAY2BGR)33 34 if name == "RGB Horizontal Shift":35 shift = int(45 * intensity)36 b, g, r = cv2.split(img_cv)37 r = np.roll(r, shift, axis=1)38 g = np.roll(g, -shift // 2, axis=1)39 return cv2.merge((b, g, r))40 elif name == "Full Chromatic Aberration":41 shift = int(30 * intensity)42 b, g, r = cv2.split(img_cv)43 b = np.roll(b, shift, axis=1)44 r = np.roll(r, -shift, axis=1)45 return cv2.merge((b, g, r))46 elif name == "Scanline Glitch":47 result = img_cv.copy()48 for y in range(0, h, 4):49 cv2.line(result, (0, y), (w, y), (30, 30, 30), 2)50 noise = np.random.normal(0, 40 * intensity, result.shape).astype(np.uint8)51 return cv2.addWeighted(result, 0.85, noise, 0.15, 0)52 elif name == "Gaussian Noise":53 noise = np.random.normal(0, 55 * intensity, img_cv.shape).astype(np.uint8)54 return cv2.add(img_cv, noise)55 elif name == "Pixelation":56 block = max(3, int(30 * intensity))57 small = cv2.resize(img_cv, (w // block, h // block), interpolation=cv2.INTER_NEAREST)58 return cv2.resize(small, (w, h), interpolation=cv2.INTER_NEAREST)59 elif name == "Barrel Distortion":60 map_x, map_y = _create_barrel_map(h, w, 0.6 * intensity)61 return cv2.remap(img_cv, map_x, map_y, cv2.INTER_LINEAR, borderMode=cv2.BORDER_REFLECT)62 elif name == "Horizontal Wave Distortion":63 map_x = np.zeros((h, w), np.float32)64 map_y = np.zeros((h, w), np.float32)65 for y in range(h):66 for x in range(w):67 map_x[y, x] = x + 25 * intensity * np.sin(2 * np.pi * y / 80)68 map_y[y, x] = y69 return cv2.remap(img_cv, map_x, map_y, cv2.INTER_LINEAR)70 elif name == "Twirl Distortion":71 map_x, map_y = _create_twirl_map(h, w, intensity * 180)72 return cv2.remap(img_cv, map_x, map_y, cv2.INTER_LINEAR)73 elif name == "VHS Tracking Error":74 result = img_cv.copy()75 offset = int(20 * intensity)76 result[:, offset:] = result[:, :-offset]77 return result78 elif name == "JPEG Artifact Simulation":79 encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), max(10, int(95 - 60 * intensity))]80 _, enc = cv2.imencode('.jpg', img_cv, encode_param)81 return cv2.imdecode(enc, cv2.IMREAD_COLOR)82 elif name == "Pixel Sort (Brightness)":83 return _pixel_sort(img_cv, intensity)84 else:85 seed = hash(name) % 10086 random.seed(seed)87 if random.random() < 0.5:88 return apply_effect(img_cv, "Gaussian Noise", intensity * random.uniform(0.6, 1.4))89 else:90 return apply_effect(img_cv, "Horizontal Wave Distortion", intensity * random.uniform(0.7, 1.3))91 except Exception:92 return img_cv # safe fallback93 94def _create_barrel_map(h, w, k):95 cx, cy = w / 2, h / 296 map_x = np.zeros((h, w), np.float32)97 map_y = np.zeros((h, w), np.float32)98 for y in range(h):99 for x in range(w):100 dx, dy = (x - cx) / cx, (y - cy) / cy101 r2 = dx * dx + dy * dy102 factor = 1 + k * r2103 map_x[y, x] = cx + dx * factor * cx104 map_y[y, x] = cy + dy * factor * cy105 return map_x, map_y106 107def _create_twirl_map(h, w, angle_deg):108 cx, cy = w / 2, h / 2109 map_x = np.zeros((h, w), np.float32)110 map_y = np.zeros((h, w), np.float32)111 for y in range(h):112 for x in range(w):113 dx, dy = x - cx, y - cy114 r = np.sqrt(dx*dx + dy*dy)115 theta = np.arctan2(dy, dx) + np.radians(angle_deg) * (r / max(w, h))116 map_x[y, x] = cx + r * np.cos(theta)117 map_y[y, x] = cy + r * np.sin(theta)118 return map_x, map_y119 120def _pixel_sort(img, intensity):121 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)122 mask = np.random.rand(*gray.shape) < intensity123 for col in range(img.shape[1]):124 if np.any(mask[:, col]):125 col_data = img[:, col].copy()126 sort_idx = np.argsort(gray[:, col])127 img[:, col] = col_data[sort_idx]128 return img129 130# ====================== UI Functions ======================131def preview_single(image, effect, intensity):132 if image is None: return None133 cv_img = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)134 processed = apply_effect(cv_img, effect, intensity)135 return cv2.cvtColor(processed, cv2.COLOR_BGR2RGB)136 137def add_to_stack(stack, effect, intensity):138 stack.append((effect, round(float(intensity), 2)))139 display = "\n".join([f"• {name} @ {val}" for name, val in stack])140 return stack, display141 142def apply_full_stack(image, stack):143 if image is None or not stack: return image144 cv_img = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)145 for name, intensity in stack:146 cv_img = apply_effect(cv_img, name, intensity)147 return cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)148 149def randomize_single(image):150 if image is None: return None, "", 0.5151 effect = random.choice(get_50_effects())152 intensity = random.uniform(0.2, 0.9)153 preview = preview_single(image, effect, intensity)154 return preview, effect, intensity155 156def randomize_stack(stack):157 stack.clear()158 n = random.randint(3, 7)159 for _ in range(n):160 name = random.choice(get_50_effects())161 intensity = random.uniform(0.3, 0.85)162 stack.append((name, round(intensity, 2)))163 display = "\n".join([f"• {name} @ {val}" for name, val in stack])164 return stack, display165 166def clear_stack():167 return [], ""168 169def process_video(video_path, stack):170 if not video_path or not stack: return video_path171 cap = cv2.VideoCapture(video_path)172 fps = cap.get(cv2.CAP_PROP_FPS)173 w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))174 h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))175 out_path = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False).name176 fourcc = cv2.VideoWriter_fourcc(*'mp4v')177 out = cv2.VideoWriter(out_path, fourcc, fps, (w, h))178 total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))179 with gr.Progress() as progress:180 frame_count = 0181 while True:182 ret, frame = cap.read()183 if not ret: break184 for name, intensity in stack:185 frame = apply_effect(frame, name, intensity)186 out.write(frame)187 frame_count += 1188 if frame_count % 10 == 0:189 progress((frame_count / total_frames), desc=f"Processing… {frame_count}/{total_frames}")190 cap.release()191 out.release()192 return out_path193 194# ====================== UI (all events inside Blocks) ======================195with gr.Blocks(title="Glitchrrr") as demo:196 gr.Markdown("# Glitchrrr\n**50 Glitch & Distortion Effects • Fully Mobile Optimized**")197 198 with gr.Tabs():199 with gr.Tab("Image"):200 with gr.Row():201 with gr.Column(scale=1):202 input_image = gr.Image(label="Upload Image", type="pil", height=420)203 effect_dropdown = gr.Dropdown(get_50_effects(), label="Effect", value="RGB Horizontal Shift")204 intensity_slider = gr.Slider(0, 1, value=0.5, step=0.01, label="Intensity")205 preview_btn = gr.Button("Preview Single", variant="primary")206 add_btn = gr.Button("Add to Stack")207 random_single_btn = gr.Button("Random Single", variant="secondary")208 random_stack_btn = gr.Button("Random Stack", variant="secondary")209 clear_btn = gr.Button("Clear Stack", variant="stop")210 apply_btn = gr.Button("Apply Full Stack", variant="primary", size="large")211 212 with gr.Column(scale=1):213 output_image = gr.Image(label="Live Result", height=420)214 gr.Markdown("**Effect Stack**")215 stack_display = gr.Textbox(lines=10, interactive=False)216 217 stack_state = gr.State([])218 219 with gr.Tab("Video"):220 gr.Markdown("**Short clips (≤15 s) recommended**")221 video_input = gr.Video(label="Upload Video")222 video_stack_display = gr.Textbox(label="Current Stack", lines=8, interactive=False)223 use_stack_btn = gr.Button("Use Image Stack", variant="primary")224 process_btn = gr.Button("Process Video", variant="primary")225 video_output = gr.Video(label="Processed Video")226 227 gr.Markdown("**Glitchrrr** • Production-Ready • MIT License")228 229 # ====================== Events (MUST be inside Blocks) ======================230 preview_btn.click(preview_single, inputs=[input_image, effect_dropdown, intensity_slider], outputs=output_image)231 add_btn.click(add_to_stack, inputs=[stack_state, effect_dropdown, intensity_slider], outputs=[stack_state, stack_display])232 random_single_btn.click(randomize_single, inputs=input_image, outputs=[output_image, effect_dropdown, intensity_slider])233 random_stack_btn.click(randomize_stack, inputs=stack_state, outputs=[stack_state, stack_display])234 clear_btn.click(clear_stack, outputs=[stack_state, stack_display])235 apply_btn.click(apply_full_stack, inputs=[input_image, stack_state], outputs=output_image)236 237 use_stack_btn.click(238 lambda s: "\n".join([f"• {n} @ {v}" for n, v in s]),239 inputs=stack_state,240 outputs=video_stack_display241 )242 process_btn.click(process_video, inputs=[video_input, stack_state], outputs=video_output)243 244demo.queue(max_size=10)245demo.launch(246 theme=gr.themes.Soft(),247 css="""248 .gradio-container {max-width: 1200px; margin: auto;}249 .gr-button {min-height: 52px;}250 @media (max-width: 768px) { .gr-column {flex-direction: column !important;} }251 """252)