このコミットが含まれているのは:
Vilyaem 2024-05-13 08:28:48 -04:00
コミット 1e18558472
27個のファイルの変更515行の追加0行の削除

1
.gitignore vendored ノーマルファイル
ファイルの表示

@ -0,0 +1 @@
.svcs/

144
README.md ノーマルファイル
ファイルの表示

@ -0,0 +1,144 @@
# VNM
Venom (vnm, virtual nano media) is an experimental
image, audio, and video file format.
It's suppposed to be extremely simple and [suckless](https://suckless.org).
Images are 16 color and run length encoded, It's like 'farbfeld' driven
to its end conclusion. The default color palette is that of TempleOS'.
__Venom is the best set of multimedia formats in the world.__
---
## IMAGES
Magic number letter "V" (86)
uint8 width and height as a single value
(must be power of two), this is multiplied by 8, max resulting resolution is
1024x1024
So to get 1024x1024 this value is 128, to get 512x512 you do 64.
row by row uint8 (color) and uint8 (run length)
---
## AUDIO
Audio is always 8000hz
Magic number letter "A" (65)
uint8 list of samples.
---
## VIDEO
Video is at the top, audio at the bottom, Video is 30FPS.
Width and height is unchanging.
Sequence of "V" images
The audio "A" sequence
---
## TOS COLOR PALETTE
This will be default for all the programs.
00. #000000 (Black) 0,0,0
01. #0000AA (Blue) 0,0,170
02. #00AA00 (Green) 0,170,0
03. #00AAAA (Cyan) 0,170,170
04. #AA0000 (Red) 170,0,0
05. #AA00AA (Magenta) 170,0,170
06. #AA5500 (Brown) 170,79,0
07. #AAAAAA (Light Gray) 170,170,170
08. #555555 (Dark Gray) 79,79,79
09. #5555FF (Light Blue) 79,79,255
10. #55FF55 (Light Green) 79,255,79
11. #55FFFF (Light Cyan) 79,255,255
12. #FF5555 (Light Red) 255,79,79
13. #FF55FF (Light Magenta) 255,79,255
14. #FFFF55 (Yellow) 255,255,79
15. #FFFFFF (White) 255,255,255
---
## Why?
Multimedia sucks. You may notice that all the files are completely
composed of eight bit integers, this allows for multimedia files to
be easily modified by UNIX utilities in interesting interactions, or
be generated very easily. I can see the feasibility of getting a VNM
file to glitch out, but I don't really care, and it has never
happened in practice. Ive discovered that 16 color isnt a such
a hardship, it's quite liberating, especially with proper dithering
images can look indistinguishable and 'cooler'. The palettes of the programs
can also just be modified to best suite a set of images.
VNM is also perfect for embedded assets in ROMs.
---
## PROGRAMS
ff2vnm - Convert farbfeld images to vnm images
vnmstat - Program that identifies, validates, and makes stats for a vnm file
vnmnoise - Example program that generates an unoptimized noisy image
vnmbeat - Example program that generates a sound file
vnmcarr - Convert VNM files into C arrays
VNM is so simple, you can just use your core utils to work
with it.
Combining images into a video: cat baby.vnm recursion.vnm > slideshow.vnm
Splitting video into images and audio: csplit -z slideshow.vnm /V/ '{*}'
---
## SCRIPTS
png2vnm.sh - Convert PNG to VNM given png2ff
vid2vnm.sh - Convert video to VNM
## PHILANTHROPY
_official VNM donation fund_
Monero (XMR): 48Sxa8J6518gqp4WeGtQ4rLe6SctPrEnnCqm6v6ydjLwRPi9Uh9gvVuUsU2AEDw75meTHCNY8KfU6Txysom4Bn5qPKMJ75w
Wownero (WOW): WW2L2yC6DMg7GArAH3nqXPA6UBoRogf64GodceqA32SeZQpx27xd6rqN82e36KE48a8SAMSoXDB5WawAgVEFKfkw1Q5KSGfX9
If you have philanthropic interest in VNM, contact Vilyaem.
---
## LICENSE
CHRISTIAN FREE SOFTWARE LICENSE
CFSL
This software is free and open source charity ware, users are asked
to donate to the Eastern Orthodox Church by any means.
Redistribution of this project in source and/or binary forms with/without
modification, are permitted provided that the following conditions are met:
1. Redistributions must retain this notice, the conditions, and the disclaimer.
2. Redistributions must retain credit to the author, and signage to where the original
work can be found.
3. Redistributions cannot become a part of, in anyway shape or form, part of proprietary
software, or software that is clearly out of line with Christian values.
4. Redistributions must remain free, both in price, and what users may do with the software,
the software must remain public and easily accessible.
DISCLAIMER
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

バイナリ
bin/ff2vnm 実行可能ファイル

バイナリファイルは表示されません。

バイナリ
bin/vnmbeat 実行可能ファイル

バイナリファイルは表示されません。

バイナリ
bin/vnmcarr 実行可能ファイル

バイナリファイルは表示されません。

バイナリ
bin/vnmnoise 実行可能ファイル

バイナリファイルは表示されません。

バイナリ
bin/vnmstat 実行可能ファイル

バイナリファイルは表示されません。

10
c.sh 実行可能ファイル
ファイルの表示

@ -0,0 +1,10 @@
#!/bin/sh
cl
rm bin/*
CC="cc -O3 -std=c89 -Wall -Wpedantic -Wextra -Werror "
$CC programs/ff2vnm.c -o bin/ff2vnm
$CC programs/vnmbeat.c -o bin/vnmbeat
$CC programs/vnmcarr.c -o bin/vnmcarr
$CC programs/vnmnoise.c -o bin/vnmnoise
$CC programs/vnmstat.c -o bin/vnmstat
doas cp bin/* /usr/bin/

バイナリ
examples/baby.ff ノーマルファイル

バイナリファイルは表示されません。

バイナリ
examples/baby.vnm ノーマルファイル

バイナリファイルは表示されません。

バイナリ
examples/black.ff ノーマルファイル

バイナリファイルは表示されません。

バイナリ
examples/black.vnm ノーマルファイル

バイナリファイルは表示されません。

バイナリ
examples/church.ff ノーマルファイル

バイナリファイルは表示されません。

バイナリ
examples/church.vnm ノーマルファイル

バイナリファイルは表示されません。

バイナリ
examples/empire.wav ノーマルファイル

バイナリファイルは表示されません。

バイナリ
examples/lord.ff ノーマルファイル

バイナリファイルは表示されません。

バイナリ
examples/noise.vnm ノーマルファイル

バイナリファイルは表示されません。

バイナリ
examples/recursive.ff ノーマルファイル

バイナリファイルは表示されません。

バイナリ
examples/recursive.vnm ノーマルファイル

バイナリファイルは表示されません。

156
programs/ff2vnm.c ノーマルファイル
ファイルの表示

@ -0,0 +1,156 @@
/*********************************************
* Description - Convert Farbfeld images to VNM
* Author - Vilyaem
* Date - May 03 2024
* *******************************************/
/*----------PREPROCESSOR----------*/
#include <stdio.h>
#include <stdint.h>
#define MAXRES 512
/*----------DATA STRUCTURES----------*/
/*color*/
typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
} Color;
/*----------GLOBALS----------*/
Color palette[16] = {
{0, 0, 0}, /*#000000 (Black)*/
{0, 0, 170}, /*#0000AA (Blue)*/
{0, 170, 0}, /*#00AA00 (Green)*/
{0, 170, 170}, /*#00AAAA (Cyan)*/
{170, 0, 0}, /*#AA0000 (Red)*/
{170, 0, 170}, /*#AA00AA (Magenta)*/
{170, 79, 0}, /*#AA5500 (Brown)*/
{170, 170, 170}, /*#AAAAAA (Light Gray)*/
{79, 79, 79}, /*#555555 (Dark Gray)*/
{79, 79, 255}, /*#5555FF (Light Blue)*/
{79, 255, 79}, /*#55FF55 (Light Green)*/
{79, 255, 255}, /*#55FFFF (Light Cyan)*/
{255, 79, 79}, /*#FF5555 (Light Red)*/
{255, 79, 255}, /*#FF55FF (Light Magenta)*/
{255, 255, 79}, /*#FFFF55 (Yellow)*/
{255, 255, 255} /*#FFFFFF (White)*/
};
int i;
/*----------FUNCTIONS----------*/
/*********************************************
* Description - Find closest colour in the palette
* Author - Vilyaem
* Date - May 03 2024
* *******************************************/
uint8_t findClosestColor(Color pixel) {
uint8_t closestColor;
int minDistance;
closestColor = 0;
minDistance = 255 * 255 * 3; /* Initialize with max distance value*/
for (i = 0; i < 16; i++) {
int dr;
int dg;
int db;
int distance;
dr = pixel.r - palette[i].r;
dg = pixel.g - palette[i].g;
db = pixel.b - palette[i].b;
distance = dr * dr + dg * dg + db * db;
if (distance < minDistance) {
minDistance = distance;
closestColor = i;
}
}
return closestColor;
}
/*********************************************
* Description - Main
* Author - Vilyaem
* Date - May 03 2024
* *******************************************/
int main(int argc, char* argv[]) {
uint32_t width;
uint32_t height;
FILE* output;
FILE* input;
char magic[8];
Color prevPixel = {0,0,0};
uint8_t colorCount;
if (argc != 3) {
printf("Usage: %s input_image.farbfeld output_image.rle\n", argv[0]);
return 1;
}
input = fopen(argv[1], "rb");
if (!input) {
puts("Error: Unable to open input file.\n");
return 1;
}
/*Reading header*/
fread(magic, 1, 8, input);
/*Forced width and height*/
width = MAXRES;
height = MAXRES;
/*Output the RLE header*/
output = fopen(argv[2], "wb");
fputc('V', output); /* Magic number*/
fputc(width / 8, output); /* Actual width*/
fputc(height / 8, output); /* Actual height*/
/*Read and convert each pixel*/
colorCount = 1;
for (i = 0; i < (int)width * (int)height; i++) {
uint16_t rgba[4];
uint8_t currentColor;
Color pixel;
fread(rgba, sizeof(uint16_t), 4, input);
/*pixel = (Color){rgba[0] >> 8, rgba[1] >> 8, rgba[2] >> 8};*/
pixel.r = rgba[0] >> 8;
pixel.g = rgba[1] >> 8;
pixel.b = rgba[2] >> 8;
currentColor = findClosestColor(pixel);
if (currentColor == findClosestColor(prevPixel) && colorCount < 64) { /*dont make V and A characters and break files!*/
colorCount++;
} else {
fputc(findClosestColor(prevPixel), output);
fputc(colorCount, output);
prevPixel = pixel;
colorCount = 1;
}
}
/*Output the last color run*/
if (colorCount > 0) {
fputc(findClosestColor(prevPixel), output);
fputc(colorCount, output);
}
fclose(input);
fclose(output);
puts("Conversion complete.\n");
return 0;
}

21
programs/vnmbeat.c ノーマルファイル
ファイルの表示

@ -0,0 +1,21 @@
/*********************************************
* Description - VNMBeat, example program
* that generates a sound in VNM
*
* ./vnmbeat > vnmbeat.vnm
*
* Author - Vilyaem
* Date - Apr 28 2024
* *******************************************/
#include <stdio.h>
int main(void){
int i;
putchar('A');
for ( i = 0; i < 1000000; i++)
putchar(
( (i * i ^ i) | ((i % 73) * i*8 & i >> 24)) /*play with this to make music*/
);
return 0;
}

30
programs/vnmcarr.c ノーマルファイル
ファイルの表示

@ -0,0 +1,30 @@
/*********************************************
* Description - Convert VNM files to C arrays
* Author - Vilyaem
* Date - May 03 2024
* *******************************************/
/*----------PREPROCESSOR----------*/
#include <stdio.h>
/*----------FUNCTIONS----------*/
/*********************************************
* Description - Main
* Author - Vilyaem
* Date - May 03 2024
* *******************************************/
int main(void){
int c;
puts("/* Generated by VNMCARR */\nuint8_t vnm[] = {");
while((c = fgetc(stdin)) != EOF){
if(c % 2 == 0){ /*Avoid the last indice having a comma*/
printf(",%d",c);
}
else{
printf("%d",c);
}
}
puts("\n};");
return 0;
}

27
programs/vnmnoise.c ノーマルファイル
ファイルの表示

@ -0,0 +1,27 @@
/*********************************************
* Description - Example VNM noise generator
* THis does no attempt to make the output tiny,
* this is a demonstration on how easy it is to produce
* vnm files.
*
* ./vnmnoise > noise.vnm
*
* Author - Vilyaem
* Date - Apr 26 2024
* *******************************************/
#include <stdio.h>
#include <stdlib.h>
#define RES 1024 /*Our resolution*/
int main(void){
int i;
putchar('V');
putchar(RES/8);
for(i = 0; i != RES*RES;i++){
putchar(1);
putchar(i%rand());
}
return 0;
}

27
programs/vnmopt.c ノーマルファイル
ファイルの表示

@ -0,0 +1,27 @@
/*********************************************
* Description - VNM Image optimizer
* Author - Vilyaem
* Date - May 03 2024
* *******************************************/
/*----------PREPROCESSOR----------*/
#include <stdio.h>
/*----------FUNCTIONS----------*/
/*********************************************
* Description - Main
* Author - Vilyaem
* Date - May 03 2024
* *******************************************/
int main(void){
int c;
int curcolour = 0;
while((c = fgetc(stdin)) != EOF){
if(c - 1 % 2 == 0){ /*it's run length*/
}
else { /*it's a colour*/
curcolour = c;
}
}
}

75
programs/vnmstat.c ノーマルファイル
ファイルの表示

@ -0,0 +1,75 @@
/*********************************************
* Description - VNM Stat, report and identify on VNM
* files
*
* < file.vnm | ./vnmstat
*
* Author - Vilyaem
* Date - Apr 26 2024
* *******************************************/
/*----------PREPROCESSOR----------*/
#include <stdio.h>
#include <stdlib.h>
#define IMG 0
#define AUD 1
#define VID 2
/*----------GLOBALS----------*/
int c;
int charcnt = 0;
int framecnt = 0;
int mode = -1;
int res = 0;
/*----------FUNCTIONS----------*/
/*********************************************
* Description - Main
* Author - Vilyaem
* Date - Apr 26 2024
* *******************************************/
int main(void){
/*Recieve file via STDIN*/
while(c != EOF){
c = fgetc(stdin);
/*Determine the type of file*/
if(charcnt == 0 && c == 'V'){
mode = IMG;
}
else if(charcnt == 0 && c == 'A'){
mode = AUD;
}
/*Determine if the image is actually a video*/
if((mode == IMG && charcnt != 0) && (c == 'V' || c == 'A')){
mode = VID;
framecnt = 1; /*(counting the first one)*/
}
/*Determine resolution*/
if(mode == IMG && charcnt == 1){
res = c * 8;
}
/*Count up frames*/
if(mode == VID && c == 'V'){
framecnt++;
}
charcnt++;
}
/*Print the results*/
puts("---VNM STATS---");
switch(mode){
case IMG: printf("This is an image, it has %d bytes of data, the resolution is %d.\n",charcnt,res); break;
case AUD: printf("This is an audio file, it has %d bytes of data.\n",charcnt); break;
case VID: printf("This is a video, it has %d bytes of data, it has %d frames, the resolution is %d.\n",charcnt,framecnt,res); break;
default:puts("error: bad file");break;
}
return 0;
}

4
scripts/png2vnm.sh 実行可能ファイル
ファイルの表示

@ -0,0 +1,4 @@
#!/bin/sh
png2ff < "$1" > "$1.png"
cat "$1.png" | ff2.vnm > "$1.vnm"
rm "$1.png"

20
scripts/vid2vnm.sh 実行可能ファイル
ファイルの表示

@ -0,0 +1,20 @@
#!/bin/sh
clear
input_video="$1"
rm result.vnm
## Convert video to PNG frames at 30 FPS
ffmpeg -r 30 -i "$input_video" frame-%04d.png
ls
## Process the frames into farbfeld format with ff2png
find -type f . -name "*.png" -exec cat {} | ff2png >> {}.ff \;
ls
## Process the farbfeld images to VNM images
find -type f . -name "*.png.ff" -exec ff2vnm {} {}.vnm \;
ls
## Extract audio from video to an 8000hz WAV file
ffmpeg -ar 8000 -ac 1 -i "$input_video" AUDIO.raw
cat *.vnm > result.vnm
echo "A" >> result.vnm
cat AUDIO.wav >> result.vnm
rm frame*
rm AUDIO.wav