Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Image loading library (WIP)

  • Loading branch information...
commit 1a931d94f14e97c7ba01303b0f00ffc0786afb53 1 parent 03214ca
Sébastien Bourdeauducq authored November 16, 2011
119  src/pixbuf/dither.c
... ...
@@ -0,0 +1,119 @@
  1
+/*
  2
+ * Flickernoise
  3
+ * Copyright (C) 2011 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#include <stdlib.h>
  19
+
  20
+#include "../color.h"
  21
+
  22
+static void floyd_steinberg(int *pic, int width, int height)
  23
+{
  24
+	int x, y;
  25
+	int offset;
  26
+	int old_r, old_g, old_b;
  27
+	int new_r, new_g, new_b;
  28
+	int qe_r, qe_g, qe_b;
  29
+	
  30
+	for(y=0;y<height;y++)
  31
+		for(x=0;x<width;x++) {
  32
+			offset = 3*(width*y+x);
  33
+			old_r = pic[offset];
  34
+			old_g = pic[offset+1];
  35
+			old_b = pic[offset+2];
  36
+			if(old_r > 0x00f80000)
  37
+				new_r = 0x00f80000;
  38
+			else if(old_r > 0)
  39
+				new_r = old_r & 0x00f80000;
  40
+			else
  41
+				new_r = 0;
  42
+			if(old_g > 0x00fc0000)
  43
+				new_g = 0x00fc0000;
  44
+			else if(old_g > 0)
  45
+				new_g = old_g & 0x00fc0000;
  46
+			else
  47
+				new_g = 0;
  48
+			if(old_b > 0x00f80000)
  49
+				new_b = 0x00f80000;
  50
+			else if(old_b > 0)
  51
+				new_b = old_b & 0x00f80000;
  52
+			else
  53
+				new_b = 0;
  54
+			pic[offset] = new_r;
  55
+			pic[offset+1] = new_g;
  56
+			pic[offset+2] = new_b;
  57
+			qe_r = old_r - new_r;
  58
+			qe_g = old_g - new_g;
  59
+			qe_b = old_b - new_b;
  60
+			
  61
+			if((x+1) < width) {
  62
+				pic[offset+3] += (qe_r*7) >> 4;
  63
+				pic[offset+3+1] += (qe_g*7) >> 4;
  64
+				pic[offset+3+2] += (qe_b*7) >> 4;
  65
+			}
  66
+			if((y+1) < height) {
  67
+				offset += 3*width;
  68
+				if(x > 0) {
  69
+					pic[offset-3] += (qe_r*3) >> 4;
  70
+					pic[offset-3+1] += (qe_g*3) >> 4;
  71
+					pic[offset-3+2] += (qe_b*3) >> 4;
  72
+				}
  73
+				pic[offset] += (qe_r*5) >> 4;
  74
+				pic[offset+1] += (qe_g*5) >> 4;
  75
+				pic[offset+2] += (qe_b*5) >> 4;
  76
+				if((x+1) < width) {
  77
+					pic[offset+3] += qe_r >> 4;
  78
+					pic[offset+3+1] += qe_g >> 4;
  79
+					pic[offset+3+2] += qe_b >> 4;
  80
+				}
  81
+			}
  82
+		}
  83
+}
  84
+
  85
+int pixbuf_dither(unsigned short *ret, unsigned char **row_pointers, int width, int height)
  86
+{
  87
+	int x, y;
  88
+	unsigned char *row;
  89
+	int offset;
  90
+	int *pic;
  91
+	
  92
+	pic = malloc(width*height*3*sizeof(int));
  93
+	if(pic == NULL) return 0;
  94
+	
  95
+	for(y=0;y<height;y++) {
  96
+		row = row_pointers[y];
  97
+		for(x=0;x<width;x++) {
  98
+			offset = 3*(width*y+x);
  99
+			pic[offset] = ((unsigned int)row[3*x]) << 16;
  100
+			pic[offset+1] = ((unsigned int)row[3*x+1]) << 16;
  101
+			pic[offset+2] = ((unsigned int)row[3*x+2]) << 16;
  102
+		}
  103
+	}
  104
+	
  105
+	floyd_steinberg(pic, width, height);
  106
+	
  107
+	for(y=0;y<height;y++) {
  108
+		for(x=0;x<width;x++) {
  109
+			offset = 3*(width*y+x);
  110
+			ret[width*y+x] = MAKERGB565N(pic[offset] >> 16,
  111
+				pic[offset+1] >> 16,
  112
+				pic[offset+2] >> 16);
  113
+		}
  114
+	}
  115
+	
  116
+	free(pic);
  117
+	
  118
+	return 1;
  119
+}
23  src/pixbuf/dither.h
... ...
@@ -0,0 +1,23 @@
  1
+/*
  2
+ * Flickernoise
  3
+ * Copyright (C) 2011 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#ifndef __PIXBUF_DITHER_H
  19
+#define __PIXBUF_DITHER_H
  20
+
  21
+int pixbuf_dither(unsigned short *ret, unsigned char **row_pointers, int width, int height);
  22
+
  23
+#endif /* __PIXBUF_DITHER_H */
27  src/pixbuf/loaderjpeg.c
... ...
@@ -0,0 +1,27 @@
  1
+/*
  2
+ * Flickernoise
  3
+ * Copyright (C) 2011 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#include <stdlib.h>
  19
+
  20
+#include "pixbuf.h"
  21
+#include "loaders.h"
  22
+
  23
+struct pixbuf *pixbuf_load_jpeg(char *filename)
  24
+{
  25
+	/* TODO */
  26
+	return NULL;
  27
+}
102  src/pixbuf/loaderpng.c
... ...
@@ -0,0 +1,102 @@
  1
+/*
  2
+ * Flickernoise
  3
+ * Copyright (C) 2010, 2011 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#include <stdio.h>
  19
+#include <stdlib.h>
  20
+#include <setjmp.h>
  21
+#include <png.h>
  22
+#include <zlib.h>
  23
+
  24
+#include "pixbuf.h"
  25
+#include "loaders.h"
  26
+
  27
+#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
  28
+#warning Floating point PNG is slow
  29
+#endif
  30
+
  31
+struct pixbuf *pixbuf_load_png(char *filename)
  32
+{
  33
+	struct pixbuf *ret;
  34
+	FILE *fd;
  35
+	unsigned char header[8];
  36
+	png_structp png_ptr;
  37
+	png_infop info_ptr;
  38
+	unsigned int width, height;
  39
+	png_byte color_type;
  40
+	png_byte bit_depth;
  41
+	png_bytep *row_pointers;
  42
+	size_t rowbytes;
  43
+	int y;
  44
+
  45
+	ret = NULL;
  46
+	fd = fopen(filename, "r");
  47
+	if(fd == NULL) goto free0;
  48
+	fread(header, 1, 8, fd);
  49
+	if(png_sig_cmp(header, 0, 8)) goto free1;
  50
+
  51
+	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  52
+	if(png_ptr == NULL) goto free1;
  53
+	info_ptr = png_create_info_struct(png_ptr);
  54
+	if(info_ptr == NULL) goto free2;
  55
+
  56
+	if(setjmp(png_jmpbuf(png_ptr))) goto free3;
  57
+	png_init_io(png_ptr, fd);
  58
+	png_set_sig_bytes(png_ptr, 8);
  59
+	png_read_info(png_ptr, info_ptr);
  60
+
  61
+	width = png_get_image_width(png_ptr, info_ptr);
  62
+	height = png_get_image_height(png_ptr, info_ptr);
  63
+	color_type = png_get_color_type(png_ptr, info_ptr);
  64
+	bit_depth = png_get_bit_depth(png_ptr, info_ptr);
  65
+
  66
+	if(color_type != PNG_COLOR_TYPE_RGB) goto free3;
  67
+	if(bit_depth != 8) goto free3;
  68
+
  69
+	row_pointers = calloc(sizeof(png_bytep), height);
  70
+	if(row_pointers == NULL) goto free3;
  71
+	if(setjmp(png_jmpbuf(png_ptr))) goto free4;
  72
+	rowbytes = png_get_rowbytes(png_ptr, info_ptr);
  73
+	for(y=0;y<height;y++) {
  74
+		row_pointers[y] = malloc(rowbytes);
  75
+		if(row_pointers[y] == NULL)
  76
+			goto free4;
  77
+	}
  78
+
  79
+	png_read_image(png_ptr, row_pointers);
  80
+
  81
+	ret = pixbuf_new(width, height);
  82
+	if(ret == NULL) goto free4;
  83
+	ret->filename = strdup(filename);
  84
+	if(!dither(ret->pixels, row_pointers, width, height)) {
  85
+		pixbuf_dec_ref(ret);
  86
+		ret = NULL;
  87
+		goto free4;
  88
+	}
  89
+
  90
+free4:
  91
+	for(y=0;y<height;y++)
  92
+		free(row_pointers[y]);
  93
+	free(row_pointers);
  94
+free3:
  95
+	png_destroy_info_struct(png_ptr, &info_ptr);
  96
+free2:
  97
+	png_destroy_read_struct(&png_ptr, NULL, NULL);
  98
+free1:
  99
+	fclose(fd);
  100
+free0:
  101
+	return ret;
  102
+}
26  src/pixbuf/loaders.h
... ...
@@ -0,0 +1,26 @@
  1
+/*
  2
+ * Flickernoise
  3
+ * Copyright (C) 2011 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#ifndef __PIXBUF_LOADERS_H
  19
+#define __PIXBUF_LOADERS_H
  20
+
  21
+#include "pixbuf.h"
  22
+
  23
+struct pixbuf *pixbuf_load_png(char *filename);
  24
+struct pixbuf *pixbuf_load_jpeg(char *filename);
  25
+
  26
+#endif /* __PIXBUF_LOADERS_H */
97  src/pixbuf/manager.c
... ...
@@ -0,0 +1,97 @@
  1
+/*
  2
+ * Flickernoise
  3
+ * Copyright (C) 2011 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#include <stdlib.h>
  19
+#include <string.h>
  20
+
  21
+#include "pixbuf.h"
  22
+
  23
+static struct pixbuf *head;
  24
+
  25
+struct pixbuf *pixbuf_new(int width, int height)
  26
+{
  27
+	struct pixbuf *p;
  28
+	
  29
+	p = malloc(sizeof(struct pixbuf)+width*height*2);
  30
+	if(p == NULL) return NULL;
  31
+	p->refcnt = 1;
  32
+	p->filename = NULL;
  33
+	p->next = head;
  34
+	p->width = width;
  35
+	p->height = height;
  36
+	head = p;
  37
+	return p;
  38
+}
  39
+
  40
+struct pixbuf *pixbuf_search(char *filename)
  41
+{
  42
+	struct pixbuf *p;
  43
+	
  44
+	p = head;
  45
+	while(p != NULL) {
  46
+		if((p->filename != NULL) && (strcmp(p->filename, filename) == 0))
  47
+			return p;
  48
+		p = p->next;
  49
+	}
  50
+	return NULL;
  51
+}
  52
+
  53
+void pixbuf_inc_ref(struct pixbuf *p)
  54
+{
  55
+	p->refcnt++;
  56
+}
  57
+
  58
+void pixbuf_dec_ref(struct pixbuf *p)
  59
+{
  60
+	struct pixbuf *prev;
  61
+	
  62
+	p->refcnt--;
  63
+	if(p->refcnt == 0) {
  64
+		if(p == head) {
  65
+			head = head->next;
  66
+			free(p->filename);
  67
+			free(p);
  68
+		} else {
  69
+			prev = head;
  70
+			while(prev->next != p)
  71
+				prev = prev->next;
  72
+			prev->next = p->next;
  73
+			free(p->filename);
  74
+			free(p);
  75
+		}
  76
+	}
  77
+}
  78
+
  79
+struct pixbuf *pixbuf_get(char *filename)
  80
+{
  81
+	struct pixbuf *p;
  82
+	
  83
+	p = pixbuf_search(filename);
  84
+	if(p != NULL) {
  85
+		pixbuf_inc_ref(p);
  86
+		return p;
  87
+	}
  88
+	
  89
+	/* try all loaders */
  90
+	p = pixbuf_load_png(filename);
  91
+	if(p != NULL) return p;
  92
+	p = pixbuf_load_jpeg(filename);
  93
+	if(p != NULL) return p;
  94
+	
  95
+	/* no loader was successful */
  96
+	return NULL;
  97
+}
36  src/pixbuf/pixbuf.h
... ...
@@ -0,0 +1,36 @@
  1
+/*
  2
+ * Flickernoise
  3
+ * Copyright (C) 2011 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#ifndef __PIXBUF_PIXBUF_H
  19
+#define __PIXBUF_PIXBUF_H
  20
+
  21
+struct pixbuf {
  22
+	int refcnt;
  23
+	char *filename;
  24
+	struct pixbuf *next;
  25
+	int width, height;
  26
+	unsigned short pixels[];
  27
+};
  28
+
  29
+struct pixbuf *pixbuf_new(int width, int height);
  30
+struct pixbuf *pixbuf_search(char *filename);
  31
+void pixbuf_inc_ref(struct pixbuf *p);
  32
+void pixbuf_dec_ref(struct pixbuf *p);
  33
+
  34
+struct pixbuf *pixbuf_get(char *filename);
  35
+
  36
+#endif /* __PIXBUF_PIXBUF_H */

0 notes on commit 1a931d9

Please sign in to comment.
Something went wrong with that request. Please try again.