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=317&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 12761 results for "image"(3928ms)

pbackApp.tsx101 matches

@Gj64•Updated 3 months ago
10 lineHeight: number;
11 textAlign: 'left' | 'center' | 'right';
12 uploadedImage: HTMLImageElement | null;
13 imageUrl: string;
14 imagePosition: 'fit' | 'fill' | 'stretch' | 'tile';
15 imageBrightness: number;
16 imageContrast: number;
17 imageSaturation: number;
18 imageRotation: number;
19 imageFlipX: boolean;
20 imageFlipY: boolean;
21 imageBlur: number;
22 shadowEnabled: boolean;
23 shadowColor: string;
103 lineHeight: 1.2,
104 textAlign: 'center',
105 uploadedImage: null,
106 imageUrl: '',
107 imagePosition: 'fill',
108 imageBrightness: 100,
109 imageContrast: 100,
110 imageSaturation: 100,
111 imageRotation: 0,
112 imageFlipX: false,
113 imageFlipY: false,
114 imageBlur: 0,
115 shadowEnabled: false,
116 shadowColor: '#000000',
133 });
134
135 const [activeTab, setActiveTab] = useState<'text' | 'image' | 'effects' | 'export'>('text');
136 const [history, setHistory] = useState<HistoryState[]>([]);
137 const [historyIndex, setHistoryIndex] = useState(-1);
206 }
207
208 if (!state.uploadedImage && !state.gradientEnabled) return;
209
210 // Save context
268 });
269
270 // Apply image or gradient texture
271 ctx.globalCompositeOperation = state.blendMode as GlobalCompositeOperation;
272 ctx.globalAlpha = state.opacity / 100;
295 ctx.fillStyle = gradient;
296 ctx.fillRect(0, 0, canvas.width, canvas.height);
297 } else if (state.uploadedImage) {
298 // Apply image filters
299 ctx.filter = `brightness(${state.imageBrightness}%) contrast(${state.imageContrast}%) saturate(${state.imageSaturation}%) blur(${state.imageBlur}px)`;
300
301 // Calculate image dimensions and position
302 let { width: imgWidth, height: imgHeight } = state.uploadedImage;
303 let drawX = 0, drawY = 0, drawWidth = imgWidth, drawHeight = imgHeight;
304
307 ctx.translate(canvas.width / 2, canvas.height / 2);
308
309 if (state.imageRotation !== 0) {
310 ctx.rotate((state.imageRotation * Math.PI) / 180);
311 }
312
313 const scaleX = state.imageFlipX ? -1 : 1;
314 const scaleY = state.imageFlipY ? -1 : 1;
315 ctx.scale(scaleX, scaleY);
316
317 // Handle different image positioning modes
318 switch (state.imagePosition) {
319 case 'fit':
320 const fitScale = Math.min(canvas.width / imgWidth, canvas.height / imgHeight);
339 case 'tile':
340 // Create pattern for tiling
341 const pattern = ctx.createPattern(state.uploadedImage, 'repeat');
342 if (pattern) {
343 ctx.fillStyle = pattern;
349 }
350
351 ctx.drawImage(state.uploadedImage, drawX, drawY, drawWidth, drawHeight);
352 ctx.restore();
353 }
364 }, [updateCanvas]);
365
366 const handleImageUpload = (file: File) => {
367 if (!file.type.startsWith('image/')) {
368 alert('Please upload a valid image file');
369 return;
370 }
373 const reader = new FileReader();
374 reader.onload = (e) => {
375 const img = new Image();
376 img.onload = () => {
377 const newState = {
378 ...state,
379 uploadedImage: img,
380 imageUrl: e.target?.result as string
381 };
382 setState(newState);
385 };
386 img.onerror = () => {
387 alert('Failed to load image');
388 setIsLoading(false);
389 };
396 const file = e.target.files?.[0];
397 if (file) {
398 handleImageUpload(file);
399 }
400 };
405 const file = e.dataTransfer.files[0];
406 if (file) {
407 handleImageUpload(file);
408 }
409 };
425 };
426
427 const downloadImage = (format: 'png' | 'jpg' | 'svg' = 'png', scale: number = 1) => {
428 const canvas = canvasRef.current;
429 if (!canvas) return;
446 if (ctx) {
447 ctx.scale(scale, scale);
448 ctx.drawImage(canvas, 0, 0);
449 }
450 }
451
452 const link = document.createElement('a');
453 link.download = `image-text-studio.${format}`;
454 link.href = downloadCanvas.toDataURL(format === 'jpg' ? 'image/jpeg' : 'image/png', 0.9);
455 link.click();
456 };
457
458 const resetImage = () => {
459 const newState = {
460 ...state,
461 uploadedImage: null,
462 imageUrl: ''
463 };
464 setState(newState);
492 <div>
493 <h1 className="text-xl font-semibold">Text Studio</h1>
494 <p className="text-sm text-white/60">Professional Image Typography</p>
495 </div>
496 </div>
514 </button>
515 <button
516 onClick={() => downloadImage('png', 2)}
517 className="btn-primary"
518 disabled={!state.uploadedImage && !state.gradientEnabled}
519 >
520 Export
531 {/* Tab Navigation */}
532 <div className="tab-list">
533 {(['text', 'image', 'effects', 'export'] as const).map((tab) => (
534 <button
535 key={tab}
646 )}
647
648 {/* Image Controls */}
649 {activeTab === 'image' && (
650 <div className="tool-panel animate-fade-in">
651 <div className="tool-section">
652 <h3 className="text-lg font-semibold mb-4">Image Upload</h3>
653 {!state.uploadedImage ? (
654 <div
655 className={`upload-area p-8 text-center cursor-pointer ${
662 >
663 <div className="text-4xl mb-4">📸</div>
664 <p className="text-lg mb-2">Drop image or click to browse</p>
665 <p className="text-sm text-white/60">
666 PNG, JPG, GIF, WebP, SVG
669 ref={fileInputRef}
670 type="file"
671 accept="image/*"
672 onChange={handleFileSelect}
673 className="hidden"
678 <div className="relative">
679 <img
680 src={state.imageUrl}
681 alt="Uploaded"
682 className="w-full h-32 object-cover rounded-lg"
683 />
684 <button
685 onClick={resetImage}
686 className="absolute top-2 right-2 bg-red-500 hover:bg-red-600 text-white rounded-full w-8 h-8 flex items-center justify-center transition-colors"
687 >
693 className="btn-secondary w-full"
694 >
695 Change Image
696 </button>
697 <input
698 ref={fileInputRef}
699 type="file"
700 accept="image/*"
701 onChange={handleFileSelect}
702 className="hidden"
706 </div>
707
708 {state.uploadedImage && (
709 <>
710 <div className="tool-section">
714 <label className="block text-sm font-medium mb-2">Position Mode</label>
715 <select
716 value={state.imagePosition}
717 onChange={(e) => updateState({ imagePosition: e.target.value as any })}
718 className="form-control"
719 >
727 <div>
728 <label className="block text-sm font-medium mb-2">
729 Rotation: {state.imageRotation}°
730 </label>
731 <input
733 min="0"
734 max="360"
735 value={state.imageRotation}
736 onChange={(e) => updateState({ imageRotation: parseInt(e.target.value) })}
737 className="range-slider"
738 />
743 <input
744 type="checkbox"
745 checked={state.imageFlipX}
746 onChange={(e) => updateState({ imageFlipX: e.target.checked })}
747 className="rounded"
748 />
752 <input
753 type="checkbox"
754 checked={state.imageFlipY}
755 onChange={(e) => updateState({ imageFlipY: e.target.checked })}
756 className="rounded"
757 />
763
764 <div className="tool-section">
765 <h3 className="text-lg font-semibold mb-4">Image Adjustments</h3>
766 <div className="space-y-4">
767 <div>
768 <label className="block text-sm font-medium mb-2">
769 Brightness: {state.imageBrightness}%
770 </label>
771 <input
773 min="0"
774 max="200"
775 value={state.imageBrightness}
776 onChange={(e) => updateState({ imageBrightness: parseInt(e.target.value) })}
777 className="range-slider"
778 />
781 <div>
782 <label className="block text-sm font-medium mb-2">
783 Contrast: {state.imageContrast}%
784 </label>
785 <input
787 min="0"
788 max="200"
789 value={state.imageContrast}
790 onChange={(e) => updateState({ imageContrast: parseInt(e.target.value) })}
791 className="range-slider"
792 />
795 <div>
796 <label className="block text-sm font-medium mb-2">
797 Saturation: {state.imageSaturation}%
798 </label>
799 <input
801 min="0"
802 max="200"
803 value={state.imageSaturation}
804 onChange={(e) => updateState({ imageSaturation: parseInt(e.target.value) })}
805 className="range-slider"
806 />
809 <div>
810 <label className="block text-sm font-medium mb-2">
811 Blur: {state.imageBlur}px
812 </label>
813 <input
815 min="0"
816 max="20"
817 value={state.imageBlur}
818 onChange={(e) => updateState({ imageBlur: parseInt(e.target.value) })}
819 className="range-slider"
820 />
1131 <div className="space-y-3">
1132 <button
1133 onClick={() => downloadImage('png', 1)}
1134 className="btn-primary w-full"
1135 disabled={!state.uploadedImage && !state.gradientEnabled}
1136 >
1137 Download PNG (1x)
1138 </button>
1139 <button
1140 onClick={() => downloadImage('png', 2)}
1141 className="btn-secondary w-full"
1142 disabled={!state.uploadedImage && !state.gradientEnabled}
1143 >
1144 Download PNG (2x)
1145 </button>
1146 <button
1147 onClick={() => downloadImage('png', 3)}
1148 className="btn-secondary w-full"
1149 disabled={!state.uploadedImage && !state.gradientEnabled}
1150 >
1151 Download PNG (3x)
1152 </button>
1153 <button
1154 onClick={() => downloadImage('jpg', 2)}
1155 className="btn-secondary w-full"
1156 disabled={!state.uploadedImage && !state.gradientEnabled}
1157 >
1158 Download JPG (2x)
1175 </div>
1176
1177 {!state.uploadedImage && !state.gradientEnabled ? (
1178 <div className="canvas-container rounded-lg p-12 text-center text-white/60 min-h-[500px] flex items-center justify-center">
1179 <div className="animate-pulse">
1180 <div className="text-6xl mb-4">🎨</div>
1181 <p className="text-xl mb-2">Upload an image or enable gradient</p>
1182 <p className="text-sm">to see your text come to life</p>
1183 </div>
1203 {/* Floating Action Button */}
1204 <button
1205 onClick={() => downloadImage('png', 2)}
1206 className="fab"
1207 disabled={!state.uploadedImage && !state.gradientEnabled}
1208 data-tooltip="Quick Export"
1209 >

pbackCanvasRenderer.tsx28 matches

@Gj64•Updated 3 months ago
39 }
40
41 if (!state.uploadedImage && !state.gradientEnabled) return;
42
43 // Save context
120 });
121
122 // Apply image or gradient texture
123 ctx.globalCompositeOperation = state.blendMode as GlobalCompositeOperation;
124 ctx.globalAlpha = state.opacity / 100;
139 ctx.fillStyle = gradient;
140 ctx.fillRect(0, 0, canvas.width, canvas.height);
141 } else if (state.uploadedImage) {
142 drawImageTexture(ctx, canvas, state);
143 }
144
342 };
343
344 const drawImageTexture = (ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement, state: AppState) => {
345 if (!state.uploadedImage) return;
346
347 // Apply image filters
348 const filterParts = [];
349 if (state.imageSettings.brightness !== 100) filterParts.push(`brightness(${state.imageSettings.brightness}%)`);
350 if (state.imageSettings.contrast !== 100) filterParts.push(`contrast(${state.imageSettings.contrast}%)`);
351 if (state.imageSettings.saturation !== 100) filterParts.push(`saturate(${state.imageSettings.saturation}%)`);
352 if (state.imageSettings.hue !== 0) filterParts.push(`hue-rotate(${state.imageSettings.hue}deg)`);
353 if (state.imageSettings.blur > 0) filterParts.push(`blur(${state.imageSettings.blur}px)`);
354
355 ctx.filter = filterParts.join(' ') || 'none';
356
357 // Calculate image dimensions and position
358 let { width: imgWidth, height: imgHeight } = state.uploadedImage;
359 let drawX = 0, drawY = 0, drawWidth = imgWidth, drawHeight = imgHeight;
360
363 ctx.translate(canvas.width / 2, canvas.height / 2);
364
365 if (state.imageSettings.rotation !== 0) {
366 ctx.rotate(degToRad(state.imageSettings.rotation));
367 }
368
369 const scaleX = state.imageSettings.flipX ? -1 : 1;
370 const scaleY = state.imageSettings.flipY ? -1 : 1;
371 ctx.scale(scaleX, scaleY);
372
373 // Handle different image positioning modes
374 switch (state.imageSettings.position) {
375 case 'fit':
376 const fitScale = Math.min(canvas.width / imgWidth, canvas.height / imgHeight);
395 case 'tile':
396 // Create pattern for tiling
397 const pattern = ctx.createPattern(state.uploadedImage, 'repeat');
398 if (pattern) {
399 ctx.fillStyle = pattern;
404 case 'custom':
405 // Apply cropping
406 const cropX = (state.imageSettings.cropX / 100) * imgWidth;
407 const cropY = (state.imageSettings.cropY / 100) * imgHeight;
408 const cropWidth = (state.imageSettings.cropWidth / 100) * imgWidth;
409 const cropHeight = (state.imageSettings.cropHeight / 100) * imgHeight;
410
411 ctx.drawImage(
412 state.uploadedImage,
413 cropX, cropY, cropWidth, cropHeight,
414 -canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height
418 }
419
420 ctx.drawImage(state.uploadedImage, drawX, drawY, drawWidth, drawHeight);
421 ctx.restore();
422 };

pbackutils.ts6 matches

@Gj64•Updated 3 months ago
237}
238
239export function applyImageFilters(
240 canvas: HTMLCanvasElement,
241 filters: Record<string, number>
324
325// File utilities
326export function validateImageFile(file: File): { valid: boolean; error?: string } {
327 const maxSize = 50 * 1024 * 1024; // 50MB
328 const supportedTypes = [
329 'image/png', 'image/jpeg', 'image/jpg', 'image/gif',
330 'image/webp', 'image/svg+xml', 'image/avif'
331 ];
332
342}
343
344export function compressImage(
345 canvas: HTMLCanvasElement,
346 quality: number = 0.8,
364 const ctx = compressedCanvas.getContext('2d');
365 if (ctx) {
366 ctx.drawImage(canvas, 0, 0, newWidth, newHeight);
367 }
368

pbackconstants.ts11 matches

@Gj64•Updated 3 months ago
166 { key: 'o', ctrlKey: true, action: 'open', description: 'Open project' },
167 { key: 'n', ctrlKey: true, action: 'new', description: 'New project' },
168 { key: 'e', ctrlKey: true, action: 'export', description: 'Export image' },
169 { key: 'd', ctrlKey: true, action: 'duplicate', description: 'Duplicate layer' },
170 { key: 'g', ctrlKey: true, action: 'group', description: 'Group layers' },
219];
220
221export const SUPPORTED_IMAGE_FORMATS = [
222 'image/png',
223 'image/jpeg',
224 'image/jpg',
225 'image/gif',
226 'image/webp',
227 'image/svg+xml',
228 'image/avif',
229 'image/bmp',
230 'image/tiff'
231];
232

pbacktypes.ts5 matches

@Gj64•Updated 3 months ago
13}
14
15export interface ImageSettings {
16 url: string;
17 position: 'fit' | 'fill' | 'stretch' | 'tile' | 'custom';
94 id: string;
95 name: string;
96 type: 'text' | 'image' | 'shape' | 'effect';
97 visible: boolean;
98 locked: boolean;
153 textStyle: TextStyle;
154
155 // Image
156 uploadedImage: HTMLImageElement | null;
157 imageSettings: ImageSettings;
158
159 // Effects

stevensDemoREADME.md1 match

@jlau•Updated 3 months ago
3It's common to have code and types that are needed on both the frontend and the backend. It's important that you write this code in a particularly defensive way because it's limited by what both environments support:
4
5![shapes at 25-02-25 11.57.13.png](https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/75db1d51-d9b3-45e0-d178-25d886c10700/public)
6
7For example, you *cannot* use the `Deno` keyword. For imports, you can't use `npm:` specifiers, so we reccomend `https://esm.sh` because it works on the server & client. You *can* use TypeScript because that is transpiled in `/backend/index.ts` for the frontend. Most code that works on the frontend tends to work in Deno, because Deno is designed to support "web-standards", but there are definitely edge cases to look out for.

stevensDemoREADME.md1 match

@jlau•Updated 3 months ago
21## `favicon.svg`
22
23As of this writing Val Town only supports text files, which is why the favicon is an SVG and not an .ico or any other binary image format. If you need binary file storage, check out [Blob Storage](https://docs.val.town/std/blob/).
24
25## `components/`

stevensDemoindex.ts15 matches

@jlau•Updated 3 months ago
73});
74
75// --- Blob Image Serving Routes ---
76
77// GET /api/images/:filename - Serve images from blob storage
78app.get("/api/images/:filename", async (c) => {
79 const filename = c.req.param("filename");
80
81 try {
82 // Get image data from blob storage
83 const imageData = await blob.get(filename);
84
85 if (!imageData) {
86 return c.json({ error: "Image not found" }, 404);
87 }
88
90 let contentType = "application/octet-stream"; // Default
91 if (filename.endsWith(".jpg") || filename.endsWith(".jpeg")) {
92 contentType = "image/jpeg";
93 } else if (filename.endsWith(".png")) {
94 contentType = "image/png";
95 } else if (filename.endsWith(".gif")) {
96 contentType = "image/gif";
97 } else if (filename.endsWith(".svg")) {
98 contentType = "image/svg+xml";
99 }
100
101 // Return the image with appropriate headers
102 return new Response(imageData, {
103 headers: {
104 "Content-Type": contentType,
107 });
108 } catch (error) {
109 console.error(`Error serving image ${filename}:`, error);
110 return c.json(
111 { error: "Failed to load image", details: error.message },
112 500,
113 );

stevensDemoindex.html3 matches

@jlau•Updated 3 months ago
10 href="/public/favicon.svg"
11 sizes="any"
12 type="image/svg+xml"
13 />
14 <link rel="preconnect" href="https://fonts.googleapis.com" />
36 height: 100%;
37 font-family: "Pixelify Sans", sans-serif;
38 image-rendering: pixelated;
39 }
40 body::before {
50 /* For pixel art aesthetic */
51 * {
52 image-rendering: pixelated;
53 }
54 </style>

stevensDemohandleUSPSEmail.ts12 matches

@jlau•Updated 3 months ago
12}
13
14type ImageSummary = {
15 sender: string;
16 recipient: (typeof RECIPIENTS)[number] | "both" | "other";
22 anthropic: Anthropic,
23 htmlContent: string,
24 imageSummaries: ImageSummary[]
25) {
26 try {
36 text: `Analyze the following content from an email and provide a response as a JSON blob (only JSON, no other text) with two parts.
37
38 The email is from the USPS showing mail I'm receiving. Metadata about packages is stored directly in the email. Info about mail pieces is in images, so I've included summaries of those as well.
39
40 Your response should include:
66 And here is info about the mail pieces:
67
68 ${JSON.stringify(imageSummaries)}`,
69 },
70 ],
95 const anthropic = new Anthropic({ apiKey });
96
97 // Process each image attachment serially
98 const summaries = [];
99 for (const [index, attachment] of e.attachments.entries()) {
100 try {
101 const imageData = await attachment.arrayBuffer();
102 const base64Image = btoa(
103 String.fromCharCode(...new Uint8Array(imageData))
104 );
105
112 content: [
113 {
114 type: "image",
115 source: {
116 type: "base64",
117 media_type: attachment.type,
118 data: base64Image,
119 },
120 },
148 summaries.push(parsedResponse);
149 } catch (error) {
150 console.error(`Image analysis error:`, error);
151 summaries.push({
152 sender: "Error",
153 recipient: "Error",
154 type: "error",
155 notes: `Image ${index + 1} Analysis Failed: ${error.message}`,
156 });
157 }
Gemini-2-5-Pro-O-01

Gemini-2-5-Pro-O-011 file match

@aibotcommander•Updated 22 mins ago
Multimodal Image Generator: https://poe.com/Gemini-2.5-Pro-Omni

ImageThing

@refactorized•Updated 2 days ago
Chrimage
Atiq
"Focal Lens with Atig Wazir" "Welcome to my photography journey! I'm Atiq Wazir, a passionate photographer capturing life's beauty one frame at a time. Explore my gallery for stunning images, behind-the-scenes stories, and tips & tricks to enhance your own