1 /*
2  * imagesource_gdkpixbuf.cpp
3  * GdkPixbuf-based image loader
4  * Supports Random Access
5  *
6  * Copyright (c) 2004 by Alastair M. Robinson
7  * Distributed under the terms of the GNU General Public License -
8  * see the file named "COPYING" for more details.
9  *
10  *
11  */
12 
13 #include <iostream>
14 #include <stdio.h>
15 #include <stdlib.h>
16 
17 #include "../support/debug.h"
18 
19 #include "imagesource_gdkpixbuf.h"
20 
21 using namespace std;
22 
23 
~ImageSource_GdkPixbuf()24 ImageSource_GdkPixbuf::~ImageSource_GdkPixbuf()
25 {
26 	if(pixbuf)
27 		g_object_unref(G_OBJECT(pixbuf));
28 }
29 
30 
31 #define OFFSET(pb, x, y) ((x) * (gdk_pixbuf_get_n_channels(pb)) + (y) * gdk_pixbuf_get_rowstride(pb))
32 
GetRow(int row)33 ISDataType *ImageSource_GdkPixbuf::GetRow(int row)
34 {
35 	unsigned char *src;
36 	ISDataType *dst;
37 
38 	if(currentrow==row)
39 		return(rowbuffer);
40 
41 	if(row>=height)
42 	{
43 		Debug[WARN] << "ImageSource_GdkPixbuf - Warning: row " << row+1 << " of " << height << " requested." << endl;
44 		return(rowbuffer);
45 	}
46 
47 	src=gdk_pixbuf_get_pixels(pixbuf)+OFFSET(pixbuf,0,row);
48 	dst=rowbuffer;
49 
50 	switch(type)
51 	{
52 		case IS_TYPE_RGB:
53 			if(hasalpha)
54 			{
55 				for(int x=0;x<width;++x)
56 				{
57 					unsigned int r,g,b,a;
58 					r=*src++;
59 					g=*src++;
60 					b=*src++;
61 					a=*src++;
62 					r=IS_SAMPLEMAX-(a*EIGHTTOIS(255-r))/255;
63 					g=IS_SAMPLEMAX-(a*EIGHTTOIS(255-g))/255;
64 					b=IS_SAMPLEMAX-(a*EIGHTTOIS(255-b))/255;
65 					*dst++=r;
66 					*dst++=g;
67 					*dst++=b;
68 				}
69 			}
70 			else
71 			{
72 				for(int x=0;x<width;++x)
73 				{
74 					unsigned int g;
75 					g=*src++;
76 					*dst++=EIGHTTOIS(g);
77 					g=*src++;
78 					*dst++=EIGHTTOIS(g);
79 					g=*src++;
80 					*dst++=EIGHTTOIS(g);
81 				}
82 			}
83 			break;
84 		case IS_TYPE_RGBA:
85 			for(int x=0;x<width;++x)
86 			{
87 				unsigned int g;
88 				g=*src++;
89 				*dst++=EIGHTTOIS(g);
90 				g=*src++;
91 				*dst++=EIGHTTOIS(g);
92 				g=*src++;
93 				*dst++=EIGHTTOIS(g);
94 				g=*src++;
95 				*dst++=EIGHTTOIS(g);
96 			}
97 			break;
98 		default:
99 			throw "Only RGB pixbufs are currently supported";
100 			break;
101 	}
102 
103 	currentrow=row;
104 	return(rowbuffer);
105 }
106 
107 
ImageSource_GdkPixbuf(const char * filename)108 ImageSource_GdkPixbuf::ImageSource_GdkPixbuf(const char *filename) : pixbuf(NULL)
109 {
110 	GError *err=NULL;
111 	pixbuf=gdk_pixbuf_new_from_file(filename,&err);
112 	if(!pixbuf)
113 		throw err->message;
114 	Init();
115 }
116 
117 
ImageSource_GdkPixbuf(GdkPixbuf * pixbuf)118 ImageSource_GdkPixbuf::ImageSource_GdkPixbuf(GdkPixbuf *pixbuf) : pixbuf(pixbuf)
119 {
120 	g_object_ref(G_OBJECT(pixbuf));
121 	Init();
122 }
123 
124 
Init()125 void ImageSource_GdkPixbuf::Init()
126 {
127 	xres=yres=72;  // FIXME - read these from the file
128 	embeddedprofile=NULL;
129 
130 	if(gdk_pixbuf_get_colorspace(pixbuf)!=GDK_COLORSPACE_RGB)
131 		throw "GdkPixbuf loader only supports RGB images!";
132 
133 	if(gdk_pixbuf_get_bits_per_sample(pixbuf)!=8)
134 		throw "GdxPixbuf loader doesn't yet support 16 bit images\n"\
135 		"Please contact me at blackfive@fakenhamweb.co.uk\n"\
136 		"And I'll try to add native support for this file format.";
137 
138 	type=IS_TYPE_RGB;
139 	samplesperpixel=3;
140 
141 	width=gdk_pixbuf_get_width(pixbuf);
142 	height=gdk_pixbuf_get_height(pixbuf);
143 	rowstride=gdk_pixbuf_get_rowstride(pixbuf);
144 	pixels=gdk_pixbuf_get_pixels(pixbuf);
145 	hasalpha=gdk_pixbuf_get_has_alpha(pixbuf);
146 
147 	if(hasalpha)
148 	{
149 		type=IS_TYPE_RGBA;
150 		++samplesperpixel;
151 	}
152 
153 	MakeRowBuffer();
154 	randomaccess=true;
155 }
156 
157