ciffcaff/ciff.c
Balazs Toldi 79487c849e
Changes based on response
Signed-off-by: Balazs Toldi <balazs@toldi.eu>
2023-05-29 20:04:16 +02:00

146 lines
3.6 KiB
C

#include "ciff.h"
#include <stdio.h>
#include <jpeglib.h>
#include <stdlib.h>
#include <string.h>
CIFF *read_ciff(FILE *file)
{
if (!file)
{
printf("Failed to open file!\n");
return NULL;
}
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, 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)
{
printf("File is not a CIFF file\n");
free(ciff);
fclose(file);
return NULL;
}
// Read the caption
ciff->caption = malloc(ciff->header_size); // overestimate the size
if (!ciff->caption)
{
printf("Failed to allocate memory for caption\n");
free(ciff);
fclose(file);
return NULL;
}
char c;
size_t i = 0;
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;
// 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)
{
printf("Failed to allocate memory for tags\n");
free(ciff->caption);
free(ciff);
fclose(file);
return NULL;
}
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)
{
printf("Failed to allocate memory for pixel data\n");
free(ciff->caption);
free(ciff);
fclose(file);
return NULL;
}
fread(ciff->pixels, ciff->content_size, 1, file);
return ciff;
}
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)
{
printf("Failed to open output file: %s\n", out_filename);
return;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, outfile);
cinfo.image_width = ciff->width;
cinfo.image_height = ciff->height;
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);
jpeg_start_compress(&cinfo, TRUE);
JSAMPROW row_pointer[1];
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);
}
jpeg_finish_compress(&cinfo);
fclose(outfile);
jpeg_destroy_compress(&cinfo);
}
void free_ciff(CIFF *ciff)
{
free(ciff->caption);
free(ciff->pixels);
free(ciff->tags);
free(ciff);
}