@harpiaresearch/vref 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  BSD 3-Clause License
2
2
 
3
- Copyright (c) 2024, Harpia AI Research
3
+ Copyright (c) 2026, Harpia AI Research
4
4
 
5
5
  Redistribution and use in source and binary forms, with or without
6
6
  modification, are permitted provided that the following conditions are met:
package/README.md CHANGED
@@ -1,220 +1,274 @@
1
+ <div align="center">
2
+
1
3
  # VREF — Visual Reference Format
2
4
 
3
- > **Standardized container for curated visual references in AI image generation**
5
+ **A standardized format for curated visual references in AI image generation**
4
6
 
5
7
  [![npm version](https://img.shields.io/npm/v/@harpiaresearch/vref)](https://www.npmjs.com/package/@harpiaresearch/vref)
6
8
  [![License](https://img.shields.io/badge/license-BSD--3--Clause-blue.svg)](LICENSE)
7
9
 
8
- Developed by [Harpia AI Research](https://harpiaresearch.cc) 🇧🇷
10
+ Harpia AI Research
11
+
12
+ </div>
13
+
14
+ ---
15
+
16
+ <div align="center">
17
+
18
+ ## The Problem
19
+
20
+ </div>
21
+
22
+ You know exactly what you want your AI to generate, but describing it in words is **nearly impossible**.
23
+
24
+ - 🤔 "How do I describe this art style?"
25
+ - 📸 "I have 20 reference images, but uploading them one by one is tedious"
26
+ - 🔄 "I can't easily share or reuse my reference collections"
27
+ - 😤 "Text prompts alone just don't capture the vision"
28
+
29
+ **Visual concepts are hard to describe, but easy to show.**
30
+
31
+ ---
32
+
33
+ <div align="center">
34
+
35
+ ## The Solution
36
+
37
+ **VREF** (Visual Reference Format) is a simple, open standard that packages your visual references into a single `.vref` file.
38
+
39
+ ```
40
+ Your 50 reference images → one references.vref file
41
+ ```
42
+
43
+ </div>
44
+
45
+ ### How It Works
46
+
47
+ ```
48
+ 1. Package images → references.vref
49
+ 2. Upload to AI platform
50
+ 3. Platform samples N random images
51
+ 4. You write text prompt
52
+ 5. AI generates with visual context
53
+ ```
54
+
55
+ Instead of fighting with text descriptions, you **show the AI what you want**.
9
56
 
10
57
  ---
11
58
 
12
- ## What is VREF?
59
+ <div align="center">
60
+
61
+ ## Why You Should Use VREF
13
62
 
14
- VREF (Visual Reference Format) is an open standard for packaging and sharing curated visual references for AI image generation platforms.
63
+ </div>
15
64
 
16
- Instead of uploading multiple loose images or struggling to describe complex visual concepts in text, users can:
65
+ ### ✅ For Creators
17
66
 
18
- 1. **Package** reference images into a single `.vref` file
19
- 2. **Upload** the `.vref` to any supporting AI platform
20
- 3. **Select** how many random references to use (via slider)
21
- 4. **Generate** images with visual context
67
+ **Stop struggling with prompts.**
68
+ - Package your mood boards, style references, and inspirations
69
+ - Upload once, reuse forever
70
+ - Share with your team or community
22
71
 
23
- ### The Problem
72
+ **Example:** Download `roblox-banners.vref` → Upload → Describe what you want → Get perfect results
24
73
 
25
- When generating images with AI, users often:
26
- - ❌ Know what they want visually but can't describe it in words
27
- - ❌ Need to upload 10-50 reference images individually
28
- - ❌ Can't easily share or reuse reference collections
29
- - ❌ Struggle to communicate style, mood, and composition
74
+ ### ✅ For Platforms
30
75
 
31
- ### The Solution
76
+ **Better user experience.**
77
+ - Users get better results faster
78
+ - Reduces prompt engineering frustration
79
+ - Differentiates your platform
80
+ - Simple to implement (< 1 day)
32
81
 
33
- VREF provides:
34
- - ✅ **Single file** container for multiple images
35
- - ✅ **Validated** image-only format
36
- - ✅ **Structured metadata** (tags, description, license)
37
- - ✅ **Portable** and shareable
38
- - ✅ **Random sampling** built-in
39
- - ✅ **Open standard** anyone can implement
82
+ ### ✅ For Everyone
83
+
84
+ **It's an open standard.**
85
+ - No vendor lock-in
86
+ - Portable across platforms
87
+ - Community-driven
88
+ - Free forever
40
89
 
41
90
  ---
42
91
 
92
+ <div align="center">
93
+
94
+ ## Real-World Use Cases
95
+
96
+ </div>
97
+
98
+ ### 🎮 Game Development
99
+ ```
100
+ rpg-sprites.vref → Character references
101
+ platformer-tiles.vref → Level design inspiration
102
+ ui-elements.vref → Interface styles
103
+ ```
104
+
105
+ ### 🎨 Creative Work
106
+ ```
107
+ architecture.vref → Building styles
108
+ color-palettes.vref → Mood and tone
109
+ typography.vref → Font and layout ideas
110
+ ```
111
+
112
+ ### 🤖 AI Training
113
+ ```
114
+ training-data.vref → Curated datasets
115
+ style-transfer.vref → Style references
116
+ fine-tuning.vref → Model-specific data
117
+ ```
118
+
119
+ ---
120
+
121
+ <div align="center">
122
+
43
123
  ## Installation
44
124
 
125
+ </div>
126
+
45
127
  ```bash
46
128
  npm install @harpiaresearch/vref
47
129
  ```
48
130
 
49
- Or use directly with `npx`:
131
+ Or use directly:
50
132
 
51
133
  ```bash
52
- npx create-vref
134
+ npx @harpiaresearch/vref
53
135
  ```
54
136
 
55
137
  ---
56
138
 
139
+ <div align="center">
140
+
57
141
  ## Quick Start
58
142
 
59
- ### Creating a .vref file (CLI)
143
+ </div>
144
+
145
+ ### Creating a .vref File
60
146
 
147
+ **CLI:**
61
148
  ```bash
62
- # From a directory of images
63
- npx create-vref ./my-images -o references.vref
149
+ # From a directory (via npx or global/local vref)
150
+ npx @harpiaresearch/vref ./my-images -o references.vref
64
151
 
65
- # With metadata
66
- npx create-vref ./images -o pack.vref \
152
+ # With metadata (including title name)
153
+ npx @harpiaresearch/vref ./images -o pack.vref \
67
154
  -n "My Reference Pack" \
68
- -d "Collection of visual references for X" \
69
- -t "style,mood,theme" \
155
+ -d "Collection of art references" \
156
+ -t "art,style,inspiration" \
70
157
  -a "Your Name" \
71
158
  -l "CC-BY-4.0"
72
-
73
- # From a single image
74
- npx create-vref image.png -o single.vref
75
159
  ```
76
160
 
77
- ### Using the library (JavaScript/TypeScript)
78
-
79
- **Creating a .vref file:**
80
-
161
+ **Code:**
81
162
  ```typescript
82
163
  import { VREFWriter } from '@harpiaresearch/vref';
83
164
 
84
165
  const writer = new VREFWriter({
85
- fileName: 'my-pack.vref',
86
- description: 'Collection of RPG character references',
87
- tags: ['rpg', 'characters', 'fantasy'],
166
+ name: 'Art Style References',
167
+ description: 'Collection of curated art style references',
168
+ tags: ['art', 'style'],
88
169
  author: 'Your Name',
89
170
  license: 'CC-BY-4.0',
90
171
  });
91
172
 
92
- // Add images from directory
93
- writer.addImagesFromDirectory('./images', true);
173
+ writer.addImagesFromDirectory('./images');
174
+ writer.write('references.vref');
175
+ ```
94
176
 
95
- // Or add individual images
96
- writer.addImageFromFile('./image1.png');
97
- writer.addImage('image2.jpg', imageBuffer);
177
+ ### Inspecting, Validating & Extracting via CLI
98
178
 
99
- // Write the .vref file
100
- writer.write('output.vref');
179
+ ```bash
180
+ # Inspect metadata and images in a pack
181
+ vref info references.vref
101
182
 
102
- console.log(`Created .vref with ${writer.getImageCount()} images`);
183
+ # Validate format and manifest integrity
184
+ vref validate references.vref
185
+
186
+ # Extract images to a directory
187
+ vref extract references.vref ./extracted-images
103
188
  ```
104
189
 
105
- **Reading a .vref file:**
190
+ ### Reading a .vref File
106
191
 
107
192
  ```typescript
108
193
  import { VREFReader } from '@harpiaresearch/vref';
109
194
 
110
- // Read the entire .vref file
111
- const vref = VREFReader.read('references.vref', { loadImages: true });
195
+ // Read file (optional validation & preloading)
196
+ const vref = VREFReader.read('references.vref', {
197
+ validate: true,
198
+ loadImages: true,
199
+ });
112
200
 
113
201
  console.log(`Loaded ${vref.manifest.imageCount} images`);
114
- console.log(`Description: ${vref.manifest.metadata?.description}`);
115
202
 
116
- // Get random sample of 3 images
117
- const randomImages = vref.sample(3);
118
- randomImages.forEach((buffer, idx) => {
119
- console.log(`Image ${idx + 1}: ${buffer.length} bytes`);
120
- });
203
+ // Sample 3 random images
204
+ const randomSamples = vref.sample(3);
121
205
 
122
206
  // Get specific image
123
207
  const image = vref.getImage('photo1.png');
124
- if (image) {
125
- // Do something with the image buffer
126
- }
127
- ```
128
-
129
- **Read only the manifest:**
130
208
 
131
- ```typescript
132
- import { VREFReader } from '@harpiaresearch/vref';
133
-
134
- const manifest = VREFReader.readManifest('references.vref');
135
- console.log(manifest);
136
- ```
137
-
138
- **Validate a .vref file:**
139
-
140
- ```typescript
141
- import { VREFReader } from '@harpiaresearch/vref';
142
-
143
- const result = VREFReader.validate('references.vref');
144
- if (result.valid) {
145
- console.log('✅ Valid .vref file');
146
- } else {
147
- console.error('❌ Invalid .vref file:');
148
- result.errors.forEach(err => console.error(` - ${err}`));
149
- }
209
+ // Extract all images to disk
210
+ VREFReader.extract('references.vref', './extracted');
150
211
  ```
151
212
 
152
213
  ---
153
214
 
154
- ## Use Cases
155
-
156
- ### 1. **AI Image Generation Platforms**
215
+ <div align="center">
157
216
 
158
- Users upload `.vref` files to platforms like:
159
- - Midjourney
160
- - Stable Diffusion
161
- - DALL-E
162
- - Replicate
163
- - Custom AI platforms
217
+ ## For AI Platform Developers
164
218
 
165
- The platform extracts random images and sends them as visual context along with the user's text prompt.
219
+ Integrating VREF takes **< 1 day**:
166
220
 
167
- ### 2. **Game Development**
221
+ </div>
168
222
 
169
- Distribute reference packs:
170
- - `rpg-sprites.vref` — Character sprites for RPG games
171
- - `platformer-tiles.vref` — Tile sets for platformers
172
- - `ui-elements.vref` — UI design references
223
+ ```typescript
224
+ import { VREFReader } from '@harpiaresearch/vref';
173
225
 
174
- ### 3. **Training ML Models**
226
+ // 1. User uploads .vref
227
+ const vref = VREFReader.read(uploadedFile, { loadImages: true });
175
228
 
176
- Use `.vref` files as datasets:
229
+ // 2. Show slider: "How many references? (1-{imageCount})"
230
+ const count = getUserSliderValue();
177
231
 
178
- ```typescript
179
- import { VREFReader } from '@harpiaresearch/vref';
180
- import { PixelGenModel } from '@harpiaresearch/pixelgen';
232
+ // 3. Sample random images
233
+ const references = vref.sample(count);
181
234
 
182
- const dataset = VREFReader.read('training-data.vref', { loadImages: true });
183
- const model = new PixelGenModel(3, 3);
235
+ // 4. Get user prompt
236
+ const prompt = getUserPrompt();
184
237
 
185
- // Train with VREF data
186
- // ...
238
+ // 5. Send to your AI
239
+ await generateImage({
240
+ prompt: prompt,
241
+ referenceImages: references,
242
+ });
187
243
  ```
188
244
 
189
- ### 4. **Design & Creative Work**
190
-
191
- Share mood boards and references:
192
- - `architecture-modern.vref`
193
- - `color-palettes-warm.vref`
194
- - `typography-references.vref`
245
+ **That's it.** ✅
195
246
 
196
247
  ---
197
248
 
198
- ## File Format Specification
249
+ ## File Format
199
250
 
200
251
  A `.vref` file is a ZIP container with:
201
252
 
202
253
  ```
203
- my-pack.vref (ZIP)
204
- ├── manifest.json
254
+ references.vref
255
+ ├── manifest.json (metadata)
205
256
  ├── image1.png
206
257
  ├── image2.jpg
207
- ├── image3.webp
208
- └── ...
258
+ └── image3.webp
209
259
  ```
210
260
 
211
- ### `manifest.json` Structure
261
+ **Supported formats:** PNG, JPEG, WebP, GIF, AVIF
262
+
263
+ **Only images allowed.** Any other file type is rejected.
264
+
265
+ ### manifest.json
212
266
 
213
267
  ```json
214
268
  {
215
- "version": "1.0.0",
269
+ "version": "1.0.2",
216
270
  "format": "VREF",
217
- "fileName": "my-pack.vref",
271
+ "fileName": "references.vref",
218
272
  "imageCount": 24,
219
273
  "images": [
220
274
  {
@@ -225,31 +279,47 @@ my-pack.vref (ZIP)
225
279
  "height": 1080
226
280
  }
227
281
  ],
228
- "createdAt": "2024-10-12T10:30:00.000Z",
282
+ "createdAt": "2026-10-13T10:30:00.000Z",
229
283
  "metadata": {
230
- "description": "Collection of X references",
231
- "tags": ["tag1", "tag2"],
232
- "author": "Author Name",
284
+ "name": "RPG Sprites",
285
+ "description": "Collection of references",
286
+ "tags": ["style", "mood"],
287
+ "author": "Your Name",
233
288
  "license": "CC-BY-4.0"
234
289
  }
235
290
  }
236
291
  ```
237
292
 
238
- ### Supported Image Formats
293
+ ---
239
294
 
240
- - ✅ PNG (`.png`)
241
- - ✅ JPEG (`.jpg`, `.jpeg`)
242
- - ✅ WebP (`.webp`)
243
- - ✅ GIF (`.gif`)
244
- - ✅ AVIF (`.avif`)
295
+ <div align="center">
245
296
 
246
- Any other file type is **rejected** with an error.
297
+ ## Why VREF Will Win
247
298
 
248
- ---
299
+ </div>
300
+
301
+ ### 🎯 Solves a Real Problem
302
+ Everyone who uses AI image generation has struggled with describing visual concepts. VREF makes it trivial.
303
+
304
+ ### 🚀 Simple to Implement
305
+ ZIP + JSON. No complex dependencies. Works everywhere.
306
+
307
+ ### 🌍 Open Standard
308
+ No company owns it. Community-driven. Free forever.
249
309
 
250
- ## API Reference
310
+ ### 📦 Already Shipping
311
+ - ✅ npm package published
312
+ - ✅ Full TypeScript support
313
+ - ✅ CLI tool ready (`create`, `info`, `validate`, `extract`)
314
+ - ✅ Automated test suite (`node:test`)
315
+ - ✅ Complete documentation
251
316
 
252
- ### `VREFWriter`
317
+ ### 🇧🇷 Made in Brazil
318
+ Harpia AI Research is putting Brazil on the map of AI innovation.
319
+
320
+ ---
321
+
322
+ ### VREFWriter
253
323
 
254
324
  ```typescript
255
325
  class VREFWriter {
@@ -265,102 +335,100 @@ class VREFWriter {
265
335
  }
266
336
  ```
267
337
 
268
- ### `VREFReader`
338
+ ### VREFReader
269
339
 
270
340
  ```typescript
271
341
  class VREFReader {
272
342
  static read(filePath: string, options?: VREFReadOptions): VREFReadResult;
273
343
  static readManifest(filePath: string): VREFManifest;
274
344
  static validate(filePath: string): { valid: boolean; errors: string[] };
345
+ static extract(filePath: string, targetDir: string): void;
275
346
  }
276
347
  ```
277
348
 
278
- ### Types
279
-
280
- See [src/types.ts](src/types.ts) for complete type definitions.
281
-
282
- ---
283
-
284
- ## Platform Integration
285
-
286
- ### For AI Platform Developers
287
-
288
- Integrating VREF support:
349
+ ### VREFReadResult
289
350
 
290
351
  ```typescript
291
- import { VREFReader } from '@harpiaresearch/vref';
352
+ interface VREFReadResult {
353
+ manifest: VREFManifest;
354
+ images?: Map<string, Buffer>;
355
+ sample: (count: number) => Buffer[];
356
+ getImage: (path: string) => Buffer | undefined;
357
+ }
358
+ ```
292
359
 
293
- // 1. User uploads .vref file
294
- const vref = VREFReader.read(uploadedFile, { loadImages: true });
360
+ Full API documentation: [TypeScript definitions](src/types.ts)
295
361
 
296
- // 2. Show slider: "How many references? (1 - {vref.manifest.imageCount})"
297
- const userSelectedCount = getUserSliderValue(); // e.g., 3
362
+ ---
298
363
 
299
- // 3. Sample random images
300
- const selectedImages = vref.sample(userSelectedCount);
364
+ ## Roadmap
301
365
 
302
- // 4. Get user's text prompt
303
- const userPrompt = getUserPrompt(); // "A warrior character in pixel art style"
366
+ ### Phase 1 ✅ (Done)
367
+ - Core library implementation
368
+ - CLI tool (`create`, `info`, `validate`, `extract`)
369
+ - Automated test coverage
370
+ - npm package published
371
+ - Full documentation
304
372
 
305
- // 5. Send to your AI model
306
- await generateImage({
307
- prompt: userPrompt,
308
- referenceImages: selectedImages,
309
- });
310
- ```
373
+ ### Phase 2 (In Progress)
374
+ - Community-created .vref files
375
+ - Platform integrations
376
+ - Example collections
311
377
 
312
- That's it! 🎉
378
+ ### Phase 3 (Future)
379
+ - Web-based .vref creator
380
+ - .vref marketplace
381
+ - Browser extensions
382
+ - Mobile support
313
383
 
314
384
  ---
315
385
 
316
- ## Examples
386
+ ## Join the Movement
317
387
 
318
- See the [examples/](examples/) directory for:
319
- - Creating `.vref` files
320
- - Reading and sampling images
321
- - Platform integration examples
322
- - PixelGen integration
388
+ VREF is just getting started. We need:
389
+
390
+ - **Platform developers**: Integrate VREF support
391
+ - **Creators**: Build and share .vref collections
392
+ - **Contributors**: Improve the library
393
+ - **Evangelists**: Spread the word
323
394
 
324
395
  ---
325
396
 
326
- ## Contributing
397
+ ## Links
327
398
 
328
- We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
399
+ - **npm**: https://www.npmjs.com/package/@harpiaresearch/vref
400
+ - **GitHub**: https://github.com/Harpia-AI-Research/vref
401
+ - **Harpia AI Research**: https://harpiaresearch.cc
402
+ - **Issues**: https://github.com/Harpia-AI-Research/vref/issues
329
403
 
330
404
  ---
331
405
 
332
406
  ## License
333
407
 
334
- BSD 3-Clause License
335
-
336
- Copyright (c) 2024, Harpia AI Research
408
+ This project is licensed under the **BSD 3-Clause License** - see the [LICENSE](LICENSE) file for details.
337
409
 
338
- See [LICENSE](LICENSE) for full text.
410
+ Copyright (c) 2026, Harpia AI Research
339
411
 
340
412
  ---
341
413
 
342
- ## Citation
414
+ ## Acknowledgments
343
415
 
344
- If you use VREF in your research or project:
416
+ VREF is an open standard for visual references in AI systems. Built to solve the gap between what creators envision and what they can describe in text.
345
417
 
346
- ```bibtex
347
- @software{vref2024,
348
- title = {VREF: Visual Reference Format for AI Image Generation},
349
- author = {Harpia AI Research},
350
- year = {2024},
351
- url = {https://github.com/Harpia-AI-Research/vref}
352
- }
353
- ```
418
+ **Technologies**: TypeScript, Node.js, adm-zip
354
419
 
355
420
  ---
356
421
 
357
- ## Links
422
+ <div align="center">
358
423
 
359
- - 🌐 Website: [harpiaresearch.cc](https://harpiaresearch.cc)
360
- - 📦 npm: [@harpiaresearch/vref](https://www.npmjs.com/package/@harpiaresearch/vref)
361
- - 📄 Specification: [docs/SPECIFICATION.md](docs/SPECIFICATION.md)
362
- - 💬 Issues: [GitHub Issues](https://github.com/Harpia-AI-Research/vref/issues)
424
+ **VREF** — Bridging vision and AI generation
363
425
 
364
- ---
426
+ <br><br>
427
+
428
+ [GitHub](https://github.com/Harpia-AI-Research/vref) •
429
+ [npm](https://www.npmjs.com/package/@harpiaresearch/vref) •
430
+ [Documentation](https://github.com/Harpia-AI-Research/vref#readme) •
431
+ [Issues](https://github.com/Harpia-AI-Research/vref/issues)
432
+
433
+ </div>
365
434
 
366
- **Made with 💚💛 by Harpia AI Research — São Paulo, Brazil** 🇧🇷
@@ -19,4 +19,8 @@ export declare class VREFReader {
19
19
  valid: boolean;
20
20
  errors: string[];
21
21
  };
22
+ /**
23
+ * Extract all files from a .vref file to a target directory
24
+ */
25
+ static extract(filePath: string, targetDir: string): void;
22
26
  }
@@ -51,6 +51,12 @@ class VREFReader {
51
51
  if (!fs.existsSync(filePath)) {
52
52
  throw new Error(`File not found: ${filePath}`);
53
53
  }
54
+ if (options.validate) {
55
+ const validation = VREFReader.validate(filePath);
56
+ if (!validation.valid) {
57
+ throw new Error(`Invalid .vref file: ${validation.errors.join(', ')}`);
58
+ }
59
+ }
54
60
  const zip = new adm_zip_1.default(filePath);
55
61
  const zipEntries = zip.getEntries();
56
62
  // Find and parse manifest
@@ -181,5 +187,18 @@ class VREFReader {
181
187
  return { valid: false, errors };
182
188
  }
183
189
  }
190
+ /**
191
+ * Extract all files from a .vref file to a target directory
192
+ */
193
+ static extract(filePath, targetDir) {
194
+ if (!fs.existsSync(filePath)) {
195
+ throw new Error(`File not found: ${filePath}`);
196
+ }
197
+ if (!fs.existsSync(targetDir)) {
198
+ fs.mkdirSync(targetDir, { recursive: true });
199
+ }
200
+ const zip = new adm_zip_1.default(filePath);
201
+ zip.extractAllTo(targetDir, true);
202
+ }
184
203
  }
185
204
  exports.VREFReader = VREFReader;
@@ -32,7 +32,7 @@ export declare class VREFWriter {
32
32
  */
33
33
  private isValidImageBuffer;
34
34
  /**
35
- * Get image dimensions (basic implementation for PNG and JPEG)
35
+ * Get image dimensions (supports PNG, JPEG, GIF, WebP)
36
36
  */
37
37
  private getImageDimensions;
38
38
  /**
@@ -125,13 +125,14 @@ class VREFWriter {
125
125
  }
126
126
  // Create manifest
127
127
  const manifest = {
128
- version: '1.0.0',
128
+ version: '1.0.2',
129
129
  format: 'VREF',
130
- fileName: path.basename(outputPath),
130
+ fileName: this.options.fileName || path.basename(outputPath),
131
131
  imageCount: this.images.size,
132
132
  images: imageMetadataList,
133
133
  createdAt: new Date().toISOString(),
134
134
  metadata: {
135
+ name: this.options.name,
135
136
  description: this.options.description,
136
137
  tags: this.options.tags,
137
138
  author: this.options.author,
@@ -154,28 +155,56 @@ class VREFWriter {
154
155
  * Validate image buffer by checking magic bytes
155
156
  */
156
157
  isValidImageBuffer(buffer, format) {
157
- if (buffer.length < 8)
158
+ if (!buffer || buffer.length < 8)
158
159
  return false;
159
160
  switch (format.toLowerCase()) {
160
161
  case 'png':
161
- return buffer[0] === 0x89 && buffer[1] === 0x50 && buffer[2] === 0x4e && buffer[3] === 0x47;
162
+ return (buffer.length >= 8 &&
163
+ buffer[0] === 0x89 &&
164
+ buffer[1] === 0x50 &&
165
+ buffer[2] === 0x4e &&
166
+ buffer[3] === 0x47);
162
167
  case 'jpg':
163
168
  case 'jpeg':
164
- return buffer[0] === 0xff && buffer[1] === 0xd8 && buffer[2] === 0xff;
169
+ return (buffer.length >= 3 &&
170
+ buffer[0] === 0xff &&
171
+ buffer[1] === 0xd8 &&
172
+ buffer[2] === 0xff);
165
173
  case 'gif':
166
- return buffer[0] === 0x47 && buffer[1] === 0x49 && buffer[2] === 0x46;
174
+ return (buffer.length >= 6 &&
175
+ buffer[0] === 0x47 &&
176
+ buffer[1] === 0x49 &&
177
+ buffer[2] === 0x46 &&
178
+ buffer[3] === 0x38 &&
179
+ (buffer[4] === 0x37 || buffer[4] === 0x39) &&
180
+ buffer[5] === 0x61);
167
181
  case 'webp':
168
- return buffer[8] === 0x57 && buffer[9] === 0x45 && buffer[10] === 0x42 && buffer[11] === 0x50;
182
+ return (buffer.length >= 12 &&
183
+ buffer[0] === 0x52 &&
184
+ buffer[1] === 0x49 &&
185
+ buffer[2] === 0x46 &&
186
+ buffer[3] === 0x46 &&
187
+ buffer[8] === 0x57 &&
188
+ buffer[9] === 0x45 &&
189
+ buffer[10] === 0x42 &&
190
+ buffer[11] === 0x50);
169
191
  case 'avif':
170
- // AVIF detection is more complex, but we can check for 'ftyp' box
171
- const ftypCheck = buffer.toString('ascii', 4, 8);
172
- return ftypCheck === 'ftyp';
192
+ if (buffer.length < 16)
193
+ return false;
194
+ const ftypBox = buffer.toString('ascii', 4, 8);
195
+ if (ftypBox !== 'ftyp')
196
+ return false;
197
+ const majorBrand = buffer.toString('ascii', 8, 12);
198
+ if (majorBrand === 'avif' || majorBrand === 'avis')
199
+ return true;
200
+ const headerSlice = buffer.subarray(12, Math.min(buffer.length, 64)).toString('ascii');
201
+ return headerSlice.includes('avif') || headerSlice.includes('avis');
173
202
  default:
174
203
  return false;
175
204
  }
176
205
  }
177
206
  /**
178
- * Get image dimensions (basic implementation for PNG and JPEG)
207
+ * Get image dimensions (supports PNG, JPEG, GIF, WebP)
179
208
  */
180
209
  getImageDimensions(buffer, format) {
181
210
  try {
@@ -185,8 +214,6 @@ class VREFWriter {
185
214
  return { width, height };
186
215
  }
187
216
  if ((format === 'jpg' || format === 'jpeg') && buffer.length >= 4) {
188
- // Basic JPEG dimension extraction (simplified)
189
- // This is a simplified version; production code might use a library
190
217
  let offset = 2;
191
218
  while (offset < buffer.length) {
192
219
  if (buffer[offset] !== 0xff)
@@ -202,6 +229,33 @@ class VREFWriter {
202
229
  offset += segmentLength;
203
230
  }
204
231
  }
232
+ if (format === 'gif' && buffer.length >= 10) {
233
+ const width = buffer.readUInt16LE(6);
234
+ const height = buffer.readUInt16LE(8);
235
+ return { width, height };
236
+ }
237
+ if (format === 'webp' && buffer.length >= 30) {
238
+ const chunkType = buffer.toString('ascii', 12, 16);
239
+ if (chunkType === 'VP8 ' && buffer.length >= 30) {
240
+ const width = buffer.readUInt16LE(26) & 0x3fff;
241
+ const height = buffer.readUInt16LE(28) & 0x3fff;
242
+ return { width, height };
243
+ }
244
+ else if (chunkType === 'VP8L' && buffer.length >= 25) {
245
+ const b1 = buffer[21];
246
+ const b2 = buffer[22];
247
+ const b3 = buffer[23];
248
+ const b4 = buffer[24];
249
+ const width = 1 + (((b2 & 0x3f) << 8) | b1);
250
+ const height = 1 + (((b4 & 0x0f) << 10) | (b3 << 2) | ((b2 & 0xc0) >> 6));
251
+ return { width, height };
252
+ }
253
+ else if (chunkType === 'VP8X' && buffer.length >= 30) {
254
+ const width = 1 + buffer.readUIntLE(24, 3);
255
+ const height = 1 + buffer.readUIntLE(27, 3);
256
+ return { width, height };
257
+ }
258
+ }
205
259
  }
206
260
  catch (error) {
207
261
  // If dimension extraction fails, just return undefined
package/dist/cli.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * VREF CLI - Command line interface for creating .vref files
3
+ * VREF CLI - Command line interface for .vref files
4
4
  * Harpia AI Research
5
5
  */
6
6
  export {};
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
  /**
4
- * VREF CLI - Command line interface for creating .vref files
4
+ * VREF CLI - Command line interface for .vref files
5
5
  * Harpia AI Research
6
6
  */
7
7
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
@@ -41,47 +41,144 @@ Object.defineProperty(exports, "__esModule", { value: true });
41
41
  const fs = __importStar(require("fs"));
42
42
  const path = __importStar(require("path"));
43
43
  const VREFWriter_1 = require("./VREFWriter");
44
+ const VREFReader_1 = require("./VREFReader");
45
+ const CLI_VERSION = '1.0.2';
44
46
  function showHelp() {
45
47
  console.log(`
46
48
  ┌─────────────────────────────────────────────────┐
47
- │ VREF CLI v1.0.0 │
49
+ │ VREF CLI v${CLI_VERSION} │
48
50
  │ by Harpia AI Research │
49
51
  │ https://harpiaresearch.cc │
50
52
  └─────────────────────────────────────────────────┘
51
53
 
52
- Create .vref files from images
54
+ Standardized container for curated visual references in AI image generation
53
55
 
54
56
  USAGE:
55
- npx create-vref <input> [options]
56
-
57
- ARGUMENTS:
58
- <input> Path to image file or directory
57
+ npx @harpiaresearch/vref <input> [options]
58
+ vref <command> [arguments]
59
59
 
60
- OPTIONS:
61
- -o, --output <path> Output .vref file path (default: output.vref)
62
- -n, --name <name> Name for the reference pack
63
- -d, --desc <text> Description of the reference pack
64
- -t, --tags <tags> Comma-separated tags
65
- -a, --author <name> Author name
66
- -l, --license <lic> License (e.g., CC-BY-4.0, MIT)
67
- -r, --recursive Include subdirectories
68
- -h, --help Show this help
60
+ COMMANDS:
61
+ <input> [options] Create a .vref file from an image or directory
62
+ info, inspect <file.vref> Inspect metadata and images in a .vref file
63
+ validate <file.vref> Validate integrity and manifest of a .vref file
64
+ extract <file.vref> [dir] Extract all images from a .vref file
65
+
66
+ CREATION OPTIONS:
67
+ -o, --output <path> Output .vref file path (default: output.vref)
68
+ -n, --name <name> Name/title for the reference pack
69
+ -d, --desc <text> Description of the reference pack
70
+ -t, --tags <tags> Comma-separated tags
71
+ -a, --author <name> Author name
72
+ -l, --license <lic> License (e.g., CC-BY-4.0, MIT)
73
+ -r, --recursive Include subdirectories
74
+ -v, --version Show CLI version
75
+ -h, --help Show this help
69
76
 
70
77
  EXAMPLES:
71
- # Create from single image
72
- npx create-vref image.png -o references.vref
73
-
74
78
  # Create from directory
75
- npx create-vref ./images -o pack.vref -n "My Pack"
76
-
77
- # With metadata
78
- npx create-vref ./sprites -o rpg-sprites.vref \\
79
+ npx @harpiaresearch/vref ./images -o pack.vref -n "My Pack"
80
+
81
+ # Create with complete metadata
82
+ npx @harpiaresearch/vref ./sprites -o rpg-sprites.vref \\
79
83
  -n "RPG Sprites" \\
80
84
  -d "Character sprites for RPG games" \\
81
85
  -t "rpg,sprites,pixelart" \\
82
86
  -a "Your Name" \\
83
87
  -l "CC-BY-4.0"
84
- `);
88
+
89
+ # Inspect an existing .vref file
90
+ vref info references.vref
91
+
92
+ # Validate file integrity
93
+ vref validate references.vref
94
+
95
+ # Extract images
96
+ vref extract references.vref ./extracted-images
97
+ `);
98
+ }
99
+ function handleValidate(filePath) {
100
+ if (!filePath) {
101
+ console.error('❌ Error: Please specify a .vref file to validate');
102
+ process.exit(1);
103
+ }
104
+ console.log(`🔍 Validating ${filePath}...`);
105
+ const result = VREFReader_1.VREFReader.validate(filePath);
106
+ if (result.valid) {
107
+ const manifest = VREFReader_1.VREFReader.readManifest(filePath);
108
+ console.log(`✅ Valid .vref file!`);
109
+ console.log(` Format: ${manifest.format} (v${manifest.version})`);
110
+ console.log(` Images: ${manifest.imageCount}`);
111
+ if (manifest.metadata?.name)
112
+ console.log(` Name: ${manifest.metadata.name}`);
113
+ }
114
+ else {
115
+ console.error(`❌ Validation failed with ${result.errors.length} error(s):`);
116
+ result.errors.forEach(err => console.error(` - ${err}`));
117
+ process.exit(1);
118
+ }
119
+ }
120
+ function handleInfo(filePath) {
121
+ if (!filePath) {
122
+ console.error('❌ Error: Please specify a .vref file to inspect');
123
+ process.exit(1);
124
+ }
125
+ try {
126
+ const manifest = VREFReader_1.VREFReader.readManifest(filePath);
127
+ const stats = fs.statSync(filePath);
128
+ const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
129
+ console.log(`\n📦 File: ${path.basename(filePath)} (${sizeMB} MB)`);
130
+ console.log(` Format: ${manifest.format} v${manifest.version}`);
131
+ console.log(` Created at: ${manifest.createdAt}`);
132
+ console.log(` Total images: ${manifest.imageCount}`);
133
+ if (manifest.metadata) {
134
+ console.log('\n📋 Metadata:');
135
+ if (manifest.metadata.name)
136
+ console.log(` Name: ${manifest.metadata.name}`);
137
+ if (manifest.metadata.description)
138
+ console.log(` Description: ${manifest.metadata.description}`);
139
+ if (manifest.metadata.tags && manifest.metadata.tags.length > 0) {
140
+ console.log(` Tags: ${manifest.metadata.tags.join(', ')}`);
141
+ }
142
+ if (manifest.metadata.author)
143
+ console.log(` Author: ${manifest.metadata.author}`);
144
+ if (manifest.metadata.license)
145
+ console.log(` License: ${manifest.metadata.license}`);
146
+ }
147
+ if (manifest.images.length > 0) {
148
+ console.log('\n🖼️ Sample of contained images:');
149
+ const previewCount = Math.min(manifest.images.length, 5);
150
+ for (let i = 0; i < previewCount; i++) {
151
+ const img = manifest.images[i];
152
+ const dim = img.width && img.height ? ` (${img.width}x${img.height})` : '';
153
+ const sizeKB = (img.size / 1024).toFixed(1);
154
+ console.log(` - ${img.path} [${img.format.toUpperCase()}]${dim} - ${sizeKB} KB`);
155
+ }
156
+ if (manifest.images.length > previewCount) {
157
+ console.log(` ... and ${manifest.images.length - previewCount} more`);
158
+ }
159
+ }
160
+ console.log();
161
+ }
162
+ catch (error) {
163
+ console.error(`❌ Error inspecting file: ${error.message}`);
164
+ process.exit(1);
165
+ }
166
+ }
167
+ function handleExtract(filePath, outputDir) {
168
+ if (!filePath) {
169
+ console.error('❌ Error: Please specify a .vref file to extract');
170
+ process.exit(1);
171
+ }
172
+ const targetDir = outputDir || path.join(process.cwd(), path.basename(filePath, '.vref') + '_extracted');
173
+ try {
174
+ console.log(`📦 Extracting ${filePath} to ${targetDir}...`);
175
+ VREFReader_1.VREFReader.extract(filePath, targetDir);
176
+ console.log(`✅ Extracted successfully to ${targetDir}`);
177
+ }
178
+ catch (error) {
179
+ console.error(`❌ Extraction error: ${error.message}`);
180
+ process.exit(1);
181
+ }
85
182
  }
86
183
  function parseArgs(args) {
87
184
  const options = {
@@ -102,6 +199,11 @@ function parseArgs(args) {
102
199
  showHelp();
103
200
  process.exit(0);
104
201
  break;
202
+ case '-v':
203
+ case '--version':
204
+ console.log(`v${CLI_VERSION}`);
205
+ process.exit(0);
206
+ break;
105
207
  case '-o':
106
208
  case '--output':
107
209
  options.output = args[++i];
@@ -117,7 +219,7 @@ function parseArgs(args) {
117
219
  break;
118
220
  case '-t':
119
221
  case '--tags':
120
- options.tags = args[++i].split(',').map((t) => t.trim());
222
+ options.tags = args[++i]?.split(',').map((t) => t.trim());
121
223
  break;
122
224
  case '-a':
123
225
  case '--author':
@@ -132,7 +234,7 @@ function parseArgs(args) {
132
234
  options.recursive = true;
133
235
  break;
134
236
  default:
135
- if (!arg.startsWith('-')) {
237
+ if (!arg.startsWith('-') && !options.input) {
136
238
  options.input = arg;
137
239
  }
138
240
  break;
@@ -146,10 +248,31 @@ function main() {
146
248
  showHelp();
147
249
  process.exit(0);
148
250
  }
251
+ const firstArg = args[0];
252
+ if (firstArg === 'validate') {
253
+ handleValidate(args[1]);
254
+ return;
255
+ }
256
+ if (firstArg === 'info' || firstArg === 'inspect') {
257
+ handleInfo(args[1]);
258
+ return;
259
+ }
260
+ if (firstArg === 'extract') {
261
+ handleExtract(args[1], args[2]);
262
+ return;
263
+ }
264
+ if (firstArg === '-h' || firstArg === '--help') {
265
+ showHelp();
266
+ process.exit(0);
267
+ }
268
+ if (firstArg === '-v' || firstArg === '--version') {
269
+ console.log(`v${CLI_VERSION}`);
270
+ process.exit(0);
271
+ }
149
272
  const options = parseArgs(args);
150
273
  if (!options.input) {
151
274
  console.error('❌ Error: No input specified');
152
- console.log('Run "npx create-vref --help" for usage information');
275
+ console.log('Run "npx @harpiaresearch/vref --help" for usage information');
153
276
  process.exit(1);
154
277
  }
155
278
  if (!fs.existsSync(options.input)) {
@@ -157,13 +280,13 @@ function main() {
157
280
  process.exit(1);
158
281
  }
159
282
  console.log('┌─────────────────────────────────────────────────┐');
160
- console.log('│ VREF CLI v1.0.0 │');
283
+ console.log(`│ VREF CLI v${CLI_VERSION} │`);
161
284
  console.log('│ by Harpia AI Research │');
162
285
  console.log('└─────────────────────────────────────────────────┘\n');
163
286
  try {
164
- const fileName = options.name || path.basename(options.output, '.vref');
165
287
  const writer = new VREFWriter_1.VREFWriter({
166
- fileName: options.output,
288
+ fileName: path.basename(options.output),
289
+ name: options.name,
167
290
  description: options.description,
168
291
  tags: options.tags,
169
292
  author: options.author,
package/dist/types.d.ts CHANGED
@@ -23,6 +23,8 @@ export interface VREFManifest {
23
23
  createdAt: string;
24
24
  /** Optional metadata */
25
25
  metadata?: {
26
+ /** Human-readable title/name of the reference pack */
27
+ name?: string;
26
28
  /** Description of the reference pack */
27
29
  description?: string;
28
30
  /** Tags for categorization */
@@ -54,8 +56,10 @@ export interface ImageMetadata {
54
56
  * Options for creating a VREF file
55
57
  */
56
58
  export interface VREFCreateOptions {
57
- /** Name for the output .vref file */
58
- fileName: string;
59
+ /** Optional name/title for the reference pack */
60
+ name?: string;
61
+ /** Name for the output .vref file (optional, defaults to output path file name) */
62
+ fileName?: string;
59
63
  /** Optional description */
60
64
  description?: string;
61
65
  /** Optional tags */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harpiaresearch/vref",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Visual Reference Format - Standardized container for curated visual references in AI image generation",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,8 +10,8 @@
10
10
  "LICENSE"
11
11
  ],
12
12
  "bin": {
13
- "create-vref": "./dist/cli.js",
14
- "vref": "./dist/cli.js"
13
+ "create-vref": "dist/cli.js",
14
+ "vref": "dist/cli.js"
15
15
  },
16
16
  "scripts": {
17
17
  "build": "tsc",
@@ -32,7 +32,7 @@
32
32
  "license": "BSD-3-Clause",
33
33
  "repository": {
34
34
  "type": "git",
35
- "url": "https://github.com/Harpia-AI-Research/vref"
35
+ "url": "git+https://github.com/Harpia-AI-Research/vref.git"
36
36
  },
37
37
  "dependencies": {
38
38
  "adm-zip": "^0.5.10"