vnm/programs/ff2vnm.c

157 行
3.9 KiB
C
Raw 通常表示 履歴

2024-05-13 21:28:48 +09:00
/*********************************************
* 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;
}