This looks like a lot but its a few small changes.
[blender.git] / source / blender / imbuf / intern / ham.c
1 /**
2  *
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  * ham.c
31  *
32  * $Id$
33  */
34
35 #include "BLI_blenlib.h"
36
37 #include "imbuf.h"
38 #include "imbuf_patch.h"
39 #include "IMB_imbuf_types.h"
40 #include "IMB_imbuf.h"
41 #include "IMB_cmap.h"
42 #include "IMB_hamx.h"
43 #include "IMB_ham.h"
44
45 #ifdef HAVE_CONFIG_H
46 #include <config.h>
47 #endif
48
49 extern short alpha_col0;
50
51 #define HAMB    0x0100
52 #define HAMG    0x0400
53 #define HAMR    0x0200
54 #define HAMC    0x1000
55 #define HAMFREE 0x2000
56
57 static void addhamdither(short x, unsigned char *dit,
58                                   short dmax, unsigned char *rgb,
59                                   unsigned short *ham,
60                                   short type, short round, short shift)
61 {
62         short dx = 0;
63         short c1, c2;
64
65         for (;x>0;x--){
66                 if (ham[0] & (HAMFREE | type)){
67                         c2 = c1 = *rgb;
68                         
69                         /* wrap dither */
70                         while (dx >= dmax) dx -= dmax;
71                         
72                         c1 += dit[dx];
73                         if (c1 > 255) c1 = 255;
74                         c2 += round;
75                         if (c2 > 255) c2 = 255;
76                         
77                         if (c1 != c2){
78                                 c1 >>= shift; c2 >>= shift;
79                                 if (ham[1] & HAMFREE){
80                                         ham[0] = type + c1;
81                                         ham[1] = type + c2;
82                                 } else if (ham[1] & type){
83                                         ham[0] = type + c1;
84                                 } else if ((ham[2] & (type | HAMFREE)) == type){
85                                         ham[0] = type + c1;
86                                 } else if ((ham[1] & HAMC) | (ham[2] & HAMC)){
87                                         ham[0] = type + c1;
88                                 }
89                         }
90                 }
91                 rgb += 4;
92                 ham ++;
93                 dx ++;
94         }
95 }
96
97 static void convhamscanl(short x, short y,
98                                   unsigned char *rgbbase,
99                                   unsigned char coltab[][4],
100                                   short *deltab,
101                                   short bits)
102 {
103         int a, r, g, b, lr, lg, lb, dr, dg, db, col, fout, type, x2;
104         int round, shift;
105         uchar *rgb, dit[2];
106         unsigned short *ham, *hambase;
107
108         /* Concept:
109                 first we check the entire image, where color transitions are coded: FGRB XXXX XXXX
110                 F                       - free color value, can be changed by anyone
111                 G/R/B           - green/red/blue ham transition, only to be changed by this color
112                 XXXX XXXX       - N bits value.
113         
114                 0000 XXXX XXXX is palette color.
115         
116                 after that first the green dither is added, then the red dither, and finally blue dither
117         */
118
119         if ((hambase = (unsigned short *) malloc((x+4) * sizeof(unsigned short)))==0) return;
120
121         lb = coltab[0][1];
122         lg = coltab[0][2];
123         lr = coltab[0][3];
124         type = col = 0;
125
126         ham = hambase;
127         rgb = rgbbase;
128         
129         shift = 8 - bits;
130         round = 1 << (shift - 1);
131         
132         /* to prevent 'noise' at the end of the line */
133         for (x2 = 3; x2 >= 0; x2 --) hambase[x + x2] = HAMFREE;
134         
135         for (x2 = x ;x2 > 0; x2--){
136                 r = rgb[0] + round;
137                 g = rgb[1] + round;
138                 b = rgb[2] + round;
139                 a = rgb[3];
140                 
141                 if (a < 128 && alpha_col0) {
142                         a = 1;
143                 } else a = 0;
144                 
145                 if (b > 255) b = 255;
146                 if (g > 255) {
147                         g = 255;
148                 }
149                 if (r > 255) r = 255;
150
151                 r >>= shift;
152                 g >>= shift;
153                 b >>= shift;
154
155                 if ((b-lb) | (g-lg) | (r-lr) | a){
156                         if (a) {
157                                 col = 0;
158                                 type = HAMC;
159                         } else {
160                                 col = ((b << (2 * bits)) + (g << bits) + r) << 1;
161                                 fout = deltab[col + 1];
162                                 col = deltab[col];
163                                 type = HAMC;
164                                 
165                                 dr = quadr[lr-r];
166                                 dg = quadr[lg-g];
167                                 db = quadr[lb-b];
168         
169                                 if ((dr+dg) <= fout){
170                                         fout = dr+dg;
171                                         col = b;
172                                         type = HAMB;
173                                 }
174                                 if ((dg+db) <= fout){
175                                         fout = dg+db;
176                                         col = r;
177                                         type = HAMR;
178                                 }
179                                 if ((dr+db) <= fout){
180                                         fout = dr+db;
181                                         col = g;
182                                         type = HAMG;
183                                 }
184                         }
185                         
186                         switch(type){
187                         case HAMG:
188                                 lg = g;
189                                 break;
190                         case HAMR:
191                                 lr = r;
192                                 break;
193                         case HAMB:
194                                 lb = b;
195                                 break;
196                         default:
197                                 lb = coltab[col][1];
198                                 lg = coltab[col][2];
199                                 lr = coltab[col][3];
200                         }
201                         *ham = type + col;
202                 } else *ham = HAMG + HAMFREE + g;
203
204                 rgb += 4;
205                 ham ++;
206         }
207
208
209         if (y & 1){
210                 dit[0] = 0 << (shift - 2);
211                 dit[1] = 3 << (shift - 2);
212         } else {
213                 dit[0] = 2 << (shift - 2);
214                 dit[1] = 1 << (shift - 2);
215         }
216
217         addhamdither(x,dit,2,rgbbase+2,hambase,HAMG, round, shift);
218
219         if ((y & 1)==0){
220                 dit[0] = 3 << (shift - 2);
221                 dit[1] = 0 << (shift - 2);
222         } else {
223                 dit[0] = 1 << (shift - 2);
224                 dit[1] = 2 << (shift - 2);
225         }
226         
227         addhamdither(x,dit,2,rgbbase+3,hambase,HAMR, round, shift);
228         addhamdither(x,dit,2,rgbbase+1,hambase,HAMB, round, shift);
229
230
231         ham = hambase;
232         rgb = rgbbase;
233         rgb += 3;
234
235         for (x2=x;x2>0;x2--){
236                 type = *(ham++);
237                 if (type & HAMG) type |= HAMR | HAMB;
238
239                 *rgb = (type & 0xff) | ((type & (HAMR | HAMB)) >> shift);
240                 rgb += 4;
241         }
242
243         free (hambase);
244 }
245
246
247 short imb_converttoham(struct ImBuf *ibuf)
248 {
249         unsigned int coltab[256],*rect;
250         short x,y,* deltab;
251         int mincol;
252         
253         memcpy(coltab,ibuf->cmap,4 * ibuf->maxcol);
254
255         mincol = ibuf->mincol;  
256         if (alpha_col0 && mincol == 0) mincol = 1;
257
258         if (ibuf->ftype == AN_hamx) {
259                 deltab = imb_coldeltatab((uchar *) coltab, 0, ibuf->maxcol, 4);
260         } else {
261                 ibuf->cbits = ibuf->depth - 2;
262                 imb_losecmapbits(ibuf, coltab);
263                 deltab = imb_coldeltatab((uchar *) coltab, mincol, ibuf->maxcol, ibuf->cbits);
264         }
265         
266         rect = ibuf->rect;
267         x=ibuf->x;
268         y=ibuf->y;
269
270         if (ibuf->ftype == AN_hamx){
271                 IMB_dit2(ibuf, 2, 4);
272                 IMB_dit2(ibuf, 1, 4);
273                 IMB_dit2(ibuf, 0, 4);
274                 imb_convhamx(ibuf, coltab, deltab);
275         } else {
276                 for(;y > 0; y--){
277                         convhamscanl(x, y, (uchar *)rect, coltab, deltab, ibuf->cbits);
278                         rect += x;
279                 }
280         }
281
282         return (TRUE);
283 }