-
-
Save clausecker/3389793 to your computer and use it in GitHub Desktop.
Simple block-based intra-frame-coding using a ring-buffer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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