Conversion from ppm to jpeg and vice versa added
This commit is contained in:
+231
-205
@@ -2,8 +2,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <turbojpeg.h>
|
#include <turbojpeg.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#define BYTE_A 0xFF000000
|
#define BYTE_A 0xFF000000
|
||||||
#define BYTE_R 0x00FF0000
|
#define BYTE_R 0x00FF0000
|
||||||
@@ -24,10 +24,18 @@
|
|||||||
#define decode_g(clr) (((clr) >> SHIFT_8) & BYTE)
|
#define decode_g(clr) (((clr) >> SHIFT_8) & BYTE)
|
||||||
#define decode_b(clr) ((clr) & BYTE)
|
#define decode_b(clr) ((clr) & BYTE)
|
||||||
|
|
||||||
#define encode(r, g, b) \
|
#define ENCODE_RGB(r, g, b) \
|
||||||
(((unsigned int)(MAX) << SHIFT_24) | ((unsigned int)(r) << SHIFT_16) | \
|
(((unsigned int)(MAX) << SHIFT_24) | ((unsigned int)(r) << SHIFT_16) | \
|
||||||
((unsigned int)(g) << SHIFT_8) | (unsigned int)(b))
|
((unsigned int)(g) << SHIFT_8) | (unsigned int)(b))
|
||||||
|
|
||||||
|
#define ENCODE_ARGB(a, r, g, b) \
|
||||||
|
(((unsigned int)(a) << SHIFT_24) | ((unsigned int)(r) << SHIFT_16) | \
|
||||||
|
((unsigned int)(g) << SHIFT_8) | (unsigned int)(b))
|
||||||
|
|
||||||
|
#define ENCODE_BGRA(b, g, r, a) \
|
||||||
|
(((unsigned int)(b) << SHIFT_24) | ((unsigned int)(g) << SHIFT_16) | \
|
||||||
|
((unsigned int)(r) << SHIFT_8) | (unsigned int)(a))
|
||||||
|
|
||||||
#define CLAMP_MAX(x) (((x) > MAX) ? MAX : (x))
|
#define CLAMP_MAX(x) (((x) > MAX) ? MAX : (x))
|
||||||
#define CLAMP_MIN(x) (((x) < 0) ? 0 : (x))
|
#define CLAMP_MIN(x) (((x) < 0) ? 0 : (x))
|
||||||
|
|
||||||
@@ -35,78 +43,16 @@ typedef struct
|
|||||||
{
|
{
|
||||||
int width, height, len;
|
int width, height, len;
|
||||||
const char* name;
|
const char* name;
|
||||||
char fmt[3];
|
char fmt[4];
|
||||||
} PPM;
|
} PPM;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
size_t len;
|
size_t len;
|
||||||
const char* name;
|
char* name;
|
||||||
} JPEG;
|
} JPEG;
|
||||||
|
|
||||||
unsigned int*
|
|
||||||
jpeg_decode(JPEG* attr)
|
|
||||||
{
|
|
||||||
printf("Starting Decode...\n");
|
|
||||||
tjhandle tjdecompress = tj3Init(TJINIT_DECOMPRESS);
|
|
||||||
unsigned char* jpeg_buf = NULL;
|
|
||||||
FILE* infile = fopen(attr->name, "rb");
|
|
||||||
if (!infile) return NULL;
|
|
||||||
fseek(infile, 0, SEEK_END);
|
|
||||||
attr->len = ftell(infile);
|
|
||||||
fseek(infile, 0, SEEK_SET);
|
|
||||||
jpeg_buf = (unsigned char*)malloc(attr->len);
|
|
||||||
fread(jpeg_buf, 1, attr->len, infile);
|
|
||||||
fclose(infile);
|
|
||||||
if (tj3DecompressHeader(tjdecompress, jpeg_buf, attr->len) < 0)
|
|
||||||
{
|
|
||||||
printf("Header error: %s\n", tj3GetErrorStr(tjdecompress));
|
|
||||||
free(jpeg_buf);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
attr->width = tj3Get(tjdecompress, TJPARAM_JPEGWIDTH);
|
|
||||||
attr->height = tj3Get(tjdecompress, TJPARAM_JPEGHEIGHT);
|
|
||||||
unsigned int* pixels =
|
|
||||||
malloc(attr->width * attr->height * sizeof(unsigned int));
|
|
||||||
tj3Decompress8(tjdecompress, jpeg_buf, attr->len,
|
|
||||||
(unsigned char*)pixels, 0, TJPF_BGRA);
|
|
||||||
tj3Destroy(tjdecompress);
|
|
||||||
free(jpeg_buf);
|
|
||||||
printf("Decode Successful!\n");
|
|
||||||
return pixels;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
jpeg_encode(unsigned int* src_buf, JPEG* attr, 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)
|
|
||||||
{
|
|
||||||
free(src_buf);
|
|
||||||
tj3Free(dst_buf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fwrite(dst_buf, 1, dst_size, fptr);
|
|
||||||
fclose(fptr);
|
|
||||||
|
|
||||||
tj3Destroy(tjcompress);
|
|
||||||
tj3Free(dst_buf);
|
|
||||||
printf("Encode Successful!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
unsigned int red, green, blue;
|
unsigned int red, green, blue;
|
||||||
@@ -147,8 +93,8 @@ static inline unsigned int
|
|||||||
apply_threshold(const unsigned int clr, const unsigned char limit)
|
apply_threshold(const unsigned int clr, const unsigned char limit)
|
||||||
{
|
{
|
||||||
unsigned int mask = 0;
|
unsigned int mask = 0;
|
||||||
if (decode_b(to_grayscale(clr)) < limit) mask = encode(0, 0, 0);
|
if (decode_b(to_grayscale(clr)) < limit) mask = ENCODE_RGB(0, 0, 0);
|
||||||
else mask = encode(MAX, MAX, MAX);
|
else mask = ENCODE_RGB(MAX, MAX, MAX);
|
||||||
return BYTE_A | mask;
|
return BYTE_A | mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +118,7 @@ apply_tint(const unsigned int clr_a, const unsigned int clr_b)
|
|||||||
unsigned char green = (decode_g(clr_a) + decode_g(clr_b)) / 2;
|
unsigned char green = (decode_g(clr_a) + decode_g(clr_b)) / 2;
|
||||||
unsigned char red = (decode_r(clr_a) + decode_r(clr_b)) / 2;
|
unsigned char red = (decode_r(clr_a) + decode_r(clr_b)) / 2;
|
||||||
|
|
||||||
return set_alpha(encode(red, green, blue), decode_a(clr_a));
|
return set_alpha(ENCODE_RGB(red, green, blue), decode_a(clr_a));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int
|
static inline unsigned int
|
||||||
@@ -184,120 +130,7 @@ apply_opacity(const unsigned clr_a, const unsigned int clr_b, const float ratio)
|
|||||||
((decode_g(clr_b) * ratio)));
|
((decode_g(clr_b) * ratio)));
|
||||||
unsigned char red = (unsigned char)((decode_r(clr_a) * (1 - ratio)) +
|
unsigned char red = (unsigned char)((decode_r(clr_a) * (1 - ratio)) +
|
||||||
((decode_r(clr_b) * ratio)));
|
((decode_r(clr_b) * ratio)));
|
||||||
return set_alpha(encode(red, green, blue), decode_a(clr_a));
|
return set_alpha(ENCODE_RGB(red, green, blue), decode_a(clr_a));
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int*
|
|
||||||
ppm_encode(const char* file, PPM* img)
|
|
||||||
{
|
|
||||||
printf("Starting encode...\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", file);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
fscanf(fptr, "%s", fmt);
|
|
||||||
fscanf(fptr, "%d %d", &img->width, &img->height);
|
|
||||||
img->len = img->width * img->height;
|
|
||||||
fscanf(fptr, "%d", &max_val);
|
|
||||||
fgetc(fptr);
|
|
||||||
unsigned char* img_buf = malloc(img->len * 3);
|
|
||||||
if (!img_buf) return NULL;
|
|
||||||
unsigned int* clr_buf = malloc(img->len * sizeof(unsigned int));
|
|
||||||
if (!clr_buf)
|
|
||||||
{
|
|
||||||
free(img_buf);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (fmt[1] == '3')
|
|
||||||
{
|
|
||||||
for (int i = 0; i < img->len; i++)
|
|
||||||
{
|
|
||||||
fscanf(fptr, "%hhu %hhu %hhu", &red, &green, &blue);
|
|
||||||
clr_buf[i] = encode(red, green, blue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (fmt[1] == '6')
|
|
||||||
{
|
|
||||||
fread(img_buf, 3, img->len, fptr);
|
|
||||||
|
|
||||||
for (int i = 0; i < img->len; i++)
|
|
||||||
{
|
|
||||||
red = img_buf[i * 3];
|
|
||||||
green = img_buf[i * 3 + 1];
|
|
||||||
blue = img_buf[i * 3 + 2];
|
|
||||||
clr_buf[i] = encode(red, green, blue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fptr);
|
|
||||||
free(img_buf);
|
|
||||||
printf("Encoding done!\n");
|
|
||||||
return clr_buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
ppm_apply_brightness(unsigned int* buf, const PPM img, const float factor)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < img.len; i++)
|
|
||||||
{
|
|
||||||
buf[i] = adjust_brightness(buf[i], factor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
ppm_decode(unsigned int* buf, const PPM img)
|
|
||||||
{
|
|
||||||
unsigned char red, green, blue;
|
|
||||||
unsigned char* dst_buf = malloc(img.len * 3);
|
|
||||||
if (!dst_buf) return;
|
|
||||||
printf("Starting decode...\n");
|
|
||||||
FILE* fptr;
|
|
||||||
|
|
||||||
if (img.fmt[1] == '3') fptr = fopen(img.name, "w");
|
|
||||||
if (img.fmt[1] == '6') fptr = fopen(img.name, "wb");
|
|
||||||
if (!fptr)
|
|
||||||
{
|
|
||||||
free(dst_buf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fptr, "%s\n%d %d\n255\n", img.fmt, img.width, img.height);
|
|
||||||
if (img.fmt[1] == '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[1] == '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);
|
|
||||||
free(buf);
|
|
||||||
printf("Decode Done!\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int
|
static inline unsigned int
|
||||||
@@ -331,7 +164,7 @@ chromatic_circular_shift(const unsigned int clr, const int n)
|
|||||||
red = ((red << n) | (red >> (SHIFT_8 - n))) & BYTE;
|
red = ((red << n) | (red >> (SHIFT_8 - n))) & BYTE;
|
||||||
green = ((green << n) | (green >> (SHIFT_8 - n))) & BYTE;
|
green = ((green << n) | (green >> (SHIFT_8 - n))) & BYTE;
|
||||||
blue = ((blue << n) | (blue >> (SHIFT_8 - n))) & BYTE;
|
blue = ((blue << n) | (blue >> (SHIFT_8 - n))) & BYTE;
|
||||||
return encode(red, green, blue);
|
return ENCODE_RGB(red, green, blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int*
|
static inline unsigned int*
|
||||||
@@ -434,7 +267,7 @@ brightness_mirror(unsigned int clr)
|
|||||||
unsigned char red = decode_r(clr);
|
unsigned char red = decode_r(clr);
|
||||||
unsigned char blue = decode_b(clr);
|
unsigned char blue = decode_b(clr);
|
||||||
unsigned char green = (red + blue) / 2;
|
unsigned char green = (red + blue) / 2;
|
||||||
return encode(red, green, blue);
|
return ENCODE_RGB(red, green, blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int
|
static inline unsigned int
|
||||||
@@ -480,7 +313,7 @@ box_blur(unsigned int* src_buf, PPM* img, int radius)
|
|||||||
unsigned long cpi = 0, red = 0, green = 0, blue = 0;
|
unsigned long cpi = 0, red = 0, green = 0, blue = 0;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int edge = (x < radius || x >= img->width - radius);
|
int edge = (x < radius || x >= img->width - radius);
|
||||||
if (edge) continue;
|
if (edge) continue;
|
||||||
cpi = src_buf[y * img->width + x];
|
cpi = src_buf[y * img->width + x];
|
||||||
|
|
||||||
for (int dx = -radius; dx <= radius; dx++)
|
for (int dx = -radius; dx <= radius; dx++)
|
||||||
@@ -497,8 +330,8 @@ box_blur(unsigned int* src_buf, PPM* img, int radius)
|
|||||||
if (count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
tmp_buf[y * img->width + x] =
|
tmp_buf[y * img->width + x] =
|
||||||
encode((red / count), (green / count),
|
ENCODE_RGB((red / count), (green / count),
|
||||||
(blue / count));
|
(blue / count));
|
||||||
}
|
}
|
||||||
else tmp_buf[y * img->width + x] = cpi;
|
else tmp_buf[y * img->width + x] = cpi;
|
||||||
}
|
}
|
||||||
@@ -512,14 +345,13 @@ box_blur(unsigned int* src_buf, PPM* img, int radius)
|
|||||||
unsigned long cpi = 0, red = 0, green = 0, blue = 0;
|
unsigned long cpi = 0, red = 0, green = 0, blue = 0;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int edge = (y < radius || y >= img->height - radius);
|
int edge = (y < radius || y >= img->height - radius);
|
||||||
if (edge) continue;
|
if (edge) continue;
|
||||||
cpi = src_buf[y * img->width + x];
|
cpi = src_buf[y * img->width + x];
|
||||||
|
|
||||||
for (int dy = -radius; dy <= radius; dy++)
|
for (int dy = -radius; dy <= radius; dy++)
|
||||||
{
|
{
|
||||||
int py = y + dy;
|
int py = y + dy;
|
||||||
if (py < 0 || py >= img->height)
|
if (py < 0 || py >= img->height) continue;
|
||||||
continue;
|
|
||||||
unsigned int p = tmp_buf[py * img->width + x];
|
unsigned int p = tmp_buf[py * img->width + x];
|
||||||
red += decode_r(p);
|
red += decode_r(p);
|
||||||
green += decode_g(p);
|
green += decode_g(p);
|
||||||
@@ -530,8 +362,8 @@ box_blur(unsigned int* src_buf, PPM* img, int radius)
|
|||||||
if (count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
dst_buf[y * img->width + x] =
|
dst_buf[y * img->width + x] =
|
||||||
encode((red / count), (green / count),
|
ENCODE_RGB((red / count), (green / count),
|
||||||
(blue / count));
|
(blue / count));
|
||||||
}
|
}
|
||||||
else dst_buf[y * img->width + x] = cpi;
|
else dst_buf[y * img->width + x] = cpi;
|
||||||
}
|
}
|
||||||
@@ -542,22 +374,216 @@ box_blur(unsigned int* src_buf, PPM* img, int radius)
|
|||||||
return dst_buf;
|
return dst_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
ppm_apply_brightness(unsigned int* buf, const PPM img, const float factor)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < img.len; i++)
|
||||||
|
{
|
||||||
|
buf[i] = adjust_brightness(buf[i], factor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int*
|
||||||
|
ppm_decode(const char* file, PPM* img)
|
||||||
|
{
|
||||||
|
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", file);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fscanf(fptr, "%s", fmt);
|
||||||
|
fscanf(fptr, "%d %d", &img->width, &img->height);
|
||||||
|
img->len = img->width * img->height;
|
||||||
|
fscanf(fptr, "%d", &max_val);
|
||||||
|
fgetc(fptr);
|
||||||
|
unsigned char* img_buf = malloc(img->len * 3);
|
||||||
|
if (!img_buf) return NULL;
|
||||||
|
unsigned int* clr_buf = malloc(img->len * sizeof(unsigned int));
|
||||||
|
if (!clr_buf)
|
||||||
|
{
|
||||||
|
free(img_buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (fmt[1] == '3')
|
||||||
|
{
|
||||||
|
for (int i = 0; i < img->len; i++)
|
||||||
|
{
|
||||||
|
fscanf(fptr, "%hhu %hhu %hhu", &red, &green, &blue);
|
||||||
|
clr_buf[i] = ENCODE_RGB(red, green, blue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (fmt[1] == '6')
|
||||||
|
{
|
||||||
|
fread(img_buf, 3, img->len, fptr);
|
||||||
|
|
||||||
|
for (int i = 0; i < img->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
ppm_encode(unsigned int* buf, const PPM img)
|
||||||
|
{
|
||||||
|
if (!buf) return;
|
||||||
|
unsigned char red, green, blue;
|
||||||
|
unsigned char* dst_buf = malloc(img.len * 3);
|
||||||
|
if (!dst_buf) return;
|
||||||
|
printf("Starting encode...\n");
|
||||||
|
FILE* fptr;
|
||||||
|
|
||||||
|
if (img.fmt[1] == '3') fptr = fopen(img.name, "w");
|
||||||
|
if (img.fmt[1] == '6') fptr = fopen(img.name, "wb");
|
||||||
|
if (!fptr)
|
||||||
|
{
|
||||||
|
free(dst_buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fptr, "%s\n%d %d\n255\n", img.fmt, img.width, img.height);
|
||||||
|
if (img.fmt[1] == '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[1] == '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);
|
||||||
|
free(buf);
|
||||||
|
printf("Encode Done!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int*
|
||||||
|
jpeg_decode(JPEG* attr)
|
||||||
|
{
|
||||||
|
printf("Starting Decode...\n");
|
||||||
|
tjhandle tjdecompress = tj3Init(TJINIT_DECOMPRESS);
|
||||||
|
unsigned char* jpeg_buf = NULL;
|
||||||
|
FILE* infile = fopen(attr->name, "rb");
|
||||||
|
if (!infile) return NULL;
|
||||||
|
fseek(infile, 0, SEEK_END);
|
||||||
|
attr->len = ftell(infile);
|
||||||
|
fseek(infile, 0, SEEK_SET);
|
||||||
|
jpeg_buf = (unsigned char*)malloc(attr->len);
|
||||||
|
fread(jpeg_buf, 1, attr->len, infile);
|
||||||
|
fclose(infile);
|
||||||
|
if (tj3DecompressHeader(tjdecompress, jpeg_buf, attr->len) < 0)
|
||||||
|
{
|
||||||
|
printf("Header error: %s\n", tj3GetErrorStr(tjdecompress));
|
||||||
|
free(jpeg_buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
attr->width = tj3Get(tjdecompress, TJPARAM_JPEGWIDTH);
|
||||||
|
attr->height = tj3Get(tjdecompress, TJPARAM_JPEGHEIGHT);
|
||||||
|
unsigned int* pixels =
|
||||||
|
malloc(attr->width * attr->height * sizeof(unsigned int));
|
||||||
|
tj3Decompress8(tjdecompress, jpeg_buf, attr->len,
|
||||||
|
(unsigned char*)pixels, 0, TJPF_BGRA);
|
||||||
|
tj3Destroy(tjdecompress);
|
||||||
|
free(jpeg_buf);
|
||||||
|
printf("Decode Successful!\n");
|
||||||
|
return pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jpeg_encode(unsigned int* src_buf, JPEG* attr, 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)
|
||||||
|
{
|
||||||
|
free(src_buf);
|
||||||
|
tj3Free(dst_buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fwrite(dst_buf, 1, dst_size, fptr);
|
||||||
|
fclose(fptr);
|
||||||
|
|
||||||
|
tj3Destroy(tjcompress);
|
||||||
|
tj3Free(dst_buf);
|
||||||
|
if (src_buf) free(src_buf);
|
||||||
|
printf("Encode Successful!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ppm_to_jpeg(PPM* in, JPEG* out)
|
||||||
|
{
|
||||||
|
unsigned int* src_buf = ppm_decode(in->name, in);
|
||||||
|
// int jpeg_size = jpeg->width * jpeg->height;
|
||||||
|
out->width = in->width;
|
||||||
|
out->height = in->height;
|
||||||
|
jpeg_encode(src_buf, out, out->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jpeg_to_ppm(JPEG* input, PPM* out)
|
||||||
|
{
|
||||||
|
unsigned int* src_buf = jpeg_decode(input);
|
||||||
|
out->width = input->width;
|
||||||
|
out->height = input->height;
|
||||||
|
out->len = out->width * out->height;
|
||||||
|
ppm_encode(src_buf, *out);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
PPM img = { .width = 3,
|
PPM ppm = { .width = 3,
|
||||||
|
.height = 2,
|
||||||
|
.name = "../assets/8ktest.ppm",
|
||||||
|
.len = 0,
|
||||||
|
.fmt = "P6" };
|
||||||
|
JPEG jpeg = { .width = 3,
|
||||||
.height = 2,
|
.height = 2,
|
||||||
.name = "../color.ppm",
|
.len = 0,
|
||||||
.fmt = "P6",
|
.name = "../test.jpg" };
|
||||||
.len = 0 };
|
|
||||||
|
|
||||||
unsigned int* buf = ppm_encode("../assets/8ktest.ppm", &img);
|
// jpeg_to_ppm(&jpeg, &ppm);
|
||||||
if (buf)
|
ppm_to_jpeg(&ppm, &jpeg);
|
||||||
{
|
|
||||||
printf("Applying Filter...\n");
|
|
||||||
buf = box_blur(buf, &img, 40);
|
|
||||||
printf("Finished Applying Filter!\n");
|
|
||||||
ppm_decode(buf, img);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user