335 lines
6.2 KiB
C
335 lines
6.2 KiB
C
#include "image/imgio.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <turbojpeg.h>
|
|
|
|
#include "image/utils.h"
|
|
|
|
unsigned int*
|
|
read_ppm(const char* file, PPM* m_attr)
|
|
{
|
|
LOG("Decoding");
|
|
unsigned char red, green, blue;
|
|
char fmt[3];
|
|
int max_val;
|
|
FILE* fptr;
|
|
fptr = fopen(file, "r");
|
|
if (!fptr)
|
|
{
|
|
LOGERROR(ERR_IMG_NAME_INVALID);
|
|
LOG(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)
|
|
{
|
|
LOGERROR(ERR_BUF_NULL);
|
|
return NULL;
|
|
}
|
|
unsigned int* clr_buf = malloc(m_attr->len * sizeof(unsigned int));
|
|
if (!clr_buf)
|
|
{
|
|
free(img_buf);
|
|
LOGERROR(ERR_BUF_NULL);
|
|
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);
|
|
LOG("Decoding Finished");
|
|
return clr_buf;
|
|
}
|
|
|
|
int
|
|
write_ppm(const unsigned int* buf, const PPM img, const char* name)
|
|
{
|
|
if (!buf)
|
|
{
|
|
LOGERROR(ERR_BUF_NULL);
|
|
return ERR_BUF_NULL;
|
|
}
|
|
unsigned char* dst_buf = malloc(img.len * 3);
|
|
if (!dst_buf)
|
|
{
|
|
LOGERROR(ERR_BUF_NULL);
|
|
return ERR_BUF_NULL;
|
|
}
|
|
LOG("Encoding");
|
|
FILE* fptr;
|
|
|
|
if (img.fmt == '3')
|
|
{
|
|
fptr = fopen(name, "w");
|
|
}
|
|
|
|
if (img.fmt == '6')
|
|
{
|
|
fptr = fopen(name, "wb");
|
|
}
|
|
|
|
if (!fptr)
|
|
{
|
|
free(dst_buf);
|
|
LOGERROR(ERR_FILE_NULL);
|
|
return ERR_FILE_NULL;
|
|
}
|
|
|
|
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++)
|
|
{
|
|
fprintf(fptr, "%d %d %d ", DECODE_R(buf[i]),
|
|
DECODE_G(buf[i]), DECODE_B(buf[i]));
|
|
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);
|
|
LOG("Encoding Finished");
|
|
return SUCCESS;
|
|
}
|
|
|
|
unsigned int*
|
|
read_jpeg(JPEG* m_attr)
|
|
{
|
|
LOG("Decoding");
|
|
tjhandle tjdecompress = tj3Init(TJINIT_DECOMPRESS);
|
|
unsigned char* jpeg_buf = NULL;
|
|
FILE* infile = fopen(m_attr->name, "rb");
|
|
if (!infile)
|
|
{
|
|
LOGERROR(ERR_FILE_NULL);
|
|
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)
|
|
{
|
|
LOGERROR(ERR_JHEADER);
|
|
LOG(tj3GetErrorStr(tjdecompress));
|
|
free(jpeg_buf);
|
|
return NULL;
|
|
}
|
|
m_attr->width = tj3Get(tjdecompress, TJPARAM_JPEGWIDTH);
|
|
m_attr->height = tj3Get(tjdecompress, TJPARAM_JPEGHEIGHT);
|
|
m_attr->len = m_attr->width * m_attr->height;
|
|
unsigned int* pixels =
|
|
malloc(m_attr->width * m_attr->height * sizeof(unsigned int));
|
|
if (!pixels)
|
|
{
|
|
LOGERROR(ERR_BUF_NULL);
|
|
return NULL;
|
|
}
|
|
tj3Decompress8(tjdecompress, jpeg_buf, m_attr->len,
|
|
(unsigned char*)pixels, 0, TJPF_BGRA);
|
|
tj3Destroy(tjdecompress);
|
|
free(jpeg_buf);
|
|
LOG("Decoding Finished");
|
|
return pixels;
|
|
}
|
|
|
|
int
|
|
write_jpeg(const unsigned int* src_buf, const JPEG* attr, const char* name)
|
|
{
|
|
LOG("Encoding");
|
|
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)
|
|
{
|
|
LOGERROR(ERR_JHEADER);
|
|
LOG(tj3GetErrorStr(tjcompress));
|
|
return ERR_JHEADER;
|
|
}
|
|
FILE* fptr = fopen(name, "wb");
|
|
if (!fptr)
|
|
{
|
|
tj3Free(dst_buf);
|
|
LOGERROR(ERR_FILE_NULL);
|
|
return ERR_FILE_NULL;
|
|
}
|
|
if (dst_buf == NULL)
|
|
{
|
|
tj3Free(dst_buf);
|
|
LOGERROR(ERR_BUF_NULL);
|
|
return ERR_BUF_NULL;
|
|
}
|
|
if (dst_size <= 0)
|
|
{
|
|
tj3Free(dst_buf);
|
|
LOGERROR(ERR_INVALID_SIZE);
|
|
return ERR_INVALID_SIZE;
|
|
}
|
|
fwrite(dst_buf, 1, dst_size, fptr);
|
|
fclose(fptr);
|
|
|
|
tj3Destroy(tjcompress);
|
|
tj3Free(dst_buf);
|
|
LOG("Encoding Finished");
|
|
return SUCCESS;
|
|
}
|
|
|
|
void
|
|
transcode_to_jpeg(PPM* in)
|
|
{
|
|
size_t length = find_extension(in->name);
|
|
char str2[length];
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
str2[i] = in->name[i];
|
|
}
|
|
char* str3 = ".jpg";
|
|
char* result = malloc(strlen(str2) + strlen(str3) + 1);
|
|
if (result != NULL)
|
|
{
|
|
strcat(result, str2);
|
|
strcat(result, str3);
|
|
}
|
|
else
|
|
{
|
|
LOGERROR(ERR_MALLOC_NULL);
|
|
return;
|
|
}
|
|
JPEG img;
|
|
if (!in)
|
|
{
|
|
LOGERROR(ERR_IMG_NULL);
|
|
return;
|
|
}
|
|
unsigned int* dst = read_ppm(in->name, in);
|
|
if (!dst)
|
|
{
|
|
LOGERROR(ERR_BUF_NULL);
|
|
return;
|
|
}
|
|
img.width = in->width;
|
|
img.height = in->height;
|
|
write_jpeg(dst, &img, result);
|
|
free(dst);
|
|
free(result);
|
|
}
|
|
|
|
void
|
|
transcode_to_ppm(JPEG* in)
|
|
{
|
|
size_t length = find_extension(in->name);
|
|
char str2[length];
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
str2[i] = in->name[i];
|
|
}
|
|
char* str3 = ".ppm";
|
|
char* result = malloc(strlen(str2) + strlen(str3) + 1);
|
|
if (result != NULL)
|
|
{
|
|
strcat(result, str2);
|
|
strcat(result, str3);
|
|
}
|
|
else
|
|
{
|
|
LOGERROR(ERR_MALLOC_NULL);
|
|
return;
|
|
}
|
|
PPM img;
|
|
if (!in)
|
|
{
|
|
LOGERROR(ERR_IMG_NULL);
|
|
return;
|
|
}
|
|
unsigned int* dst = read_jpeg(in);
|
|
if (!dst)
|
|
{
|
|
LOGERROR(ERR_BUF_NULL);
|
|
return;
|
|
}
|
|
img.width = in->width;
|
|
img.height = in->height;
|
|
img.len = img.width * img.height;
|
|
write_ppm(dst, img, result);
|
|
free(dst);
|
|
free(result);
|
|
}
|
|
|
|
PPM
|
|
inherit_from_jpeg(const JPEG* in, const char fmt)
|
|
{
|
|
PPM img;
|
|
if (!in)
|
|
{
|
|
LOGERROR(ERR_IMG_NULL);
|
|
return img;
|
|
}
|
|
PPM image = { .width = in->width,
|
|
.height = in->height,
|
|
.len = in->len,
|
|
.fmt = fmt };
|
|
return image;
|
|
}
|
|
|
|
JPEG
|
|
inherit_from_ppm(const PPM* in)
|
|
{
|
|
JPEG blank;
|
|
if (!in)
|
|
{
|
|
LOGERROR(ERR_IMG_NULL);
|
|
return blank;
|
|
}
|
|
JPEG image = {
|
|
.width = in->width,
|
|
.height = in->height,
|
|
.len = in->len,
|
|
};
|
|
return image;
|
|
}
|