101Your description should include:
102- What content is on the page
103- Other elements like sidebars, links, images that may be in the page
104- The author and origin of the page
105- The stylistic aesthetic of the page
145- A footer with author information.
146- Some reasonable links in the body text.
147- An image. You can create an image by using the following markup:
148<img src="https://maxm-imggenurl.web.val.run/{your image alt text}" height={image height} />
149- Specific, concrete information only. NEVER use placeholders or other generic text.
150`,
jamesWebbImageProxymain.tsx1 match
1export default async function(req: Request) {
2const body = (await fetch("https://live.staticflickr.com/65535/53782948438_9b85e57a6c_o_d.png")).body
3return new Response(body, {headers: {"Content-Type": "image/png"}});
4}
6<p align=center>
7<a href="https://maxm-valtownchatgpt.web.val.run/">
8<img width=600 src="https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/c180aba1-997a-4e40-615a-1ed8456b5a00/public">
9</a>
10</p>
16"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" ",
17),
18{ headers: { "Content-Type": "image/svg+xml" } },
19);
20}
asciiNycCamerasmain.tsx11 matches
34import valTownBadge from "https://esm.town/v/jxnblk/valTownBadge?v=16";
5import { imageToAscii } from "https://esm.town/v/maxm/imageToAscii";
6import { extractValInfo } from "https://esm.town/v/pomdtr/extractValInfo";
7import { Hono } from "npm:hono@3";
35document.getElementById("message").style.display = "none";
36document.getElementById("close-btn").style.display = "flex";
37await fetchImage(id);
38};
39152<p>
153Click on a circle to select a traffic camera. <br />{" "}
154The traffic images will be converted to ASCII and streamed to your browser.
155<br /> <a className="underline" href={info.htmlUrl}>Source code & info</a>.
156</p>
196);
197app.get("/camera-ascii/:id", async (c) => {
198const url = "https://webcams.nyctmc.org/api/cameras/" + c.req.param("id") + "/image";
199const { stringColor } = await imageToAscii(url, 150);
200return new Response(stringColor, { headers: { "Content-Type": "text/plain" } });
201});
203"/camera/:id",
204async (c) => {
205const url = "https://webcams.nyctmc.org/api/cameras/" + c.req.param("id") + "/image";
206const { string, stringColor } = await imageToAscii(url, 150);
207return new Response(
208`<style>
228<p class="loading"></p>
229<p>
230<a target="_blank" href="${url}">view source image</a>
231</p>
232<script>
258app.get("/camera-text-stream/:id", async (c) => {
259let timerId: number | undefined;
260const url = "https://webcams.nyctmc.org/api/cameras/" + c.req.param("id") + "/image";
261const body = new ReadableStream({
262async start(controller) {
264controller.enqueue(new TextEncoder().encode("data: " + JSON.stringify(msg) + "\r\n\r\n"));
265};
266const { stringColor } = await imageToAscii(url, 150);
267write(stringColor);
268timerId = setInterval(async () => {
269const { stringColor } = await imageToAscii(url, 150);
270write(stringColor);
271}, 2000);
asciiImageExamplemain.tsx3 matches
1import { imageToAscii } from "https://esm.town/v/maxm/imageToAscii";
23export default async function(req: Request): Promise<Response> {
4const { string, stringColor } = await imageToAscii(
5"https://webcams.nyctmc.org/api/cameras/9fa5b0dd-e955-449e-97e1-9c53ad9c23a8/image",
6150,
7);
imageToAsciimain.tsx11 matches
2526// Converted from: https://github.com/victorqribeiro/imgToAscii/blob/ca7e181b9bb9770798ed3a0d3dfeb344c60953f2/src/imgToAscii.js
27import { createCanvas, loadImage } from "https://deno.land/x/canvas@v1.4.1/mod.ts";
28export async function imageToAscii(src: string, maxWidth?: number) {
29let string = "";
30let stringColor = "";
38"`","'","."," "]
39}
40const image = await loadImage(src);
41let width = image.width();
42const scale = maxWidth ? maxWidth / width : 1;
43const height = Math.floor(image.height() * scale * 0.6);
44width = Math.floor(width * scale);
45const canvas = createCanvas(width, height);
46const context = canvas.getContext("2d");
47context.drawImage(image, 0, 0, canvas.width, canvas.height);
48const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
49let grayStep = Math.ceil(255 / alphabet[charType].length);
50for (let i = 0; i < imageData.data.length; i += 4) {
51for (let j = 0; j < alphabet[charType].length; j++) {
52let r = imageData.data[i];
53let g = imageData.data[i + 1];
54let b = imageData.data[i + 2];
55if ((r * 0.2126) + (g * 0.7152) + (b * 0.0722) < (j + 1) * grayStep) {
56const char = alphabet[charType][j];
asciiNycCamerasREADME.md3 matches
1# ASCII NYC Traffic Cameras
23All of NYC's traffic cameras available as streaming ASCII images: https://maxm-asciinyccameras.web.val.run/
45<p align=center>
6<a href="https://maxm-asciinyccameras.web.val.run/">
7<!-- <img width=700 src="https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/9c4e7e22-ae90-420e-4238-df0013d2a300/public"> -->
8<img width=700 src="https://i.imgur.com/83LBOcN.gif">
9</a>
121314NYC has a bunch of traffic cameras and makes them available through static images [like this one](https://webcams.nyctmc.org/api/cameras/858ef4e8-5058-4db2-96e2-70f71b65aa24/image). If you refresh the page you'll see the image update every 2 seconds or so. I thought it might be fun to make these cameras viewable as an ASCII art video feed. I made a [small library](https://www.val.town/v/maxm/imageToAscii) that takes most of its logic from [this repo](https://github.com/victorqribeiro/imgToAscii). You can see a basic example of how to convert [any image to ASCII here](https://www.val.town/v/maxm/asciiImageExample).
1516I pull in [NYC GeoJSON from here](https://observablehq.com/@miaozhang/maps) and then hook up a Server-Sent Events endpoint to stream the ASCII updates to the browser. (Polling would work just as well, I've just been on a bit of a SSE kick lately.)
asciiImageExampleREADME.md1 match
1null
23Migrated from folder: asciiNyc/asciiImageExample
endlessMazeStreamREADME.md1 match
12
3