1/*
2 *   Buffer an Image
3 *
4 *   Copyright 2007 Sascha Sommer <saschasommer@freenet.de>
5 *
6 *   This program is free software; you can redistribute it and/or modify it
7 *   under the terms of the GNU General Public License as published by the Free
8 *   Software Foundation; either version 2 of the License, or (at your option)
9 *   any later version.
10 *
11 *   This program is distributed in the hope that it will be useful, but
12 *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 *   for more details.
15 *
16 *   You should have received a copy of the GNU General Public License
17 *   along with this program; if not, write to the Free Software
18 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24#include <gutenprint/gutenprint.h>
25#include "gutenprint-internal.h"
26
27struct buffered_image_priv
28{
29	stp_image_t* image;
30	unsigned char** buf;
31	unsigned int flags;
32};
33
34static void
35buffered_image_init(stp_image_t* image)
36{
37	struct buffered_image_priv *priv = image->rep;
38	if(priv->image->init)
39		priv->image->init(priv->image);
40}
41
42
43static int
44buffered_image_width(stp_image_t * image)
45{
46	struct buffered_image_priv *priv = image->rep;
47	return priv->image->width(priv->image);
48}
49
50static int
51buffered_image_height(stp_image_t * image)
52{
53	struct buffered_image_priv *priv = image->rep;
54	return priv->image->height(priv->image);
55}
56
57static const char *
58buffered_image_get_appname(stp_image_t *image)
59{
60	struct buffered_image_priv *priv = image->rep;
61	return priv->image->get_appname(priv->image);
62}
63
64
65static stp_image_status_t
66buffered_image_get_row(stp_image_t* image,unsigned char *data, size_t byte_limit, int row)
67{
68	struct buffered_image_priv *priv = image->rep;
69	int width = buffered_image_width(image);
70	int height = buffered_image_height(image);
71	/* FIXME this will break with padding bytes */
72	int bytes_per_pixel = byte_limit / width;
73	int inc = bytes_per_pixel;
74	unsigned char* src;
75	int i;
76	/* fill buffer */
77	if(!priv->buf){
78		priv->buf = stp_zalloc((sizeof(unsigned short*) + 1) * height);
79		if(!priv->buf){
80			return STP_IMAGE_STATUS_ABORT;
81		}
82		for(i=0;i<height;i++){
83			priv->buf[i] = stp_malloc(byte_limit);
84			if(STP_IMAGE_STATUS_OK != priv->image->get_row(priv->image,priv->buf[i],byte_limit,i))
85				return STP_IMAGE_STATUS_ABORT;
86		}
87	}
88	if(priv->flags & BUFFER_FLAG_FLIP_Y)
89		row = height - row - 1;
90
91	src = priv->buf[row];
92
93	if(priv->flags & BUFFER_FLAG_FLIP_X){
94		src += byte_limit - bytes_per_pixel;
95		inc = -bytes_per_pixel;
96	}
97
98	/* copy data */
99	for( i = 0 ; i < width ; i++){
100		memcpy(data,src,bytes_per_pixel);
101		src += inc;
102		data += bytes_per_pixel;
103	}
104	return STP_IMAGE_STATUS_OK;
105}
106
107static void
108buffered_image_conclude(stp_image_t * image)
109{
110	struct buffered_image_priv *priv = image->rep;
111	if(priv->buf){
112		int i = 0;
113		while(priv->buf[i]){
114			stp_free(priv->buf[i]);
115			++i;
116		}
117		stp_free(priv->buf);
118		priv->buf = NULL;
119	}
120	if(priv->image->conclude)
121		priv->image->conclude(priv->image);
122
123	stp_free(priv);
124	stp_free(image);
125}
126
127stp_image_t*
128stpi_buffer_image(stp_image_t* image, unsigned int flags)
129{
130	struct buffered_image_priv *priv;
131	stp_image_t* buffered_image = stp_zalloc(sizeof(stp_image_t));
132	if(!buffered_image){
133		return NULL;
134	}
135	priv = buffered_image->rep = stp_zalloc(sizeof(struct buffered_image_priv));
136	if(!priv){
137		stp_free(buffered_image);
138		return NULL;
139	}
140
141	if(image->init)
142		buffered_image->init = buffered_image_init;
143	buffered_image->width = buffered_image_width;
144	buffered_image->height = buffered_image_height;
145	buffered_image->get_row = buffered_image_get_row;
146	buffered_image->conclude = buffered_image_conclude;
147	priv->image = image;
148	priv->flags = flags;
149	if(image->get_appname)
150		buffered_image->get_appname = buffered_image_get_appname;
151
152
153	return buffered_image;
154}
155
156
157