webcamEffectsmain.tsx7 matches
1/**
2* This app creates a webcam-based image processing application with spooky effects.
3* It requests webcam permissions, displays the video feed, and applies visual and audio effects.
4* We use React for the UI, the browser's MediaDevices API for webcam access,
175canvas.width = 64;
176canvas.height = 64;
177ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
178179const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
180const data = imageData.data;
181182// Add spooky aura overlay
251}
252253ctx.putImageData(imageData, 0, 0);
254255displayCanvas.width = video.videoWidth;
256displayCanvas.height = video.videoHeight;
257displayCtx.imageSmoothingEnabled = false;
258displayCtx.drawImage(canvas, 0, 0, displayCanvas.width, displayCanvas.height);
259260animationFrameId = requestAnimationFrame(drawToCanvas);
pageSpeedAPImain.tsx9 matches
11<button className="close-btn" onClick={onClose}>×</button>
12<div className="popup-content">
13{content.type === 'images' && (
14<>
15<h3>Images</h3>
16<ul>
17{content.items.map((item, index) => (
121122const resourceSummary = audits['resource-summary']?.details?.items || [];
123const images = resourceSummary.find(item => item.resourceType === 'image') || { requestCount: 0, transferSize: 0 };
124const videos = resourceSummary.find(item => item.resourceType === 'media') || { requestCount: 0, transferSize: 0 };
125const totalBytes = resourceSummary.reduce((sum, item) => sum + (item.transferSize || 0), 0);
126127const networkRequests = audits['network-requests']?.details?.items || [];
128const imageItems = networkRequests.filter(item => item.resourceType === 'Image' || item.resourceType === 'image');
129const videoItems = networkRequests.filter(item => item.resourceType === 'Media' || item.resourceType === 'media');
130153cls: audits['cumulative-layout-shift']?.displayValue || 'N/A',
154performance: categories.performance ? `${Math.round(categories.performance.score * 100)}%` : 'N/A',
155images: {
156count: images.requestCount || 0,
157size: ((images.transferSize || 0) / 1024 / 1024).toFixed(2),
158items: imageItems
159},
160videos: {
227<li>Cumulative Layout Shift (CLS): {performanceMetrics.cls}</li>
228<li>Performance Score: {performanceMetrics.performance}</li>
229<li>Images: <span className="clickable" onClick={() => handleResourceClick('images')}>{performanceMetrics.images.count}</span> ({performanceMetrics.images.size} MB)</li>
230<li>Videos: <span className="clickable" onClick={() => handleResourceClick('videos')}>{performanceMetrics.videos.count}</span> ({performanceMetrics.videos.size} MB)</li>
231<li>Total Estimated Size: {performanceMetrics.totalSize}</li>
pageDetectormain.tsx28 matches
7const [result, setResult] = useState(null);
8const [loading, setLoading] = useState(false);
9const [showImageList, setShowImageList] = useState(false);
10const [showVideoList, setShowVideoList] = useState(false);
11const [showFullHtml, setShowFullHtml] = useState(false);
34};
3536const toggleImageList = () => {
37setShowImageList(!showImageList);
38setShowVideoList(false);
39};
41const toggleVideoList = () => {
42setShowVideoList(!showVideoList);
43setShowImageList(false);
44};
4548};
4950const downloadImage = async (imageUrl) => {
51try {
52const response = await fetch(imageUrl);
53const blob = await response.blob();
54const url = window.URL.createObjectURL(blob);
56a.style.display = 'none';
57a.href = url;
58a.download = imageUrl.split('/').pop();
59document.body.appendChild(a);
60a.click();
61window.URL.revokeObjectURL(url);
62} catch (error) {
63console.error("Error downloading image:", error);
64}
65};
123};
124125const ImageListPopup = ({ imageList }) => (
126<div className="popup image-list-popup">
127<h3>Image List</h3>
128<ul>
129{imageList.map((img, index) => (
130<li key={index}>
131<span className="clickable" onClick={() => downloadImage(img.url)}>{img.url}</span>
132<br />
133Size: {img.size} KB
178</div>
179</div>
180<p>Images: <span className="clickable" onClick={toggleImageList}>{result.imageCount}</span> (Estimated size: {result.estimatedImageSize.toFixed(2)} GB)</p>
181<p>Videos: <span className="clickable" onClick={toggleVideoList}>{result.videoCount}</span> (Estimated size: {result.estimatedVideoSize.toFixed(2)} GB)</p>
182<p>Total Estimated Size: {result.totalEstimatedSize.toFixed(2)} GB</p>
187<p>Availability: {result.availability}</p>
188</div>
189{showImageList && <ImageListPopup imageList={result.imageList} />}
190{showVideoList && <VideoListPopup videoList={result.videoList} />}
191<div className="html-preview">
229const pageContent = await response.text();
230
231// Image detection
232const imageRegex = /<img[^>]+src\s*=\s*['"]([^'"]+)['"][^>]*>|background-image:\s*url\(['"]?([^'"]+)['"]?\)/gi;
233const imageMatches = [...pageContent.matchAll(imageRegex)];
234const imageList = await Promise.all(imageMatches.map(async match => {
235const imgUrl = new URL(match[1] || match[2], url).href;
236try {
239return { url: imgUrl, size: size.toFixed(2) };
240} catch (error) {
241console.error(`Failed to fetch image: ${imgUrl}`, error);
242return { url: imgUrl, size: '0.00' };
243}
244}));
245const imageCount = imageList.length;
246247// Improved video detection and size estimation
265const videoCount = videoList.length;
266
267const estimatedImageSize = imageList.reduce((total, img) => total + parseFloat(img.size), 0) / 1024; // Convert KB to GB
268const estimatedVideoSize = videoList.reduce((total, video) => total + video.size, 0);
269const totalEstimatedSize = estimatedImageSize + estimatedVideoSize;
270271// Extract page title
306307// Estimate FCP based on page size and content (very rough estimation)
308const estimatedFCP = Math.min(1000, Math.max(100, totalEstimatedSize * 1000 + imageCount * 10 + videoCount * 50));
309310// Simple availability check
317url,
318pageTitle,
319imageCount,
320imageList,
321videoCount,
322videoList,
323estimatedImageSize,
324estimatedVideoSize,
325totalEstimatedSize,
510box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
511}
512.image-list-popup {
513background-color: #ffcccb;
514border-color: #ff0000;
115to avoid the nasty look shown in the "Text Indentation" section.
116117## Images ##
118119
multiplayerCirclesREADME.md1 match
3Move circles around. State is synced with the server. Open a window in another tab and watch the circles update as you move them .
45
6
slamBotPostmain.tsx39 matches
1import { createCanvas, loadImage } from "https://deno.land/x/canvas/mod.ts";
2import { blob } from "https://esm.town/v/std/blob";
3import { BLOB_PREFIX, POST_PREFIX, Slam } from "https://esm.town/v/dupontgu/findSlamArticles";
4import { Counter } from "https://esm.town/v/dupontgu/persistentCounter"
5import { blueskyPostWithImage } from "https://esm.town/v/dupontgu/heavenlyOrangeMarmoset"
67// Replace with your actual access token and Mastodon instance URL
9const MASTODON_URL = "https://mastodon.social";
1011interface Image {
12url: string
13// text locations within image, Vec3: [x, y, rotation]
14slammer_txt_loc: number[]
15slammed_txt_loc: number[],
17alt_txt: string
18}
19const images: Image[] = [
20{
21url:"https://bloximages.newyork1.vip.townnews.com/gazette.com/content/tncms/assets/v3/editorial/d/ea/dea0914b-9915-553c-bc42-81313201d4ac/5b32bb43c0f7e.image.jpg",
22slammer_txt_loc: [140, 190, -0.4],
23slammed_txt_loc: [90, 280, -0.0],
40},
41{
42url:"https://media.licdn.com/dms/image/v2/C4E12AQGcr20PW6r-Sw/article-cover_image-shrink_423_752/article-cover_image-shrink_423_752/0/1520115254001?e=1733356800&v=beta&t=OVWwDx4QhdF1IaMjSOOMpLRGRCnSVGp7Il_mERmKBGc",
43slammer_txt_loc: [180, 120, -0.0],
44slammed_txt_loc: [280, 330, -0.0],
61},
62{
63url:"https://i.dailymail.co.uk/1s/2024/03/19/04/82623845-13212905-image-a-89_1710821176313.jpg",
64slammer_txt_loc: [310, 440, -0.0],
65slammed_txt_loc: [170, 790, -0.0],
82},
83{
84url:"https://static.wikia.nocookie.net/international-pokedex/images/6/6a/Body_Slam_%28Ash%27s_Snorlax%29.png",
85slammer_txt_loc: [280, 100, -0.0],
86slammed_txt_loc: [240, 430, -0.0],
96},
97{
98url:"https://static.wikia.nocookie.net/baki/images/2/22/Tackle.png/revision/latest?cb=20170117232328",
99slammer_txt_loc: [150, 100, -0.0],
100slammed_txt_loc: [510, 350, -0.0],
110},
111{
112url:"https://static.wikia.nocookie.net/dragonball/images/2/2b/Gigantic_Spike.png/revision/latest/scale-to-width-down/1000?cb=20180515222853",
113slammer_txt_loc: [270, 100, -0.0],
114slammed_txt_loc: [340, 500, -0.0],
125]
126127async function uploadImage(imageBuffer: any, altText: string): Promise<string> {
128const formData = new FormData();
129formData.append("file", new Blob([imageBuffer], { type: "image/png" }));
130formData.append("description", altText);
131139140if (!uploadResponse.ok) {
141throw new Error("Failed to upload image");
142}
143146}
147148async function postStatusWithImage(statusText: string, imageBuffer: any, altText: string) {
149const mediaId = await uploadImage(imageBuffer, altText);
150151const postResponse = await fetch(`${MASTODON_URL}/api/v1/statuses`, {
157body: JSON.stringify({
158status: statusText,
159media_ids: [mediaId], // Attach the uploaded image by its media ID
160}),
161});
170}
171172async function overlayTextOnImage(slammer_text: string, slammed_text: string, imageDef: Image): Promise<Uint8Array> {
173const image = await loadImage(imageDef.url);
174let fontFile = await fetch(
175"https://github.com/sophilabs/macgifer/raw/master/static/font/impact.ttf",
177const fontBlob = await fontFile.blob();
178let fontBytes = new Uint8Array(await fontBlob.arrayBuffer());
179const canvas = createCanvas(image.width(), image.height());
180canvas.loadFont(fontBytes, { family: "Impact" });
181const ctx = canvas.getContext('2d');
182183ctx.drawImage(image, 0, 0, image.width(), image.height());
184ctx.fillStyle = 'white';
185ctx.strokeStyle = 'black';
189190const baseTextSize = 46;
191const slammer_size = (baseTextSize * imageDef.text_scale) - (slammer_text.length * imageDef.text_scale * 0.84)
192ctx.font = `${slammer_size}px Impact`;
193ctx.rotate(imageDef.slammer_txt_loc[2])
194let xAdjust = (slammer_text.length / 2) * 6
195ctx.strokeText(slammer_text, imageDef.slammer_txt_loc[0] - xAdjust, imageDef.slammer_txt_loc[1]);
196ctx.fillText(slammer_text, imageDef.slammer_txt_loc[0] - xAdjust, imageDef.slammer_txt_loc[1]);
197198// reset rotation
199ctx.rotate(-imageDef.slammer_txt_loc[2])
200const slammed_size = (baseTextSize * imageDef.text_scale) - (slammed_text.length * imageDef.text_scale * 0.84)
201ctx.font = `${slammed_size}px Impact`;
202ctx.rotate(imageDef.slammed_txt_loc[2])
203xAdjust = (slammed_text.length / 2) * 6
204ctx.strokeText(slammed_text, imageDef.slammed_txt_loc[0] - xAdjust, imageDef.slammed_txt_loc[1]);
205ctx.fillText(slammed_text, imageDef.slammed_txt_loc[0] - xAdjust, imageDef.slammed_txt_loc[1]);
206207return canvas.toBuffer('image/png');
208}
209216const postCounter = new Counter("SLAM_post_counter");
217const count = await postCounter.get()
218const image = images[count % images.length]
219// const image = images[images.length - 1]
220const modifiedImageBuffer = await overlayTextOnImage(slam.slammer, slam.slammed, image);
221const adjustedHeadline = slam.txt.replace('slams', 'SLAMS').replace('Slams', 'SLAMS')
222const statusText = `${adjustedHeadline}\n\n via \n${slam.url}`
223const altText = `${image.alt_txt}\n The slammer is labeled with ${slam.slammer} and the person or thing being slammed is labeled ${slam.slammed}.\n\n image source: ${image.url}`
224const mastoUrl = await postStatusWithImage(statusText, modifiedImageBuffer, altText)
225await blob.delete(inputs[0].key)
226await blob.setJSON(POST_PREFIX + slam.url, {url:mastoUrl})
227await postCounter.increment()
228await blueskyPostWithImage(statusText, modifiedImageBuffer, altText)
229return new Response(modifiedImageBuffer, {
230headers: {
231'Content-Type': 'image/png',
232},
233});
heavenlyOrangeMarmosetmain.tsx5 matches
1import { BskyAgent, BlobRef, RichText } from 'npm:@atproto/api';
23export async function blueskyPostWithImage(statusText: string, imageBuffer: any, altText: string) {
4const BSKY_EMAIL = Deno.env.get("BSKY_EMAIL");
5const BSKY_PWD = Deno.env.get("BSKY_PWD");
8const rt = new RichText({ text: statusText })
9await rt.detectFacets(agent)
10const { data } = await agent.uploadBlob(imageBuffer, { encoding: "png" })
11const postReuslt = await agent.post({
12text: rt.text,
13facets: rt.facets,
14embed: {
15$type: 'app.bsky.embed.images',
16images: [
17{
18image: data.blob,
19alt: altText
20}
1011<div align="center">
12<img src="https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/67a1d35e-c37c-41a4-0e5a-03a9ba585d00/public" width="500px"/>
13</div>
blob_adminREADME.md1 match
3This is a lightweight Blob Admin interface to view and debug your Blob data.
45
67Use this button to install the val:
blob_adminREADME.md1 match
3This is a lightweight Blob Admin interface to view and debug your Blob data.
45
67Use this button to install the val: