23```
2425## Images
2627To send an image to ChatGPT, the easiest way is by converting it to a
28data URL, which is easiest to do with [@stevekrouse/fileToDataURL](https://www.val.town/v/stevekrouse/fileToDataURL).
2930```ts title="Image Example" val
31import { fileToDataURL } from "https://esm.town/v/stevekrouse/fileToDataURL";
3244role: "user",
45content: [{
46type: "image_url",
47image_url: {
48url: dataURL,
49},
cerebras_codermain.tsx1 match
1165<meta property="og:description" content="Turn your ideas into fully functional apps in less than a second – powered by Llama3.3-70b on Cerebras's super-fast wafer chips. Code is 100% open-source, hosted on Val Town."">
1166<meta property="og:type" content="website">
1167<meta property="og:image" content="https://stevekrouse-blob_admin.web.val.run/api/public/CerebrasCoderOG.jpg">
1168
1169
tldc_discordmain.tsx3 matches
16};
1718type ImageData = {
19type: "image";
20text: string;
21name?: string | undefined;
48};
4950export type Data = BooleanData | TextData | ImageData | SpeechData | WebsiteData | FileData;
5152type DataComponentRequestBody = {
cerebras_codermain.tsx1 match
1165<meta property="og:description" content="Turn your ideas into fully functional apps in less than a second – powered by Llama3.3-70b on Cerebras's super-fast wafer chips. Code is 100% open-source, hosted on Val Town."">
1166<meta property="og:type" content="website">
1167<meta property="og:image" content="https://stevekrouse-blob_admin.web.val.run/api/public/CerebrasCoderOG.jpg">
1168
1169
cerebras_codermain.tsx1 match
1165<meta property="og:description" content="Turn your ideas into fully functional apps in less than a second – powered by Llama3.3-70b on Cerebras's super-fast wafer chips. Code is 100% open-source, hosted on Val Town."">
1166<meta property="og:type" content="website">
1167<meta property="og:image" content="https://stevekrouse-blob_admin.web.val.run/api/public/CerebrasCoderOG.jpg">
1168
1169
flowingBeigePigeonmain.tsx31 matches
3import { createRoot } from "https://esm.sh/react-dom@18.2.0/client";
45// Comprehensive type for wildlife image analysis
6type ImageAnalysisResult = {
7// Identification Details
8animalType?: string;
4142function WildlifeRescueApp() {
43const [image, setImage] = useState<string | null>(null);
44const [location, setLocation] = useState<{
45lat: number;
50} | null>(null);
51const [locationError, setLocationError] = useState<string | null>(null);
52const [imageAnalysis, setImageAnalysis] = useState<ImageAnalysisResult | null>(null);
53const [editableAnalysis, setEditableAnalysis] = useState<ImageAnalysisResult | null>(null);
54const [isAnalyzing, setIsAnalyzing] = useState(false);
55const [uploadError, setUploadError] = useState<string | null>(null);
6869// Comprehensive AI analysis method
70const analyzeImage = useCallback(async (imageDataUrl: string) => {
71setIsAnalyzing(true);
72try {
110},
111{
112type: "image_url",
113image_url: { url: imageDataUrl }
114}
115],
119});
120121const analysisText = response.choices[0].message.content || "Unable to analyze image";
122
123// Comprehensive parsing of analysis
124const analysis: ImageAnalysisResult = {
125// Identification Details
126animalType: extractDetail(analysisText, ['animal species', 'species']),
167},
168{
169type: "image_url",
170image_url: { url: imageDataUrl }
171}
172],
178analysis.narrativeDescription = narrativeResponse.choices[0].message.content || "Unable to generate narrative";
179180setImageAnalysis(analysis);
181setEditableAnalysis({...analysis});
182setUploadError(null);
187recommendedAction: "Urgent professional wildlife rescue consultation required"
188};
189setImageAnalysis(fallbackAnalysis);
190setEditableAnalysis(fallbackAnalysis);
191setUploadError("Failed to analyze the image. Please try again.");
192} finally {
193setIsAnalyzing(false);
196197// Severity determination remains the same
198const determineSeverityLevel = (analysisText: string): ImageAnalysisResult['severityLevel'] => {
199const lowRiskKeywords = ['minor', 'slight', 'small'];
200const criticalRiskKeywords = ['critical', 'severe', 'urgent', 'emergency'];
206};
207208// Enhanced image upload handler with file validation
209const handleImageUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
210const file = event.target.files?.[0];
211if (file) {
212// Validate file type
213const validImageTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
214if (!validImageTypes.includes(file.type)) {
215setUploadError('Please upload a valid image file (JPEG, PNG, GIF, or WebP)');
216return;
217}
220const maxSizeInBytes = 10 * 1024 * 1024; // 10MB
221if (file.size > maxSizeInBytes) {
222setUploadError('Image file is too large. Please upload an image under 10MB.');
223return;
224}
226const reader = new FileReader();
227reader.onloadend = async () => {
228const imageDataUrl = reader.result as string;
229setImage(imageDataUrl);
230await analyzeImage(imageDataUrl);
231};
232reader.readAsDataURL(file);
235236// Handle editable field changes
237const handleAnalysisChange = (field: keyof ImageAnalysisResult, value: any) => {
238if (editableAnalysis) {
239setEditableAnalysis({
265<input
266type="file"
267accept="image/*"
268onChange={handleImageUpload}
269ref={fileInputRef}
270style={{ display: 'none' }}
280}}
281>
282Upload Wildlife Image
283</button>
284</div>
296)}
297298{image && editableAnalysis && (
299<div>
300<img
301src={image}
302alt="Uploaded wildlife"
303style={{ maxWidth: '300px', margin: '10px 0' }}
wildlifeRescueAppmain.tsx13 matches
45function WildlifeRescueApp() {
6const [image, setImage] = useState<{ file: File | null, preview: string }>({ file: null, preview: '' });
7const [location, setLocation] = useState<{ lat: number; lng: number }>({ lat: 0, lng: 0 });
8const [animalType, setAnimalType] = useState<string>('');
1213const resetForm = useCallback(() => {
14setImage({ file: null, preview: '' });
15setAnimalType('');
16setInjuryDescription('');
22}, []);
2324const handleImageUpload = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
25const file = e.target.files?.[0];
26if (file) {
31}
3233const validTypes = ['image/jpeg', 'image/png', 'image/gif'];
34if (!validTypes.includes(file.type)) {
35setSubmitStatus('Invalid file type. Please upload JPEG, PNG, or GIF.');
39const reader = new FileReader();
40reader.onloadend = () => {
41setImage({
42file,
43preview: reader.result as string
81try {
82// Input validation
83if (!image.file) {
84throw new Error('Please upload a wildlife image');
85}
86if (!animalType?.trim()) {
96injuryDescription,
97location,
98imagePreview: image.preview
99});
100125<div style={{ marginBottom: '15px' }}>
126<label style={{ display: 'block', marginBottom: '5px' }}>
127Upload Wildlife Image:
128<input
129ref={fileInputRef}
130type="file"
131accept="image/jpeg,image/png,image/gif"
132onChange={handleImageUpload}
133required
134style={{ width: '100%', padding: '10px', backgroundColor: 'white' }}
135/>
136</label>
137{image.preview && (
138<img
139src={image.preview}
140alt="Uploaded wildlife"
141style={{
blob_adminREADME.md1 match
3This is a lightweight Blob Admin interface to view and debug your Blob data.
45
67Versions 0-17 of this val were done with Hono and server-rendering.
blob_adminmain.tsx5 matches
440{profile && (
441<div className="flex items-center space-x-4">
442<img src={profile.profileImageUrl} alt="Profile" className="w-8 h-8 rounded-full" />
443<span>{profile.username}</span>
444<a href="/auth/logout" className="text-blue-400 hover:text-blue-300">Logout</a>
583alt="Blob content"
584className="max-w-full h-auto"
585onError={() => console.error("Error loading image")}
586/>
587</div>
635<li>Create public shareable links for blobs</li>
636<li>View and manage public folder</li>
637<li>Preview images directly in the interface</li>
638</ul>
639</div>
694const { ValTown } = await import("npm:@valtown/sdk");
695const vt = new ValTown();
696const { email: authorEmail, profileImageUrl, username } = await vt.me.profile.retrieve();
697// const authorEmail = me.email;
698762763c.set("email", email);
764c.set("profile", { profileImageUrl, username });
765await next();
766};
cerebras_codermain.tsx1 match
1165<meta property="og:description" content="Turn your ideas into fully functional apps in less than a second – powered by Llama3.3-70b on Cerebras's super-fast wafer chips. Code is 100% open-source, hosted on Val Town."">
1166<meta property="og:type" content="website">
1167<meta property="og:image" content="https://stevekrouse-blob_admin.web.val.run/api/public/CerebrasCoderOG.jpg">
1168
1169