Skip to content

Commit 50442dd

Browse files
fix: improve image dataset handling (#162)
1 parent 6e6c526 commit 50442dd

26 files changed

+485
-125
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@ This is the source code repository for the documentation of [image-js](https://g
44

55
The documentation is available on <https://docs.image-js.org/>.
66

7+
## Generating demo images
8+
9+
To regenerate the demo images (only needed when adding/updating images):
10+
11+
```bash
12+
npm run generate-images
13+
```
14+
15+
This will:
16+
17+
- Fetch images from the URLs defined in `defaultImageUrls.ts`
18+
- Save them to the `static/` folder
19+
- Generate `imageData.json` with metadata
20+
721
## Create demos
822

923
A demo is simply a function which takes an image or mask as input and returns an image or mask as output. When imported in `md` files, it will be transformed into a demo component which allows choosing from various image or video sources to showcase the image transformation.

generateImages.mjs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
4+
import { fetchURL, write } from 'image-js';
5+
6+
import { defaultImages, defaultMasks } from './imageDataset.mjs';
7+
8+
const __dirname = import.meta.dirname;
9+
10+
export async function imageLoader() {
11+
const demoImagesDir = 'demoImages';
12+
const staticDir = 'static';
13+
14+
const imageData = { masks: [], images: [] };
15+
try {
16+
// Create static directory if it doesn't exist
17+
const staticPath = path.join(__dirname, staticDir, demoImagesDir);
18+
19+
if (!fs.existsSync(staticPath)) {
20+
fs.mkdirSync(staticPath, { recursive: true });
21+
}
22+
23+
const images = await Promise.all(
24+
defaultImages.map((imageDataUrl) => fetchURL(imageDataUrl.value)),
25+
);
26+
27+
for (let i = 0; i < images.length; i++) {
28+
const image = images[i];
29+
const imageDataUrl = defaultImages[i];
30+
const imageTitle = getFilename(imageDataUrl.value);
31+
const imagePath = path.join(
32+
__dirname,
33+
staticDir,
34+
demoImagesDir,
35+
'images',
36+
imageTitle,
37+
);
38+
write(imagePath, image, { recursive: true });
39+
// Keeping object structure for compatibility
40+
imageData.images.push({
41+
type: 'url',
42+
imageType: 'image',
43+
label: `${imageDataUrl.label} (${image.width}x${image.height})`,
44+
value: `/${demoImagesDir}/images/${imageTitle}`,
45+
});
46+
}
47+
48+
const masks = await Promise.all(
49+
defaultMasks.map((maskDataUrl) => fetchURL(maskDataUrl.value)),
50+
);
51+
52+
for (let i = 0; i < masks.length; i++) {
53+
const mask = masks[i];
54+
const maskDataUrl = defaultMasks[i];
55+
const maskTitle = getFilename(maskDataUrl.value);
56+
const maskPath = path.join(
57+
__dirname,
58+
staticDir,
59+
demoImagesDir,
60+
'masks',
61+
maskTitle,
62+
);
63+
write(maskPath, mask, { recursive: true });
64+
// Keeping object structure for compatibility
65+
imageData.masks.push({
66+
type: 'url',
67+
imageType: 'mask',
68+
label: `${maskDataUrl.label} (${mask.width}x${mask.height})`,
69+
value: `/${demoImagesDir}/masks/${maskTitle}`,
70+
});
71+
}
72+
// Write data about newly created files.
73+
const outputPath = path.join(__dirname, 'src/demo/contexts/demo/generated');
74+
if (!fs.existsSync(outputPath)) {
75+
fs.mkdirSync(outputPath, { recursive: true });
76+
}
77+
fs.writeFileSync(
78+
`${outputPath}/imageData.json`,
79+
JSON.stringify(imageData, null, 2),
80+
);
81+
} catch (error) {
82+
throw new Error(`Error in imageLoader: ${error.message}`);
83+
}
84+
85+
return imageData;
86+
}
87+
// Returns only filename with extension.
88+
function getFilename(filepath) {
89+
return filepath.replace(/^.*[\\/]/, '');
90+
}
91+
await imageLoader();

imageDataset.mjs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
const standardUrl = 'https://demo-dataset.image-js.org/standard';
2+
const standardMaskUrl = 'https://demo-dataset.image-js.org/standard_mask';
3+
const morphologyMaskUrl = 'https://demo-dataset.image-js.org/morphology_mask';
4+
5+
export const defaultImages = [
6+
{
7+
value: `${standardUrl}/jellybeans.png`,
8+
label: 'Jelly beans ',
9+
imageType: 'image',
10+
},
11+
{
12+
value: `${standardUrl}/female.png`,
13+
label: 'Female',
14+
imageType: 'image',
15+
},
16+
{
17+
value: `${standardUrl}/femaleBellLabs.png`,
18+
label: 'Female from Bell Labs ',
19+
imageType: 'image',
20+
},
21+
{
22+
value: `${standardUrl}/house.png`,
23+
label: 'House',
24+
imageType: 'image',
25+
},
26+
{
27+
value: `${standardUrl}/mandrill.png`,
28+
label: 'Mandrill',
29+
imageType: 'image',
30+
},
31+
{
32+
value: `${standardUrl}/peppers.png`,
33+
label: 'Peppers',
34+
imageType: 'image',
35+
},
36+
37+
{
38+
value: `${standardUrl}/barbara.jpg`,
39+
label: 'Barbara',
40+
imageType: 'image',
41+
},
42+
43+
{
44+
value: `${standardUrl}/boat.png`,
45+
label: 'Standard boat',
46+
imageType: 'image',
47+
},
48+
{
49+
value: `${standardUrl}/male.png`,
50+
label: 'Male',
51+
imageType: 'image',
52+
},
53+
{
54+
value: `${standardUrl}/airport.png`,
55+
label: 'Airport',
56+
imageType: 'image',
57+
},
58+
];
59+
60+
export const defaultMasks = [
61+
{
62+
type: 'url',
63+
value: `${morphologyMaskUrl}/circles.png`,
64+
label: 'Circles',
65+
imageType: 'mask',
66+
},
67+
{
68+
value: `${morphologyMaskUrl}/shapes.png`,
69+
label: 'Shapes',
70+
imageType: 'mask',
71+
},
72+
{
73+
value: `${morphologyMaskUrl}/star.png`,
74+
label: 'Star',
75+
imageType: 'mask',
76+
},
77+
{
78+
value: `${standardMaskUrl}/house.png`,
79+
label: 'House',
80+
imageType: 'mask',
81+
},
82+
{
83+
value: `${standardMaskUrl}/mandrill.png`,
84+
label: 'Mandrill',
85+
imageType: 'mask',
86+
},
87+
{
88+
value: `${standardMaskUrl}/peppers.png`,
89+
label: 'Peppers',
90+
imageType: 'mask',
91+
},
92+
93+
{
94+
value: `${standardMaskUrl}/barbara.png`,
95+
label: 'Barbara',
96+
imageType: 'mask',
97+
},
98+
{
99+
value: `${standardMaskUrl}/boat.png`,
100+
label: 'Standard boat',
101+
imageType: 'mask',
102+
},
103+
104+
{
105+
value: `${standardMaskUrl}/male.png`,
106+
label: 'Male',
107+
imageType: 'mask',
108+
},
109+
];

0 commit comments

Comments
 (0)