Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Image loading library (WIP)

  • Loading branch information...
commit 1a931d94f14e97c7ba01303b0f00ffc0786afb53 1 parent 03214ca
@sbourdeauducq sbourdeauducq authored
View
119 src/pixbuf/dither.c
@@ -0,0 +1,119 @@
+/*
+ * Flickernoise
+ * Copyright (C) 2011 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+
+#include "../color.h"
+
+static void floyd_steinberg(int *pic, int width, int height)
+{
+ int x, y;
+ int offset;
+ int old_r, old_g, old_b;
+ int new_r, new_g, new_b;
+ int qe_r, qe_g, qe_b;
+
+ for(y=0;y<height;y++)
+ for(x=0;x<width;x++) {
+ offset = 3*(width*y+x);
+ old_r = pic[offset];
+ old_g = pic[offset+1];
+ old_b = pic[offset+2];
+ if(old_r > 0x00f80000)
+ new_r = 0x00f80000;
+ else if(old_r > 0)
+ new_r = old_r & 0x00f80000;
+ else
+ new_r = 0;
+ if(old_g > 0x00fc0000)
+ new_g = 0x00fc0000;
+ else if(old_g > 0)
+ new_g = old_g & 0x00fc0000;
+ else
+ new_g = 0;
+ if(old_b > 0x00f80000)
+ new_b = 0x00f80000;
+ else if(old_b > 0)
+ new_b = old_b & 0x00f80000;
+ else
+ new_b = 0;
+ pic[offset] = new_r;
+ pic[offset+1] = new_g;
+ pic[offset+2] = new_b;
+ qe_r = old_r - new_r;
+ qe_g = old_g - new_g;
+ qe_b = old_b - new_b;
+
+ if((x+1) < width) {
+ pic[offset+3] += (qe_r*7) >> 4;
+ pic[offset+3+1] += (qe_g*7) >> 4;
+ pic[offset+3+2] += (qe_b*7) >> 4;
+ }
+ if((y+1) < height) {
+ offset += 3*width;
+ if(x > 0) {
+ pic[offset-3] += (qe_r*3) >> 4;
+ pic[offset-3+1] += (qe_g*3) >> 4;
+ pic[offset-3+2] += (qe_b*3) >> 4;
+ }
+ pic[offset] += (qe_r*5) >> 4;
+ pic[offset+1] += (qe_g*5) >> 4;
+ pic[offset+2] += (qe_b*5) >> 4;
+ if((x+1) < width) {
+ pic[offset+3] += qe_r >> 4;
+ pic[offset+3+1] += qe_g >> 4;
+ pic[offset+3+2] += qe_b >> 4;
+ }
+ }
+ }
+}
+
+int pixbuf_dither(unsigned short *ret, unsigned char **row_pointers, int width, int height)
+{
+ int x, y;
+ unsigned char *row;
+ int offset;
+ int *pic;
+
+ pic = malloc(width*height*3*sizeof(int));
+ if(pic == NULL) return 0;
+
+ for(y=0;y<height;y++) {
+ row = row_pointers[y];
+ for(x=0;x<width;x++) {
+ offset = 3*(width*y+x);
+ pic[offset] = ((unsigned int)row[3*x]) << 16;
+ pic[offset+1] = ((unsigned int)row[3*x+1]) << 16;
+ pic[offset+2] = ((unsigned int)row[3*x+2]) << 16;
+ }
+ }
+
+ floyd_steinberg(pic, width, height);
+
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ offset = 3*(width*y+x);
+ ret[width*y+x] = MAKERGB565N(pic[offset] >> 16,
+ pic[offset+1] >> 16,
+ pic[offset+2] >> 16);
+ }
+ }
+
+ free(pic);
+
+ return 1;
+}
View
23 src/pixbuf/dither.h
@@ -0,0 +1,23 @@
+/*
+ * Flickernoise
+ * Copyright (C) 2011 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PIXBUF_DITHER_H
+#define __PIXBUF_DITHER_H
+
+int pixbuf_dither(unsigned short *ret, unsigned char **row_pointers, int width, int height);
+
+#endif /* __PIXBUF_DITHER_H */
View
27 src/pixbuf/loaderjpeg.c
@@ -0,0 +1,27 @@
+/*
+ * Flickernoise
+ * Copyright (C) 2011 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+
+#include "pixbuf.h"
+#include "loaders.h"
+
+struct pixbuf *pixbuf_load_jpeg(char *filename)
+{
+ /* TODO */
+ return NULL;
+}
View
102 src/pixbuf/loaderpng.c
@@ -0,0 +1,102 @@
+/*
+ * Flickernoise
+ * Copyright (C) 2010, 2011 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <png.h>
+#include <zlib.h>
+
+#include "pixbuf.h"
+#include "loaders.h"
+
+#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+#warning Floating point PNG is slow
+#endif
+
+struct pixbuf *pixbuf_load_png(char *filename)
+{
+ struct pixbuf *ret;
+ FILE *fd;
+ unsigned char header[8];
+ png_structp png_ptr;
+ png_infop info_ptr;
+ unsigned int width, height;
+ png_byte color_type;
+ png_byte bit_depth;
+ png_bytep *row_pointers;
+ size_t rowbytes;
+ int y;
+
+ ret = NULL;
+ fd = fopen(filename, "r");
+ if(fd == NULL) goto free0;
+ fread(header, 1, 8, fd);
+ if(png_sig_cmp(header, 0, 8)) goto free1;
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if(png_ptr == NULL) goto free1;
+ info_ptr = png_create_info_struct(png_ptr);
+ if(info_ptr == NULL) goto free2;
+
+ if(setjmp(png_jmpbuf(png_ptr))) goto free3;
+ png_init_io(png_ptr, fd);
+ png_set_sig_bytes(png_ptr, 8);
+ png_read_info(png_ptr, info_ptr);
+
+ width = png_get_image_width(png_ptr, info_ptr);
+ height = png_get_image_height(png_ptr, info_ptr);
+ color_type = png_get_color_type(png_ptr, info_ptr);
+ bit_depth = png_get_bit_depth(png_ptr, info_ptr);
+
+ if(color_type != PNG_COLOR_TYPE_RGB) goto free3;
+ if(bit_depth != 8) goto free3;
+
+ row_pointers = calloc(sizeof(png_bytep), height);
+ if(row_pointers == NULL) goto free3;
+ if(setjmp(png_jmpbuf(png_ptr))) goto free4;
+ rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+ for(y=0;y<height;y++) {
+ row_pointers[y] = malloc(rowbytes);
+ if(row_pointers[y] == NULL)
+ goto free4;
+ }
+
+ png_read_image(png_ptr, row_pointers);
+
+ ret = pixbuf_new(width, height);
+ if(ret == NULL) goto free4;
+ ret->filename = strdup(filename);
+ if(!dither(ret->pixels, row_pointers, width, height)) {
+ pixbuf_dec_ref(ret);
+ ret = NULL;
+ goto free4;
+ }
+
+free4:
+ for(y=0;y<height;y++)
+ free(row_pointers[y]);
+ free(row_pointers);
+free3:
+ png_destroy_info_struct(png_ptr, &info_ptr);
+free2:
+ png_destroy_read_struct(&png_ptr, NULL, NULL);
+free1:
+ fclose(fd);
+free0:
+ return ret;
+}
View
26 src/pixbuf/loaders.h
@@ -0,0 +1,26 @@
+/*
+ * Flickernoise
+ * Copyright (C) 2011 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PIXBUF_LOADERS_H
+#define __PIXBUF_LOADERS_H
+
+#include "pixbuf.h"
+
+struct pixbuf *pixbuf_load_png(char *filename);
+struct pixbuf *pixbuf_load_jpeg(char *filename);
+
+#endif /* __PIXBUF_LOADERS_H */
View
97 src/pixbuf/manager.c
@@ -0,0 +1,97 @@
+/*
+ * Flickernoise
+ * Copyright (C) 2011 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "pixbuf.h"
+
+static struct pixbuf *head;
+
+struct pixbuf *pixbuf_new(int width, int height)
+{
+ struct pixbuf *p;
+
+ p = malloc(sizeof(struct pixbuf)+width*height*2);
+ if(p == NULL) return NULL;
+ p->refcnt = 1;
+ p->filename = NULL;
+ p->next = head;
+ p->width = width;
+ p->height = height;
+ head = p;
+ return p;
+}
+
+struct pixbuf *pixbuf_search(char *filename)
+{
+ struct pixbuf *p;
+
+ p = head;
+ while(p != NULL) {
+ if((p->filename != NULL) && (strcmp(p->filename, filename) == 0))
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+void pixbuf_inc_ref(struct pixbuf *p)
+{
+ p->refcnt++;
+}
+
+void pixbuf_dec_ref(struct pixbuf *p)
+{
+ struct pixbuf *prev;
+
+ p->refcnt--;
+ if(p->refcnt == 0) {
+ if(p == head) {
+ head = head->next;
+ free(p->filename);
+ free(p);
+ } else {
+ prev = head;
+ while(prev->next != p)
+ prev = prev->next;
+ prev->next = p->next;
+ free(p->filename);
+ free(p);
+ }
+ }
+}
+
+struct pixbuf *pixbuf_get(char *filename)
+{
+ struct pixbuf *p;
+
+ p = pixbuf_search(filename);
+ if(p != NULL) {
+ pixbuf_inc_ref(p);
+ return p;
+ }
+
+ /* try all loaders */
+ p = pixbuf_load_png(filename);
+ if(p != NULL) return p;
+ p = pixbuf_load_jpeg(filename);
+ if(p != NULL) return p;
+
+ /* no loader was successful */
+ return NULL;
+}
View
36 src/pixbuf/pixbuf.h
@@ -0,0 +1,36 @@
+/*
+ * Flickernoise
+ * Copyright (C) 2011 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PIXBUF_PIXBUF_H
+#define __PIXBUF_PIXBUF_H
+
+struct pixbuf {
+ int refcnt;
+ char *filename;
+ struct pixbuf *next;
+ int width, height;
+ unsigned short pixels[];
+};
+
+struct pixbuf *pixbuf_new(int width, int height);
+struct pixbuf *pixbuf_search(char *filename);
+void pixbuf_inc_ref(struct pixbuf *p);
+void pixbuf_dec_ref(struct pixbuf *p);
+
+struct pixbuf *pixbuf_get(char *filename);
+
+#endif /* __PIXBUF_PIXBUF_H */
Please sign in to comment.
Something went wrong with that request. Please try again.