#include "image/imgio.h" #include #include #include #include #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; }