API: moved functions to files to make it easier to import to other projects

This commit is contained in:
Andrew Haynes
2026-03-22 17:24:40 -04:00
parent 05a15d38af
commit 64cf77bbe3
11 changed files with 678 additions and 572 deletions
+208
View File
@@ -0,0 +1,208 @@
#include "imgio.h"
#include <stdio.h>
#include <stdlib.h>
#include <turbojpeg.h>
unsigned int*
ppm_load(const char* file, PPM* m_attr)
{
printf("Starting decode...\n");
unsigned char red;
unsigned char green;
unsigned char blue;
char fmt[3];
int max_val;
FILE* fptr;
fptr = fopen(file, "r");
if (!fptr)
{
printf("Invalid file name: %s\n", file);
return NULL;
}
fscanf(fptr, "%s", fmt);
m_attr->fmt = fmt[1];
fscanf(fptr, "%d %d", &m_attr->width, &m_attr->height);
m_attr->len = m_attr->width * m_attr->height;
fscanf(fptr, "%d", &max_val);
fgetc(fptr);
unsigned char* img_buf = malloc(m_attr->len * 3);
if (!img_buf)
{
return NULL;
}
unsigned int* clr_buf = malloc(m_attr->len * sizeof(unsigned int));
if (!clr_buf)
{
free(img_buf);
return NULL;
}
if (m_attr->fmt == '3')
{
for (int i = 0; i < m_attr->len; i++)
{
fscanf(fptr, "%hhu %hhu %hhu", &red, &green, &blue);
clr_buf[i] = ENCODE_RGB(red, green, blue);
}
}
else if (m_attr->fmt == '6')
{
fread(img_buf, 3, m_attr->len, fptr);
for (int i = 0; i < m_attr->len; i++)
{
red = img_buf[i * 3];
green = img_buf[i * 3 + 1];
blue = img_buf[i * 3 + 2];
clr_buf[i] = ENCODE_RGB(red, green, blue);
}
}
fclose(fptr);
free(img_buf);
printf("Decoding done!\n");
return clr_buf;
}
int
ppm_save(const unsigned int* buf, const PPM img)
{
if (!buf)
{
return 0;
}
unsigned char red, green, blue;
unsigned char* dst_buf = malloc(img.len * 3);
if (!dst_buf)
{
return 0;
}
printf("Starting encode...\n");
FILE* fptr;
if (img.fmt == '3')
{
fptr = fopen(img.name, "w");
}
if (img.fmt == '6')
{
fptr = fopen(img.name, "wb");
}
if (!fptr)
{
free(dst_buf);
return 0;
}
fprintf(fptr, "P%c\n%d %d\n255\n", img.fmt, img.width, img.height);
if (img.fmt == '3')
{
for (int i = 0; i < img.len; i++)
{
red = DECODE_R(buf[i]);
green = DECODE_G(buf[i]);
blue = DECODE_B(buf[i]);
fprintf(fptr, "%d %d %d ", red, green, blue);
if (i % 7 == 0)
{
fprintf(fptr, "\n");
}
}
}
if (img.fmt == '6')
{
for (int i = 0; i < img.len; i++)
{
dst_buf[i * 3] = DECODE_R(buf[i]);
dst_buf[i * 3 + 1] = DECODE_G(buf[i]);
dst_buf[i * 3 + 2] = DECODE_B(buf[i]);
}
fwrite(dst_buf, 1, img.len * 3, fptr);
}
fclose(fptr);
free(dst_buf);
printf("Encode Done!\n");
return 1;
}
unsigned int*
jpeg_load(JPEG* m_attr)
{
printf("Starting Decode...\n");
tjhandle tjdecompress = tj3Init(TJINIT_DECOMPRESS);
unsigned char* jpeg_buf = NULL;
FILE* infile = fopen(m_attr->name, "rb");
if (!infile)
{
return NULL;
}
fseek(infile, 0, SEEK_END);
m_attr->len = ftell(infile);
fseek(infile, 0, SEEK_SET);
jpeg_buf = (unsigned char*)malloc(m_attr->len);
fread(jpeg_buf, 1, m_attr->len, infile);
fclose(infile);
if (tj3DecompressHeader(tjdecompress, jpeg_buf, m_attr->len) < 0)
{
printf("Header error: %s\n", tj3GetErrorStr(tjdecompress));
free(jpeg_buf);
return NULL;
}
m_attr->width = tj3Get(tjdecompress, TJPARAM_JPEGWIDTH);
m_attr->height = tj3Get(tjdecompress, TJPARAM_JPEGHEIGHT);
unsigned int* pixels =
malloc(m_attr->width * m_attr->height * sizeof(unsigned int));
tj3Decompress8(tjdecompress, jpeg_buf, m_attr->len,
(unsigned char*)pixels, 0, TJPF_BGRA);
tj3Destroy(tjdecompress);
free(jpeg_buf);
printf("Decode Successful!\n");
return pixels;
}
int
jpeg_save(const unsigned int* src_buf, const JPEG* attr, const char* name)
{
printf("Starting Decode...\n");
tjhandle tjcompress = tj3Init(TJINIT_COMPRESS);
unsigned char* dst_buf = NULL;
size_t dst_size = 0;
tj3Set(tjcompress, TJPARAM_QUALITY, 80);
tj3Set(tjcompress, TJPARAM_SUBSAMP, TJSAMP_420);
if (tj3Compress8(tjcompress, (unsigned char*)src_buf, attr->width, 0,
attr->height, TJPF_BGRA, &dst_buf, &dst_size) < 0)
{
printf("TurboJPEG Error: %s\n", tj3GetErrorStr(tjcompress));
}
FILE* fptr = fopen(name, "wb");
if (!fptr || dst_buf == NULL || dst_size <= 0)
{
tj3Free(dst_buf);
return 0;
}
fwrite(dst_buf, 1, dst_size, fptr);
fclose(fptr);
tj3Destroy(tjcompress);
tj3Free(dst_buf);
printf("Encode Successful!\n");
return 1;
}
void
ppm_to_jpeg(PPM* in, JPEG* out)
{
unsigned int* src_buf = ppm_load(in->name, in);
out->width = in->width;
out->height = in->height;
jpeg_save(src_buf, out, out->name);
}
void
jpeg_to_ppm(JPEG* input, PPM* out)
{
unsigned int* src_buf = jpeg_load(input);
out->width = input->width;
out->height = input->height;
out->len = out->width * out->height;
ppm_save(src_buf, *out);
}