Val Town Code SearchReturn to Val Town

API Access

You can access search results via JSON API by adding format=json to your query:

https://codesearch.val.run/?q=image&page=223&format=json

For typeahead suggestions, use the /typeahead endpoint:

https://codesearch.val.run/typeahead?q=image

Returns an array of strings in format "username" or "username/projectName"

Found 2776 results for "image"(318ms)

OpenTownieImageUpload.tsx47 matches

@arfanUpdated 1 month ago
2import React, { useRef, useState } from "https://esm.sh/react@18.2.0?dev";
3
4// Maximum number of images that can be uploaded
5export const PROMPT_IMAGE_LIMIT = 5;
6
7interface ImageUploadProps {
8 images: (string | null)[];
9 setImages: (images: (string | null)[]) => void;
10 processFiles: (files: File[]) => void;
11}
12
13export function ImageUpload({ images, setImages, processFiles }: ImageUploadProps) {
14 const fileInputRef = useRef<HTMLInputElement>(null);
15
21 };
22
23 // Handle removing an image
24 const removeImage = (index: number) => {
25 const newImages = [...images];
26 newImages.splice(index, 1);
27 setImages(newImages);
28 };
29
30 // Check if we've reached the image limit
31 const isAtLimit = images.filter(Boolean).length >= PROMPT_IMAGE_LIMIT;
32
33 return (
34 <div className="w-full">
35 {/* Image previews */}
36 {images.length > 0 && (
37 <div className="flex flex-wrap gap-2 mb-2">
38 {images.map((image, index) => (
39 <div key={index} className="relative">
40 {image ? (
41 <div className="relative group">
42 <img
43 src={image}
44 alt={`Uploaded ${index + 1}`}
45 className="h-16 w-16 object-cover rounded border border-gray-300"
47 <button
48 className="absolute top-0 right-0 bg-red-500 text-white rounded-full w-5 h-5 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity"
49 onClick={() => removeImage(index)}
50 title="Remove image"
51 >
52 ×
68 ref={fileInputRef}
69 onChange={handleFileChange}
70 accept="image/*"
71 multiple
72 className="hidden"
80
81// Process files utility function - moved from the component to be reusable
82export const processFiles = async (files: File[], images: (string | null)[], setImages: (images: (string | null)[]) => void) => {
83 // Filter for image files only
84 const imageFiles = files.filter(file => file.type.startsWith('image/'));
85
86 // Limit the number of images
87 const filesToProcess = imageFiles.slice(0, PROMPT_IMAGE_LIMIT - images.filter(Boolean).length);
88
89 if (filesToProcess.length === 0) return;
90
91 // Add null placeholders for loading state
92 const newImages = [...images, ...Array(filesToProcess.length).fill(null)];
93 setImages(newImages);
94
95 // Process each file
96 const processedImages = await Promise.all(
97 filesToProcess.map(async (file) => {
98 return await readFileAsDataURL(file);
100 );
101
102 // Replace null placeholders with actual images
103 const updatedImages = [...images];
104 processedImages.forEach((dataUrl, index) => {
105 updatedImages[images.length + index] = dataUrl;
106 });
107
108 setImages(updatedImages.slice(0, PROMPT_IMAGE_LIMIT));
109};
110
115 reader.onload = () => {
116 const result = reader.result as string;
117 console.log("Image loaded, size:", result.length, "bytes");
118 resolve(result);
119 };
123};
124
125// Component to display images in messages
126export function ImagePreview({ images }: { images: string[] }) {
127 const [expandedImage, setExpandedImage] = useState<string | null>(null);
128
129 if (!images || images.length === 0) return null;
130
131 return (
132 <div className="mt-2">
133 <div className="flex flex-wrap gap-2">
134 {images.map((image, index) => (
135 <div key={index} className="relative">
136 <img
137 src={image}
138 alt={`Image ${index + 1}`}
139 className="max-h-32 max-w-32 object-contain rounded cursor-pointer"
140 onClick={() => setExpandedImage(image)}
141 />
142 </div>
144 </div>
145
146 {/* Modal for expanded image */}
147 {expandedImage && (
148 <div
149 className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50"
150 onClick={() => setExpandedImage(null)}
151 >
152 <div className="max-w-[90%] max-h-[90%]">
153 <img
154 src={expandedImage}
155 alt="Expanded view"
156 className="max-w-full max-h-full object-contain"

OpenTownieChat.tsx8 matches

@arfanUpdated 1 month ago
9import { ChatInput } from "./ChatInput.tsx";
10import { ApiKeyWarning } from "./ApiKeyWarning.tsx";
11import { processFiles } from "./ImageUpload.tsx";
12
13export function Chat({
25 const [soundEnabled, setSoundEnabled] = useLocalStorage<boolean>("soundEnabled", true);
26 const [selectedFiles, setSelectedFiles] = useState<string[]>([]);
27 const [images, setImages] = useState<(string | null)[]>([]);
28 const [isDragging, setIsDragging] = useState(false);
29
59 bearerToken,
60 selectedFiles,
61 images,
62 soundEnabled,
63 });
94
95 if (e.dataTransfer.files && !running) {
96 processFiles(Array.from(e.dataTransfer.files), images, setImages);
97 }
98 };
124
125 if (e.dataTransfer?.files && !running) {
126 processFiles(Array.from(e.dataTransfer.files), images, setImages);
127 }
128 };
141 document.removeEventListener('drop', handleDocumentDrop);
142 };
143 }, [images, running, setImages]);
144
145 return (
184 handleSubmit={handleSubmit}
185 running={running}
186 images={images}
187 setImages={setImages}
188 isDragging={isDragging}
189 />

OpenTownieChatInput.tsx19 matches

@arfanUpdated 1 month ago
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2import React, { useState, useEffect, useRef } from "https://esm.sh/react@18.2.0?dev";
3import { ImageUpload, processFiles } from "./ImageUpload.tsx";
4
5interface ChatInputProps {
8 handleSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
9 running: boolean;
10 images: (string | null)[];
11 setImages: React.Dispatch<React.SetStateAction<(string | null)[]>>;
12 isDragging: boolean;
13}
18 handleSubmit,
19 running,
20 images,
21 setImages,
22 isDragging
23}: ChatInputProps) {
43 const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
44 e.preventDefault();
45 const validImages = images.filter((img): img is string => typeof img === "string");
46 console.log("Submitting with images:", validImages);
47 if (input.trim() || validImages.length > 0) {
48 handleSubmit(e);
49 setImages([]);
50 }
51 };
52
53 const handleProcessFiles = (files: File[]) => {
54 processFiles(files, images, setImages);
55 };
56
61 disabled={running}
62 >
63 {images.length > 0 && (
64 <ImageUpload
65 images={images}
66 setImages={setImages}
67 processFiles={handleProcessFiles}
68 />
82 if (e.key === "Enter" && !e.shiftKey && !isMobile) {
83 e.preventDefault();
84 if (input.trim() || images.filter(Boolean).length > 0) {
85 handleFormSubmit(e as any);
86 }
103 }
104 }}
105 title="Attach images"
106 >
107 Attach images 📎
108 </button>
109 )}
118 }
119 }}
120 accept="image/*"
121 multiple
122 className="hidden"
157 <div className="bg-white p-6 rounded-lg shadow-lg text-center">
158 <div className="text-2xl mb-2">📁</div>
159 <div className="text-xl font-semibold">Drop images here</div>
160 </div>
161 </div>

MiniAppStarterindex.ts2 matches

@charmaineUpdated 1 month ago
2import { serveFile } from "https://esm.town/v/std/utils@64-main/index.ts";
3import { Hono } from "npm:hono";
4import { embedMetadata, handleFarcasterEndpoints, iconUrl, name, ogImageUrl } from "./farcaster.ts";
5
6const app = new Hono();
16 <meta name="fc:frame" content={JSON.stringify(embedMetadata(baseUrl))} />
17 <link rel="icon" href={iconUrl} />
18 <meta property="og:image" content={ogImageUrl} />
19 </head>
20 <body class="bg-white text-black dark:bg-black dark:text-white">

MiniAppStarterfarcaster.ts4 matches

@charmaineUpdated 1 month ago
3export const name = "Mini App Starter";
4export const iconUrl = "https://imgur.com/TrJLlwp.png";
5export const ogImageUrl = "https://imgur.com/xKVOVUE.png";
6
7export function embedMetadata(baseUrl: string) {
8 return {
9 version: "next",
10 imageUrl: ogImageUrl,
11 button: {
12 title: name,
15 name: name,
16 url: baseUrl,
17 splashImageUrl: iconUrl,
18 splashBackgroundColor: "#111111",
19 },
44 "iconUrl": iconUrl,
45 "homeUrl": baseUrl,
46 "splashImageUrl": iconUrl,
47 "splashBackgroundColor": "#111111",
48 "webhookUrl": baseUrl + "/webhook",

hn_notifierindex.html1 match

@charmaineUpdated 1 month ago
16 href="/public/favicon.svg"
17 sizes="any"
18 type="image/svg+xml"
19 />
20 <style>
ditherPng

ditherPngmain.tsx16 matches

@maxmUpdated 1 month ago
1import { createCanvas, loadImage } from "https://deno.land/x/canvas/mod.ts";
2import { Color, getPixels, Image, quantizeByMedianCut } from "https://esm.town/v/maxm/monke/mod.ts";
3
4const methods = [
10];
11
12async function getImage(url: string) {
13 const data = await fetch(url).then((e) => e.arrayBuffer()).then((e) => new Uint8Array(e));
14 const image = await loadImage(data);
15
16 const canvas = createCanvas(image.width(), image.height());
17
18 const ctx = canvas.getContext("2d");
19
20 ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
21 const d = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
22 return new Image(d, canvas.width, canvas.height);
23}
24
38 // ctx.fillStyle = "red";
39 // ctx.fillRect(10, 10, 200 - 20, 200 - 20);
40 // const d = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
41 const image = await getImage(
42 imgUrl,
43 );
44 image.dither(["#000000", "#ffffff"].map((e) => new Color(e)), {
45 method: methods.find((e) => e === url.searchParams.get("method")) || methods[0],
46 });
47 const i = createCanvas(image.width, image.height);
48
49 const ctx2 = i.getContext("2d");
50
51 const data = image.toImageData();
52
53 ctx2.putImageData(data, 0, 0);
54 return new Response(i.toBuffer("image/png"), {
55 headers: {
56 "Content-Type": "image/png",
57 },
58 });

monkehistogram.ts1 match

@maxmUpdated 1 month ago
3/**
4 * Histogram of colors with reduced space
5 * Effectively quantizes the image into 32768 colors
6 */
7export class ColorHistogram {

monkebox.ts39 matches

@maxmUpdated 1 month ago
2
3/** Box blur with r = 3 */
4export function boxBlur(image: { pixels: Color[]; width: number }) {
5 let i = 0;
6 // pixels is an array of pixels with r, g, b values
7 // width is the width of the image in pixels
8 while (i < (image.pixels.length)) {
9 const sumNeighbours = [0, 0, 0];
10 let numAdded = 0;
11
12 if (i > image.width + 1) {
13 // 1
14 sumNeighbours[0] += image.pixels[i - image.width - 1].r;
15 sumNeighbours[1] += image.pixels[i - image.width - 1].g;
16 sumNeighbours[2] += image.pixels[i - image.width - 1].b;
17 numAdded += 1;
18 }
19 if (i > image.width) {
20 // 2
21 sumNeighbours[0] += image.pixels[i - image.width].r;
22 sumNeighbours[1] += image.pixels[i - image.width].g;
23 sumNeighbours[2] += image.pixels[i - image.width].b;
24
25 // 3
26 sumNeighbours[0] += image.pixels[i - image.width + 1].r;
27 sumNeighbours[1] += image.pixels[i - image.width + 1].g;
28 sumNeighbours[2] += image.pixels[i - image.width + 1].b;
29 numAdded += 2;
30 }
31
32 if (i % image.width > 0) {
33 // 4
34 sumNeighbours[0] += image.pixels[i - 1].r;
35 sumNeighbours[1] += image.pixels[i - 1].g;
36 sumNeighbours[2] += image.pixels[i - 1].b;
37 numAdded += 1;
38 }
39 // 5
40 sumNeighbours[0] += image.pixels[i].r;
41 sumNeighbours[1] += image.pixels[i].g;
42 sumNeighbours[2] += image.pixels[i].b;
43 numAdded += 1;
44
45 if ((i % image.width) - image.width < -1) {
46 // 6
47 sumNeighbours[0] += image.pixels[i + 1].r;
48 sumNeighbours[1] += image.pixels[i + 1].g;
49 sumNeighbours[2] += image.pixels[i + 1].b;
50 numAdded += 1;
51 }
52
53 if (image.pixels.length - i > image.width) {
54 // 7
55 sumNeighbours[0] += image.pixels[i + image.width].r;
56 sumNeighbours[1] += image.pixels[i + image.width].g;
57 sumNeighbours[2] += image.pixels[i + image.width].b;
58
59 // 8
60 sumNeighbours[0] += image.pixels[i + image.width - 1].r;
61 sumNeighbours[1] += image.pixels[i + image.width - 1].g;
62 sumNeighbours[2] += image.pixels[i + image.width - 1].b;
63 numAdded += 2;
64
65 if (image.pixels.length - i > image.width + 1) {
66 // 9
67 sumNeighbours[0] += image.pixels[i + image.width + 1].r;
68 sumNeighbours[1] += image.pixels[i + image.width + 1].g;
69 sumNeighbours[2] += image.pixels[i + image.width + 1].b;
70 numAdded += 1;
71 }
72 }
73
74 image.pixels[i].r = Math.trunc(sumNeighbours[0] / numAdded);
75 image.pixels[i].g = Math.trunc(sumNeighbours[1] / numAdded);
76 image.pixels[i].b = Math.trunc(sumNeighbours[2] / numAdded);
77 i += 1;
78 }

monkesierra.ts4 matches

@maxmUpdated 1 month ago
3
4/**
5 * Dither the image into a smaller palette
6 * Uses two-row Sierra matrix
7 */
13 let i = 0;
14 // pixels is an array of pixels with r, g, b values
15 // width is the width of the image in pixels
16 while (i < (pixels.length)) {
17 const newC = findClosestColor(pixels[i], palette);
64
65/**
66 * Dither the image into a smaller palette
67 * Uses Sierra lite matrix
68 * Use twoRowSierraDither for more accuracy
75 let i = pixels.length - 1;
76 // pixels is an array of pixels with r, g, b values
77 // width is the width of the image in pixels
78 while (i >= 0) {
79 const newC = findClosestColor(pixels[i], palette);

brainrot_image_gen1 file match

@dcm31Updated 2 days ago
Generate images for Italian Brainrot characters using FAL AI

modifyImage2 file matches

@stevekrouseUpdated 2 days ago