Changes based on response
Signed-off-by: Balazs Toldi <balazs@toldi.eu>
This commit is contained in:
parent
053ba8d04f
commit
79487c849e
4 changed files with 166 additions and 124 deletions
210
caff.c
210
caff.c
|
@ -1,128 +1,146 @@
|
|||
#include "caff.h"
|
||||
#include <webp/encode.h>
|
||||
|
||||
void print_credits(CAFF_Credits* credits){
|
||||
printf("Creator:%s\n",credits->creator);
|
||||
printf("Date:%d.%d.%d %d:%d\n",credits->year,credits->month,credits->day,credits->hour,credits->minute);
|
||||
void print_credits(CAFF_Credits *credits)
|
||||
{
|
||||
printf("Creator:%s\n", credits->creator);
|
||||
printf("Date:%d.%d.%d %d:%d\n", credits->year, credits->month, credits->day, credits->hour, credits->minute);
|
||||
}
|
||||
|
||||
|
||||
void caff_init_animation_list(CAFF_Animation_List *a) {
|
||||
a->array = NULL;
|
||||
a->length = 0;
|
||||
a->size = 0;
|
||||
void caff_init_animation_list(CAFF_Animation_List *a)
|
||||
{
|
||||
a->array = NULL;
|
||||
a->length = 0;
|
||||
a->size = 0;
|
||||
}
|
||||
|
||||
void caff_add_animation_list(CAFF_Animation_List *a, CAFF_Animation element) {
|
||||
if (a->length == a->size) {
|
||||
a->size =(a->size == 0) ? 1 : a->size*2;
|
||||
CAFF_Animation* new_array = realloc(a->array, a->size * sizeof(CAFF_Animation));
|
||||
if(!new_array){
|
||||
printf("Failed to allocate memory!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
void caff_add_animation_list(CAFF_Animation_List *a, CAFF_Animation element)
|
||||
{
|
||||
if (a->length == a->size)
|
||||
{
|
||||
a->size = (a->size == 0) ? 1 : a->size * 2;
|
||||
CAFF_Animation *new_array = realloc(a->array, a->size * sizeof(CAFF_Animation));
|
||||
if (!new_array)
|
||||
{
|
||||
printf("Failed to allocate memory!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
a->array = new_array;
|
||||
}
|
||||
a->array = new_array;
|
||||
}
|
||||
a->array[a->length++] = element;
|
||||
a->array[a->length++] = element;
|
||||
}
|
||||
|
||||
void caff_free_animtion_list(CAFF_Animation_List *a) {
|
||||
free(a->array);
|
||||
a->array = NULL;
|
||||
a->length = a->size = 0;
|
||||
void caff_free_animtion_list(CAFF_Animation_List *a)
|
||||
{
|
||||
free(a->array);
|
||||
a->array = NULL;
|
||||
a->length = a->size = 0;
|
||||
}
|
||||
|
||||
CAFF* caff_parse_file(const char* filename) {
|
||||
FILE* file = fopen(filename, "rb");
|
||||
if (!file) {
|
||||
CAFF *caff_parse_file(const char *filename)
|
||||
{
|
||||
FILE *file = fopen(filename, "rb");
|
||||
if (!file)
|
||||
{
|
||||
printf("Failed to open CAFF file: %s\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CAFF* caff = malloc(sizeof(CAFF));
|
||||
if(!caff){
|
||||
CAFF *caff = malloc(sizeof(CAFF));
|
||||
if (!caff)
|
||||
{
|
||||
printf("Failed to allocate memory for CAFF!\n");
|
||||
return NULL;
|
||||
}
|
||||
caff->bytes_read = 0;
|
||||
caff->credits = NULL;
|
||||
caff->header = NULL;
|
||||
caff_init_animation_list(&caff->animations);
|
||||
|
||||
|
||||
size_t anim_count = 0;
|
||||
while (!feof(file)) {
|
||||
while (!feof(file))
|
||||
{
|
||||
uint8_t id;
|
||||
uint64_t length;
|
||||
fread(&id, 1, 1, file);
|
||||
fread(&length, 8, 1, file);
|
||||
fread(&id, sizeof(uint8_t), 1, file);
|
||||
fread(&length, sizeof(uint64_t), 1, file);
|
||||
|
||||
switch (id) {
|
||||
case 0x1:
|
||||
// Do not replace the header after it is initialized
|
||||
if(!caff->header)
|
||||
switch (id)
|
||||
{
|
||||
case 0x1:
|
||||
// Do not replace the header after it is initialized
|
||||
if (!caff->header)
|
||||
caff->header = read_header(file);
|
||||
break;
|
||||
case 0x2:
|
||||
// Do not replace the credits after it is initialized
|
||||
if(!caff->credits)
|
||||
break;
|
||||
case 0x2:
|
||||
// Do not replace the credits after it is initialized
|
||||
if (!caff->credits)
|
||||
caff->credits = read_credits(file);
|
||||
print_credits(caff->credits );
|
||||
break;
|
||||
case 0x3:
|
||||
anim_count++;
|
||||
if(caff->header && caff->header->num_anim == anim_count){
|
||||
goto end;
|
||||
}
|
||||
// You might want to append to a list of animations here.
|
||||
CAFF_Animation* anim = read_animation(file);
|
||||
|
||||
caff_add_animation_list(&caff->animations,*anim);
|
||||
free(anim);
|
||||
// We only need the first image now...
|
||||
goto end;
|
||||
break;
|
||||
default:
|
||||
// Random bytes should not cause an error
|
||||
printf("Unknown block ID: %u\n", id);
|
||||
goto end;
|
||||
print_credits(caff->credits);
|
||||
break;
|
||||
case 0x3:
|
||||
anim_count++;
|
||||
if (caff->header && caff->header->num_anim == anim_count)
|
||||
{
|
||||
fclose(file);
|
||||
return caff;
|
||||
}
|
||||
// You might want to append to a list of animations here.
|
||||
CAFF_Animation *anim = read_animation(file);
|
||||
|
||||
caff_add_animation_list(&caff->animations, *anim);
|
||||
free(anim);
|
||||
// We only need the first image now...
|
||||
fclose(file);
|
||||
return caff;
|
||||
default:
|
||||
// Random bytes should not cause an error
|
||||
printf("Unknown block ID: %u\n", id);
|
||||
fclose(file);
|
||||
return caff;
|
||||
}
|
||||
}
|
||||
end:
|
||||
|
||||
|
||||
fclose(file);
|
||||
printf("Parse END!\n");
|
||||
return caff;
|
||||
}
|
||||
|
||||
CAFF_Header* read_header(FILE* file) {
|
||||
CAFF_Header* header = malloc(sizeof(CAFF_Header));
|
||||
if (!header) {
|
||||
CAFF_Header *read_header(FILE *file)
|
||||
{
|
||||
CAFF_Header *header = malloc(sizeof(CAFF_Header));
|
||||
if (!header)
|
||||
{
|
||||
printf("Failed to allocate memory for CAFF header\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read the magic string.
|
||||
if (fread(header->magic, 1, 4, file) != 4) {
|
||||
if (fread(header->magic, sizeof(char), 4, file) != 4)
|
||||
{
|
||||
printf("Failed to read magic string from CAFF header\n");
|
||||
free(header);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check the magic string.
|
||||
if (strncmp(header->magic, "CAFF", 4) != 0) {
|
||||
if (strncmp(header->magic, "CAFF", 4) != 0)
|
||||
{
|
||||
printf("Invalid magic string in CAFF header\n");
|
||||
free(header);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read the header size.
|
||||
if (fread(&header->header_size, 8, 1, file) != 1) {
|
||||
if (fread(&header->header_size, sizeof(uint64_t), 1, file) != 1)
|
||||
{
|
||||
printf("Failed to read header size from CAFF header\n");
|
||||
free(header);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read the number of animations.
|
||||
if (fread(&header->num_anim, 8, 1, file) != 1) {
|
||||
if (fread(&header->num_anim, sizeof(uint64_t), 1, file) != 1)
|
||||
{
|
||||
printf("Failed to read number of animations from CAFF header\n");
|
||||
free(header);
|
||||
return NULL;
|
||||
|
@ -131,27 +149,30 @@ CAFF_Header* read_header(FILE* file) {
|
|||
return header;
|
||||
}
|
||||
|
||||
|
||||
CAFF_Credits* read_credits(FILE* file) {
|
||||
CAFF_Credits* credits = malloc(sizeof(CAFF_Credits));
|
||||
if (!credits) {
|
||||
CAFF_Credits *read_credits(FILE *file)
|
||||
{
|
||||
CAFF_Credits *credits = malloc(sizeof(CAFF_Credits));
|
||||
if (!credits)
|
||||
{
|
||||
printf("Failed to allocate memory for CAFF credits\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read the creation date and time.
|
||||
if (fread(&credits->year, 2, 1, file) != 1 ||
|
||||
fread(&credits->month, 1, 1, file) != 1 ||
|
||||
fread(&credits->day, 1, 1, file) != 1 ||
|
||||
fread(&credits->hour, 1, 1, file) != 1 ||
|
||||
fread(&credits->minute, 1, 1, file) != 1) {
|
||||
if (fread(&credits->year, sizeof(uint16_t), 1, file) != 1 ||
|
||||
fread(&credits->month, sizeof(uint8_t), 1, file) != 1 ||
|
||||
fread(&credits->day, sizeof(uint8_t), 1, file) != 1 ||
|
||||
fread(&credits->hour, sizeof(uint8_t), 1, file) != 1 ||
|
||||
fread(&credits->minute, sizeof(uint8_t), 1, file) != 1)
|
||||
{
|
||||
printf("Failed to read creation date and time from CAFF credits\n");
|
||||
free(credits);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read the length of the creator field.
|
||||
if (fread(&credits->creator_len, 8, 1, file) != 1) {
|
||||
if (fread(&credits->creator_len, sizeof(uint64_t), 1, file) != 1)
|
||||
{
|
||||
printf("Failed to read length of creator field from CAFF credits\n");
|
||||
free(credits);
|
||||
return NULL;
|
||||
|
@ -159,14 +180,16 @@ CAFF_Credits* read_credits(FILE* file) {
|
|||
|
||||
// Allocate memory for the creator field.
|
||||
credits->creator = malloc(credits->creator_len + 1);
|
||||
if (!credits->creator) {
|
||||
if (!credits->creator)
|
||||
{
|
||||
printf("Failed to allocate memory for creator field in CAFF credits\n");
|
||||
free(credits);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read the creator field.
|
||||
if (fread(credits->creator, 1, credits->creator_len, file) != credits->creator_len) {
|
||||
if (fread(credits->creator, 1, credits->creator_len, file) != credits->creator_len)
|
||||
{
|
||||
printf("Failed to read creator field from CAFF credits\n");
|
||||
free(credits->creator);
|
||||
free(credits);
|
||||
|
@ -179,16 +202,18 @@ CAFF_Credits* read_credits(FILE* file) {
|
|||
return credits;
|
||||
}
|
||||
|
||||
|
||||
CAFF_Animation* read_animation(FILE* file) {
|
||||
CAFF_Animation* animation = malloc(sizeof(CAFF_Animation));
|
||||
if (!animation) {
|
||||
CAFF_Animation *read_animation(FILE *file)
|
||||
{
|
||||
CAFF_Animation *animation = malloc(sizeof(CAFF_Animation));
|
||||
if (!animation)
|
||||
{
|
||||
printf("Failed to allocate memory for CAFF animation\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read the duration.
|
||||
if (fread(&animation->duration, 8, 1, file) != 1) {
|
||||
if (fread(&animation->duration, sizeof(uint64_t), 1, file) != 1)
|
||||
{
|
||||
printf("Failed to read duration from CAFF animation\n");
|
||||
free(animation);
|
||||
return NULL;
|
||||
|
@ -196,7 +221,8 @@ CAFF_Animation* read_animation(FILE* file) {
|
|||
|
||||
// Read the CIFF image.
|
||||
animation->ciff = read_ciff(file);
|
||||
if (!animation->ciff) {
|
||||
if (!animation->ciff)
|
||||
{
|
||||
printf("Failed to read CIFF image from CAFF animation\n");
|
||||
free(animation);
|
||||
return NULL;
|
||||
|
@ -205,21 +231,23 @@ CAFF_Animation* read_animation(FILE* file) {
|
|||
return animation;
|
||||
}
|
||||
|
||||
|
||||
void caff_free(CAFF* caff) {
|
||||
void caff_free(CAFF *caff)
|
||||
{
|
||||
// Free the header
|
||||
free(caff->header);
|
||||
caff->header = NULL;
|
||||
|
||||
// Free the credits
|
||||
if (caff->credits->creator) {
|
||||
if (caff->credits->creator)
|
||||
{
|
||||
free(caff->credits->creator);
|
||||
}
|
||||
free(caff->credits);
|
||||
caff->credits = NULL;
|
||||
|
||||
|
||||
// Free the animations
|
||||
for (size_t i = 0; i < caff->animations.length; i++) {
|
||||
for (size_t i = 0; i < caff->animations.length; i++)
|
||||
{
|
||||
free_ciff(caff->animations.array[i].ciff);
|
||||
}
|
||||
caff_free_animtion_list(&caff->animations);
|
||||
|
|
1
caff.h
1
caff.h
|
@ -36,6 +36,7 @@ typedef struct {
|
|||
CAFF_Header* header; // The CAFF header
|
||||
CAFF_Credits* credits; // The CAFF credits
|
||||
CAFF_Animation_List animations; // The CAFF animations
|
||||
uint64_t bytes_read;
|
||||
} CAFF;
|
||||
CAFF* caff_parse_file(const char* filename);
|
||||
CAFF_Header* read_header(FILE* file);
|
||||
|
|
78
ciff.c
78
ciff.c
|
@ -4,30 +4,38 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
CIFF *read_ciff(FILE *file)
|
||||
{
|
||||
|
||||
CIFF* read_ciff(FILE* file) {
|
||||
|
||||
if (!file) {
|
||||
if (!file)
|
||||
{
|
||||
printf("Failed to open file!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CIFF* ciff = malloc(sizeof(CIFF));
|
||||
if (!ciff) {
|
||||
CIFF *ciff = malloc(sizeof(CIFF));
|
||||
if (!ciff)
|
||||
{
|
||||
printf("Failed to allocate memory for CIFF structure\n");
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read the header
|
||||
fread(ciff->magic, 4, 1, file);
|
||||
fread(&ciff->header_size, 8, 1, file);
|
||||
fread(&ciff->content_size, 8, 1, file);
|
||||
fread(&ciff->width, 8, 1, file);
|
||||
fread(&ciff->height, 8, 1, file);
|
||||
|
||||
fread(ciff->magic, sizeof(uint32_t), 1, file);
|
||||
fread(&ciff->header_size, sizeof(uint64_t), 1, file);
|
||||
fread(&ciff->content_size, sizeof(uint64_t), 1, file);
|
||||
fread(&ciff->width, sizeof(uint64_t), 1, file);
|
||||
fread(&ciff->height, sizeof(uint64_t), 1, file);
|
||||
if (ciff->width * ciff->height*3 < ciff->content_size)
|
||||
{
|
||||
printf("w:%ld h:%ld s:%ld",ciff->width,ciff->height,ciff->content_size);
|
||||
printf("Invalid CIFF size!\n");
|
||||
ciff->content_size = ciff->width * ciff->height*3;
|
||||
}
|
||||
// Ensure the file is actually a CIFF file
|
||||
if (strncmp(ciff->magic, "CIFF", 4) != 0) {
|
||||
if (strncmp(ciff->magic, "CIFF", 4) != 0)
|
||||
{
|
||||
printf("File is not a CIFF file\n");
|
||||
free(ciff);
|
||||
fclose(file);
|
||||
|
@ -36,7 +44,8 @@ CIFF* read_ciff(FILE* file) {
|
|||
|
||||
// Read the caption
|
||||
ciff->caption = malloc(ciff->header_size); // overestimate the size
|
||||
if (!ciff->caption) {
|
||||
if (!ciff->caption)
|
||||
{
|
||||
printf("Failed to allocate memory for caption\n");
|
||||
free(ciff);
|
||||
fclose(file);
|
||||
|
@ -45,34 +54,38 @@ CIFF* read_ciff(FILE* file) {
|
|||
|
||||
char c;
|
||||
size_t i = 0;
|
||||
do {
|
||||
fread(&c, 1, 1, file);
|
||||
do
|
||||
{
|
||||
fread(&c, sizeof(char), 1, file);
|
||||
ciff->caption[i++] = c;
|
||||
} while (c != '\n');
|
||||
ciff->caption[i] = '\0'; // null-terminate the string
|
||||
size_t caption_lenth= i;
|
||||
size_t caption_lenth = i;
|
||||
// Read the tags
|
||||
size_t tags_size = ciff->header_size-sizeof(char)*4-sizeof(uint64_t)*4-caption_lenth; // Size for the rest of the header
|
||||
ciff->tags = malloc(tags_size*sizeof(char));
|
||||
if (!ciff->tags) {
|
||||
size_t tags_size = ciff->header_size - sizeof(char) * 4 - sizeof(uint64_t) * 4 - caption_lenth; // Size for the rest of the header
|
||||
ciff->tags = malloc(tags_size * sizeof(char));
|
||||
if (!ciff->tags)
|
||||
{
|
||||
printf("Failed to allocate memory for tags\n");
|
||||
free(ciff->caption);
|
||||
free(ciff);
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(fread(ciff->tags, tags_size, 1, file) != 1) {
|
||||
|
||||
if (fread(ciff->tags, tags_size, sizeof(uint8_t), file) != 1)
|
||||
{
|
||||
printf("Failed to read tags!\n");
|
||||
free(ciff->caption);
|
||||
free(ciff);
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// Read the pixels
|
||||
ciff->pixels = malloc(ciff->content_size);
|
||||
if (!ciff->pixels) {
|
||||
if (!ciff->pixels)
|
||||
{
|
||||
printf("Failed to allocate memory for pixel data\n");
|
||||
free(ciff->caption);
|
||||
free(ciff);
|
||||
|
@ -81,16 +94,17 @@ CIFF* read_ciff(FILE* file) {
|
|||
}
|
||||
fread(ciff->pixels, ciff->content_size, 1, file);
|
||||
|
||||
|
||||
return ciff;
|
||||
}
|
||||
|
||||
void generate_jpg(CIFF* ciff, const char* out_filename) {
|
||||
void generate_jpg(CIFF *ciff, const char *out_filename)
|
||||
{
|
||||
struct jpeg_compress_struct cinfo;
|
||||
struct jpeg_error_mgr jerr;
|
||||
|
||||
FILE* outfile = fopen(out_filename, "wb");
|
||||
if (!outfile) {
|
||||
FILE *outfile = fopen(out_filename, "wb");
|
||||
if (!outfile)
|
||||
{
|
||||
printf("Failed to open output file: %s\n", out_filename);
|
||||
return;
|
||||
}
|
||||
|
@ -102,7 +116,7 @@ void generate_jpg(CIFF* ciff, const char* out_filename) {
|
|||
|
||||
cinfo.image_width = ciff->width;
|
||||
cinfo.image_height = ciff->height;
|
||||
cinfo.input_components = 3; // number of color components per pixel
|
||||
cinfo.input_components = 3; // number of color components per pixel
|
||||
cinfo.in_color_space = JCS_RGB; // color space of input image
|
||||
|
||||
jpeg_set_defaults(&cinfo);
|
||||
|
@ -110,7 +124,8 @@ void generate_jpg(CIFF* ciff, const char* out_filename) {
|
|||
jpeg_start_compress(&cinfo, TRUE);
|
||||
|
||||
JSAMPROW row_pointer[1];
|
||||
while (cinfo.next_scanline < cinfo.image_height) {
|
||||
while (cinfo.next_scanline < cinfo.image_height)
|
||||
{
|
||||
row_pointer[0] = &ciff->pixels[cinfo.next_scanline * ciff->width * 3];
|
||||
jpeg_write_scanlines(&cinfo, row_pointer, 1);
|
||||
}
|
||||
|
@ -122,9 +137,8 @@ void generate_jpg(CIFF* ciff, const char* out_filename) {
|
|||
jpeg_destroy_compress(&cinfo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void free_ciff(CIFF* ciff) {
|
||||
void free_ciff(CIFF *ciff)
|
||||
{
|
||||
free(ciff->caption);
|
||||
free(ciff->pixels);
|
||||
free(ciff->tags);
|
||||
|
|
1
main.c
1
main.c
|
@ -50,7 +50,6 @@ int main(int argc, char **argv)
|
|||
}
|
||||
else
|
||||
{
|
||||
|
||||
free_ciff(ciff);
|
||||
}
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue