Skip to content

Instantly share code, notes, and snippets.

@clausecker
Forked from anonymous/blocks.c
Created August 18, 2012 20:48
Show Gist options
  • Save clausecker/3389793 to your computer and use it in GitHub Desktop.
Save clausecker/3389793 to your computer and use it in GitHub Desktop.
Simple block-based intra-frame-coding using a ring-buffer
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "image.h"
#include "ppm.h"
#include "databuffer.h"
#include "rangecode.h"
#define INDEXBITS 14
#define BUFSIZE (1<<INDEXBITS)
#define BS 8
struct block {
struct pixel pixel[BS][BS];
};
static struct block ringbuf[BUFSIZE];
struct databuffer *imagebuffer, *indexbuffer;
int rbindex = 0;
int bcount = 0;
static int find_block(struct block * needle) {
int i;
int limit = bcount > BUFSIZE ? BUFSIZE : rbindex;
// simplifiaction for analysis. Use BUFSIZE later
for (i = 0; i < limit ; i++)
if (0 == memcmp(needle,&ringbuf[i],sizeof *needle)) return i;
return -1;
}
static int put_block(struct block * needle) {
int x, y;
bcount++;
rbindex %= BUFSIZE;
ringbuf[rbindex] = *needle;
for( y=0; y<BS; y++ )
for( x=0; x<BS; x++ )
{
databuffer_add_byte( needle->pixel[x][y].x, imagebuffer );
databuffer_add_byte( needle->pixel[x][y].y, imagebuffer );
databuffer_add_byte( needle->pixel[x][y].z, imagebuffer );
}
return rbindex++;
}
static int auto_block(struct block * needle) {
int i;
i = find_block(needle);
if (i != -1) return i;
else return put_block(needle);
}
static uint32_t *encode_image(struct image *image) {
struct block block;
int i,j,k,l;
int width = image->width, height = image->height;
int index;
for (i = 0; i < width / BS; i++) {
for (j = 0; j < height / BS; j++) {
for (k = 0; k < BS; k++) {
for (l = 0; l < BS; l++) {
block.pixel[k][l] = image->pixels[j*BS*width+i*BS+k+l*width];
}
}
index = auto_block(&block);
databuffer_add_bits( index, indexbuffer, INDEXBITS );
}
}
return NULL;
}
int main() {
struct image image;
int dimension, framenum = 0;
int diff;
int size = 0;
struct databuffer *imagebuffer_comp, *indexbuffer_comp;
struct rangecoder *imagecoder, *indexcoder;
imagecoder = rangecoder_create( 2, 8 );
indexcoder = rangecoder_create( 2, 8 );
while(ppm_read(&image,NULL)) {
diff = bcount;
imagebuffer = databuffer_create( 1024 );
indexbuffer = databuffer_create( 512 );
image_transform(&image);
encode_image(&image);
dimension = (image.width/BS)*(image.height/BS);
diff = bcount - diff;
imagebuffer_comp = databuffer_create( 1024 );
indexbuffer_comp = databuffer_create( 512 );
rangecode_compress( imagecoder, imagebuffer, imagebuffer_comp );
rangecode_compress( indexcoder, indexbuffer, indexbuffer_comp );
size += imagebuffer_comp->size*8+imagebuffer_comp->bits;
size += indexbuffer_comp->size*8+indexbuffer_comp->bits;
printf("Frame %4i, neue B.: %6i (%.2f%%), B. insges: %7i size: %f\n",++framenum,diff,diff*100.0/dimension,bcount,size/(8.0*1024.0*1024.0));
image_free(&image);
databuffer_free( imagebuffer_comp );
databuffer_free( indexbuffer_comp );
databuffer_free( imagebuffer );
databuffer_free( indexbuffer );
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment