chore: initial commit
This commit is contained in:
commit
f5949f9d44
2
.clang-format
Normal file
2
.clang-format
Normal file
@ -0,0 +1,2 @@
|
||||
BasedOnStyle: "Google"
|
||||
ColumnLimit: 0
|
4
.gitignore
vendored
Executable file
4
.gitignore
vendored
Executable file
@ -0,0 +1,4 @@
|
||||
libcproject
|
||||
assets
|
||||
build
|
||||
bin
|
32
Makefile
Executable file
32
Makefile
Executable 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
16
README.md
Executable 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
33
lib/image.c
Normal 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
33
lib/image.h
Normal 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
69
lib/image_ppm.c
Normal 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
23
lib/image_ppm.h
Normal 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
52
main.c
Executable 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user