chore: initial commit

This commit is contained in:
Théo LUDWIG 2023-12-04 23:27:48 +01:00
commit f5949f9d44
Signed by: theoludwig
GPG Key ID: ADFE5A563D718F3B
9 changed files with 264 additions and 0 deletions

2
.clang-format Normal file
View File

@ -0,0 +1,2 @@
BasedOnStyle: "Google"
ColumnLimit: 0

4
.gitignore vendored Executable file
View File

@ -0,0 +1,4 @@
libcproject
assets
build
bin

32
Makefile Executable file
View File

@ -0,0 +1,32 @@
CC = gcc
CC_FLAGS = -Wall -Wextra -Wfloat-equal -Wundef -Werror -std=c17 -pedantic -pedantic-errors -O3 -I./
CC_SANITIZER_FLAGS = -fsanitize=address -fsanitize=undefined
LIB_SOURCES = $(wildcard lib/*.c)
LIB_OBJECTS = $(patsubst %.c, %.o, $(LIB_SOURCES))
HEADER_FILES = $(wildcard lib/*.h)
MAIN_EXECUTABLE = bin/main
LIBCPROJECT_PATH = ./libcproject/build/libcproject.a
LIBCPROJECT_CC_FLAGS = -L. -l:${LIBCPROJECT_PATH}
${MAIN_EXECUTABLE}: ./main.c ${HEADER_FILES} $(addprefix build/, ${LIB_OBJECTS}) ${LIBCPROJECT_PATH}
mkdir --parents ./bin
mkdir --parents ./assets
${CC} ${CC_FLAGS} ${CC_SANITIZER_FLAGS} $^ -o $@ ${LIBCPROJECT_CC_FLAGS}
.PHONY: run
run: ${MAIN_EXECUTABLE}
./$< ${ARGS}
build/lib:
mkdir --parents ./build/lib
build/lib/%.o: lib/%.c ${HEADER_FILES} | build/lib
${CC} ${CC_FLAGS} -c $< -o $@
.PHONY: lint
lint:
clang-format --Werror --dry-run ${LIB_SOURCES} ${HEADER_FILES} ./main.c
.PHONY: clean
clean:
rm --recursive --force ./bin ./build ./assets

16
README.md Executable file
View File

@ -0,0 +1,16 @@
# fileformatsproject
It needs [libcproject v4.1.1](https://github.com/theoludwig/libcproject/releases/tag/v4.1.1) static library to compile and execute.
```sh
make # to compile
make run # to run main
make lint # to lint the code
make clean # to clean up
```
## Ideas/TODOs
- [ ] Make functions `image_from_ppm_binary`, `image_from_ppm_text`, which receive `bytes_t*` and convert accordingly to `struct image*`
- [ ] Try to convert PPM to another format more famous (JPG, PNG, GIF, WEBP) and vice-versa
- [ ] Explore other file formats (not only images, but also audio, video, etc.)

33
lib/image.c Normal file
View File

@ -0,0 +1,33 @@
#include "image.h"
struct image* image_initialization(size_t width, size_t height) {
struct image* image = malloc(sizeof(struct image));
if (image == NULL) {
perror("Error (image_initialization)");
exit(EXIT_FAILURE);
}
image->height = height;
image->width = width;
image->pixels = malloc(sizeof(struct pixel*) * image->height);
for (size_t row = 0; row < image->height; row++) {
image->pixels[row] = malloc(sizeof(struct pixel) * image->width);
for (size_t column = 0; column < image->width; column++) {
image->pixels[row][column].red = 0;
image->pixels[row][column].green = 0;
image->pixels[row][column].blue = 0;
}
}
return image;
}
void image_free(struct image* image) {
if (image == NULL) {
perror("Error (image_free)");
exit(EXIT_FAILURE);
}
for (size_t row = 0; row < image->height; row++) {
free(image->pixels[row]);
}
free(image->pixels);
free(image);
}

33
lib/image.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef __IMAGE__
#define __IMAGE__
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "../libcproject/libcproject.h"
struct pixel {
byte_t red;
byte_t green;
byte_t blue;
};
struct image {
struct pixel** pixels;
size_t width;
size_t height;
};
/**
* @brief Initializes a new image (with all colors defaulting to 0 => black).
*
* @param width
* @param height
* @return struct image*
*/
struct image* image_initialization(size_t width, size_t height);
void image_free(struct image* image);
#endif

69
lib/image_ppm.c Normal file
View File

@ -0,0 +1,69 @@
#include "image_ppm.h"
byte_t* image_to_ppm_text(struct image* image, off_t* size) {
if (image == NULL || image->pixels == NULL || image->width == 0 || image->height == 0) {
errno = EINVAL;
perror("Error (image_to_ppm_text)");
exit(EXIT_FAILURE);
}
string_t width = convert_number_to_string(image->width);
string_t height = convert_number_to_string(image->height);
string_t result = string_copy("P3\n");
string_concatenate(&result, width);
free(width);
string_concatenate(&result, " ");
string_concatenate(&result, height);
free(height);
string_concatenate(&result, "\n255\n");
for (size_t row = 0; row < image->height; row++) {
for (size_t column = 0; column < image->width; column++) {
struct pixel current_pixel = image->pixels[row][column];
string_t red = convert_number_to_string(current_pixel.red);
string_t green = convert_number_to_string(current_pixel.green);
string_t blue = convert_number_to_string(current_pixel.blue);
string_concatenate(&result, red);
free(red);
string_concatenate(&result, " ");
string_concatenate(&result, green);
free(green);
string_concatenate(&result, " ");
string_concatenate(&result, blue);
free(blue);
string_concatenate(&result, " ");
}
string_concatenate(&result, "\n");
}
(*size) = string_get_length(result);
return (byte_t*)result;
}
byte_t* image_to_ppm_binary(struct image* image, off_t* size) {
if (image == NULL || image->pixels == NULL || image->width == 0 || image->height == 0) {
errno = EINVAL;
perror("Error (image_to_ppm_binary)");
exit(EXIT_FAILURE);
}
size_t pixel_data_size = (image->width * image->height * 3);
string_t width = convert_number_to_string(image->width);
string_t height = convert_number_to_string(image->height);
size_t header_size = 14 + string_get_length(width) + string_get_length(height);
(*size) = header_size + pixel_data_size;
byte_t* result = (byte_t*)malloc(*size);
if (result == NULL) {
perror("Error (image_to_ppm_binary)");
exit(EXIT_FAILURE);
}
byte_t* pixel_data_start = result;
pixel_data_start += sprintf((string_t)pixel_data_start, "P6\n%s\n%s\n255\n", width, height);
free(width);
free(height);
for (size_t row = 0; row < image->height; row++) {
for (size_t column = 0; column < image->width; column++) {
struct pixel current_pixel = image->pixels[row][column];
*pixel_data_start++ = current_pixel.red;
*pixel_data_start++ = current_pixel.green;
*pixel_data_start++ = current_pixel.blue;
}
}
return result;
}

23
lib/image_ppm.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef __IMAGE_PPM__
#define __IMAGE_PPM__
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "../libcproject/libcproject.h"
#include "image.h"
/**
* @brief Convert image to PPM (Portable PixMap format) defined by the Netpbm project (Plain/Raw text ASCII format).
* @see https://netpbm.sourceforge.net/doc/ppm.html
*/
byte_t* image_to_ppm_text(struct image* image, off_t* size);
/**
* @brief Convert image to PPM (Portable PixMap format) defined by the Netpbm project (binary format).
* @see https://netpbm.sourceforge.net/doc/ppm.html
*/
byte_t* image_to_ppm_binary(struct image* image, off_t* size);
#endif

52
main.c Executable file
View File

@ -0,0 +1,52 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "lib/image.h"
#include "lib/image_ppm.h"
#include "libcproject/libcproject.h"
int main() {
printf("Generating images...\n");
size_t images_count = 0;
for (size_t red = 0; red < 256; red += 51) {
for (size_t green = 0; green < 256; green += 51) {
for (size_t blue = 0; blue < 256; blue += 51) {
struct image* image = image_initialization(100, 100);
for (size_t row = 0; row < image->height; row++) {
for (size_t column = 0; column < image->width; column++) {
image->pixels[row][column].red = red;
image->pixels[row][column].green = green;
image->pixels[row][column].blue = blue;
}
}
string_t red_string = convert_number_to_string((long long)red);
string_t green_string = convert_number_to_string((long long)green);
string_t blue_string = convert_number_to_string((long long)blue);
string_t path = string_copy("./assets/");
string_concatenate(&path, "image-red-");
string_concatenate(&path, red_string);
string_concatenate(&path, "-green-");
string_concatenate(&path, green_string);
string_concatenate(&path, "-blue-");
string_concatenate(&path, blue_string);
string_concatenate(&path, ".ppm");
free(red_string);
free(green_string);
free(blue_string);
off_t file_size = 0;
byte_t* image_ppm = image_to_ppm_binary(image, &file_size);
filesystem_write(path, image_ppm, file_size);
images_count += 1;
image_free(image);
free(path);
free(image_ppm);
}
}
}
printf("Generated %zu images in `./assets`.\n", images_count);
return EXIT_SUCCESS;
}