#Get image from automated download

1 messages · Page 1 of 1 (latest)

sharp minnow
#

I have this page which displays a render using threejs and renders it into a png and downloads it. i need that image to use it in a canvas from deno-canvas but when i download it using this package it returns this:

error: Uncaught (in promise) Error: The filename, directory name, or volume label syntax is incorrect. (os error 123): writefile 'C:\Users\titul\AppData\Local\Temp\deno_dwld2b5d29e3bc7dd136/E:\Arcunis\recipeImageMaker\stone.png'

code where i download it:|

import { download } from "https://deno.land/x/[email protected]/mod.ts";
import { join } from "https://deno.land/std/path/mod.ts";
export default async function generateBlock(block: String) {
    await download("http://localhost:8000/renderer/index.html?material=" + block, {file: join(Deno.cwd(), block + ".png")});
}
somber wadi
#

Looking at the docs of the download library the file parameter is there to set the filename only. You're passing a full absolute path into that. Under the hood the library seem to only append the file parameter to their own internal path leading to the broken file path you're seeing in the error message.

You might have better luck just using builtin APIs to download a file:

async function download(url: string, filePath: string) {
  const res = await fetch(url);
  const file = await Deno.open(filePath, {
    create: true,
    write: true
  })

  await res.body?.pipeTo(file.writable);
}

// Usage
await download("https://example.com/my-file.txt", path.join(Deno.cwd(), "save-to-disk.txt"))
sharp minnow
#

this still gives an error

error: Uncaught (in promise) BadResource: Bad resource ID
    file.close();
         ^
    at FsFile.close (ext:deno_fs/30_fs.js:738:10)
    at download (file:///E:/Arcunis/recipeImageMaker/src/generateBlock.ts:11:10)
    at eventLoopTick (ext:core/01_core.js:153:7)
    at async generateBlock (file:///E:/Arcunis/recipeImageMaker/src/generateBlock.ts:16:5)

new file:

import { join } from "https://deno.land/[email protected]/path/mod.ts";

async function download(url: string, filePath: string) {
    const res = await fetch(url);
    const file = await Deno.open(filePath, {
        create: true,
        write: true
    })
  
    await res.body?.pipeTo(file.writable);
    file.close();
}

export default async function generateBlock(block: String) {
    
    await download("http://localhost:8000/renderer/index.html?material=" + block, join(Deno.cwd(), block + ".png"));

}

generateBlock("stone"); // Temporary function call for testing
#

it does look like progress tho

somber wadi
#

@sharp minnow ah apologies, the file.close() should be removed

#

Deleted it from my code snippet. Not sure why I added that, my brain blanked probably

sharp minnow
#

that worked. only the image is not valid. the stone-valid.png is downloaded by me just going to the url and the stone-invalid.png is downloaded by the code. the file sizes do not match and the invalid one does not load in any image editor/viewer

spring dove
#

marvinh’s code works for me. Are you sure the file being served is the same?

sharp minnow
#

its not exactly being served. its generated. first threejs generates a cube and loads a texture from a material from the url parameters. then it generates an image and downloads it

somber wadi
#

sounds like something is wrong with how the image is generated

sharp minnow
#

could be but if i just go to the page myself it works fine

spring dove
#

It seems like you’re actually downloading the page’s source instead of the image you want.

#

I’m not sure you can easily/seamlessly just have Deno save the file from the browser JavaScript code.

sharp minnow
#

ahh ye when i opened the file i do indeed see the html

spring dove
#

But note that you can just run that code on Deno itself if you use the right tools, instead of having it run on a browser.

#

I guess Three.js might not be possible, actually. 🤔

sharp minnow
#

yhea only i coudnt find a local kind of version of threejs or something like it

spring dove
#

If you just want an isometric image, you could create it without Three.js.

sharp minnow
#

how do you mean?

#

also this is an exaple output of the renderer just a 3D cube with a texture captured using an orthographic camera

sharp minnow
sharp minnow
#

@spring dove any idea if there is a package that can let me render things in the deno environment instead of using html? or something that can create images with the possibility of loading textures with corner positions (idk what its officialy called) to be able to make it look 3D

#

or mabye be able to export the threejs render in a different way so i can access it

spring dove
#

See if this is satisfying enough! deno run -A cube.js

sharp minnow
#

ohh thats cool. already figured out another way tho. mabye a bit slower but idc abb speed. i made the renderer set the textContent to the dataUrl and use puppeteer to load the page, wait for the data to be put in the body and turn the data into an image.

#

got another problem now is that the image wont show.
this is the code where it puts the items on the crafting grid:

let i = 0;
for (const item of recipe.items) {
    if (item == null) {
        i ++;
        continue;
    }
    const itemTexture: Image = await getTexture(item);
    console.log(itemTexture.width(), itemTexture.height());
    ctx.drawImage(itemTexture, slots[i][0] * recipe.size_multiplier, slots[i][1] * recipe.size_multiplier, itemTexture.width() * recipe.size_multiplier, itemTexture.height() * recipe.size_multiplier);
    i ++;
}

getTexture function:

async function getTexture(item: string): Promise<Image> {
    const itemModel: ItemModel = await import("./assets/minecraft/models/item/" + item + ".json", {with: {type: "json"}}).then(value => value.default);
    if (itemModel.parent == "minecraft:item/generated") {
        return await loadImage("./assets/minecraft/textures/" + itemModel.textures.layer0.substring(10) + ".png");
    }
    const parentModel: ItemModel = await import("./assets/minecraft/models/" + itemModel.parent.substring(10) + ".json", {with: {type: "json"}}).then(value => value.default);
    if (parentModel.parent == "minecraft:block/cube_all") {
        return await generateBlock(item);
    }
    throw `unsupported model format '${itemModel.parent}'`
}
#

and here it loads the image:

export default async function generateBlock(block: string): Promise<Image> {

    if (!existsSync("./tmp/" + block + ".png")) {
        if (!existsSync("./tmp")) Deno.mkdirSync("./tmp");
        const browser = await puppeteer.launch();
        const page = await browser.newPage();
        await page.goto("http://localhost:8000/renderer/index.html?material=" + block);
        await sleep(100);
        const data = await page.evaluate(() => document.body.textContent);
        
        const dataResponse = await fetch(data);
        const file = await Deno.open("./tmp/" + block + ".png", {create: true, write: true});
        await dataResponse.body?.pipeTo(file.writable);
    }
    
    return await loadImage("./tmp/" + block + ".png");
}
#

the width of the stone image is also logging just fine so it clearly has the image. its just not putting it in

#

sorry nvm its working. had to change the image size to a standard of 16 (the width of the crafting grid)