using libjpeg to read-write JPEG

Beberapa waktu lalu sempat iseng coba-coba menggunakan libjpeg dengan MinGW. Awalnya dari install msys lalu nyoba build libjpeg. setelah dicoba untuk utak-atik pengolahan citra ternyata lumayan cepat juga.

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <mem.h>

#include <jpeglib.h>

fungsi baca-tulis dari libjpeg tidak mengembalikan data dalam bentuk bitmap. oleh sebab itu saya membuat sendiri struktur bitmap sederhana dan fungsi-fungsi minimal untuk itu.

//tipe data untuk manipulasi bitmap
typedef unsigned char byte;
typedef struct st_RGBimage {
	int w, h;
	int stride;
	byte* data;
}bitmap;

bitmap* create_bitmap(int w, int h, int stride)
{
	bitmap* tmp = (bitmap*)malloc(sizeof(bitmap));
	tmp->w = w;
	tmp->h = h;
	tmp->stride = stride;
	tmp->data = (byte*)malloc(sizeof(byte)*stride*h);
	return tmp;
}

void free_bitmap(bitmap** bmp){
	free((*bmp)->data);
	free(bmp);
	*bmp = NULL;
}

mari mulai dengan membaca dan memuat citra jpeg ke struktur bitmap.

//struktur dan fungsi sampingan
struct my_error_mgr{
	struct jpeg_error_mgr pub;
	jmp_buf setjmp_buffer;
};

void my_error_exit(j_common_ptr cinfo)
{
	
}

int load_jpeg(char * filename, bitmap** bmp)
{
	struct jpeg_decompress_struct cinfo;
	struct my_error_mgr jerr;
	FILE * infile;		
	JSAMPARRAY buffer;
	int row_stride;		
	int i;
	
	if ((infile = fopen(filename, "rb")) == NULL) {
		fprintf(stderr, "can't open %s\n", filename);
		return 0;
	}

	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = my_error_exit;

	if (setjmp(jerr.setjmp_buffer)) {
		jpeg_destroy_decompress(&cinfo);
		fclose(infile);
		return 0;
	}
	
	jpeg_create_decompress(&cinfo);
	jpeg_stdio_src(&cinfo, infile);
	jpeg_read_header(&cinfo, TRUE);
	jpeg_start_decompress(&cinfo);

	row_stride = cinfo.output_width * cinfo.output_components;
	(*bmp) = create_bitmap(cinfo.output_width, cinfo.output_height, row_stride);
	buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
	i = 0;
	while (cinfo.output_scanline < cinfo.output_height) {
		jpeg_read_scanlines(&cinfo, buffer, 1);
		memcpy((void*)((*bmp)->data+i), (void*)buffer[0], row_stride);
		i+= row_stride;
	}
	
	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
	fclose(infile);
	return 1;
}

setelah dibaca, fungsi selanjutnya adalah menyimpan dari struktur bitmap.

void save_jpeg(char *filename, int quality, bitmap* bmp)
{
	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;
	
	FILE * outfile;
	JSAMPROW row_pointer[1];
	int row_stride;
	
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_compress(&cinfo);
	
	if ((outfile = fopen(filename, "wb")) == NULL) {
		fprintf(stderr, "can't open %s\n", filename);
		exit(1);
	}
	
	jpeg_stdio_dest(&cinfo, outfile);
	cinfo.image_width = bmp->w;
	cinfo.image_height = bmp->h;
	cinfo.input_components = 3;
	cinfo.in_color_space = JCS_RGB;
	
	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, quality, TRUE);
	jpeg_start_compress(&cinfo, TRUE);
	
	row_stride = bmp->w * 3;
	while(cinfo.next_scanline < cinfo.image_height){
		row_pointer&#91;0&#93; = &bmp->data[cinfo.next_scanline * bmp->stride];
		jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}
	
	jpeg_finish_compress(&cinfo);
	fclose(outfile);
	jpeg_destroy_compress(&cinfo);
}

sekarang saya sudah bisa manipulasi sederhana dengan struktur bitmap.

bitmap* rgb_binarize(bitmap* bmp24, int threshold)
{
	//bitmap* g = create_bitmap(bmp24->w, bmp24->h, bmp24->stride / 3);
	bitmap* g = create_bitmap(bmp24->w, bmp24->h, bmp24->stride);
	int i,j, tmp;
	for (j=0; j<bmp24->h; ++j){
		for (i=0; i<bmp24->w; ++i){
			tmp = (int)(0.299*bmp24->data[bmp24->stride*j+i*3]+0.587*bmp24->data[bmp24->stride*j+i*3+1]+0.114*bmp24->data[bmp24->stride*j+i*3+2]);
			tmp = (tmp>threshold)?255:0;
			g->data[j*g->stride + i*3] = (byte)tmp;
			g->data[j*g->stride + i*3 + 1] = (byte)tmp;
			g->data[j*g->stride + i*3 + 2] = (byte)tmp;
		}
	}
	return g;
}

int main(int argc, char **argv){
	bitmap * bmp;
	bitmap * grey;
	if (argc>1)
		load_jpeg(argv[1], &bmp);
	else return 1;
	grey = rgb_binarize(bmp, 128);
	save_jpeg("grey.jpg", 90, grey);
	free_bitmap(&bmp);
	free_bitmap(&grey);
	return 0;
}

selamat mencoba!😉

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s