146 lines
3.6 KiB
C
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);
|
|
}
|