6 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version. The Blender
12 * Foundation also sells licenses for use in proprietary software under
13 * the Blender License. See http://www.blender.org/BL/ for information
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
26 * All rights reserved.
28 * The Original Code is: all of this file.
30 * Contributor(s): none yet.
32 * ***** END GPL/BL DUAL LICENSE BLOCK *****
37 #include "BLI_blenlib.h"
38 #include "DNA_listBase.h"
40 #include "imbuf_patch.h"
41 #include "IMB_imbuf_types.h"
42 #include "IMB_imbuf.h"
43 #include "IMB_allocimbuf.h"
51 1 - seek for a transistion in a collumn
52 2 - check the relationship with left and right,
54 Is pixel above transition to the left or right equal to the top color, seek down
56 Is pixel below transition to the left or right equal to the bottom color, seek up
60 /* there should be a funcion * to indicate if two colors are
62 * For now we use a define
66 static unsigned int anti_mask = 0xffffffff;
67 static int anti_a, anti_b, anti_g, anti_r;
69 #define compare(x, y) ((x ^ y) & anti_mask)
73 struct Edge * next, * prev;
78 static void anti_free_listarray(int count, ListBase * listarray)
82 if (listarray == 0) return;
84 for (i = 0; i < count; i++) BLI_freelistN(listarray + i);
88 static ListBase * scanimage(struct ImBuf * ibuf, int dir)
90 int step, pixels, lines, nextline, x, y, col1, col2;
92 ListBase * listarray, * curlist;
98 step = 1; nextline = ibuf->x;
99 pixels = ibuf->x; lines = ibuf->y;
102 step = ibuf->x; nextline = 1;
103 pixels = ibuf->y; lines = ibuf->x;
106 listarray = (ListBase*)MEM_callocN((lines)* sizeof(ListBase), "listarray");
107 for (y = 0; y < lines; y++){
109 rect += y * nextline;
110 curlist = listarray + y;
115 for (x = 0; x < pixels; x++) {
117 if (compare(col1, col2)) {
122 BLI_addtail(curlist, edge);
126 printf("\n\n%s: Aborting antialias !\n", ibuf->name);
127 printf("To many transitions.\nIs this a natural image ?\n\n"),
128 anti_free_listarray(lines, listarray);
140 static Edge * findmatch(Edge * first, Edge * edge)
143 int in = 0, out = 65535;
145 if (edge->prev) in = edge->prev->position;
146 if (edge->next) out = edge->next->position;
149 if (first->position < edge->position) {
150 if (first->col1 == edge->col1) {
151 if (first->position >= in) match = first;
152 } else if (first->col2 == edge->col2) {
153 if (first->next == 0) match = first;
154 else if (first->next->position >= edge->position) match = first;
155 } else if (first->col2 == edge->col1) {
156 match = 0; /* at 'sig saw' situations this one can be wrongly set */
158 } else if (first->position == edge->position) {
159 if (first->col1 == edge->col1 || first->col2 == edge->col2) match = first;
161 if (match) break; /* there is one */
163 if (first->col1 == edge->col1) {
164 if (first->prev == 0) match = first;
165 else if (first->prev->position <= edge->position) match = first;
166 } else if (first->col2 == edge->col2) {
167 if (first->position <= out) match = first;
178 static void filterdraw(unsigned int * ldest, unsigned int * lsrce, int zero, int half, int step)
184 /* we filter the pixels at ldest between in and out with pixels from lsrce
185 * weight values go from 0 to 1
190 if (count < 0) count = -count;
191 if (count <= 1) return;
194 src = (uchar *) (lsrce + (step * zero));
195 dst = (uchar *) (ldest + (step * zero));
198 src = (uchar *) (lsrce + (step * zero));
199 dst = (uchar *) (ldest + (step * zero));
205 dst += step * (count >> 1);
206 src += step * (count >> 1);
208 count = (count + 1) >> 1;
212 /* this of course gamma corrected */
214 for(; count > 0; count --) {
215 if (anti_a) dst[0] += weight * (src[0] - dst[0]);
216 if (anti_b) dst[1] += weight * (src[1] - dst[1]);
217 if (anti_g) dst[2] += weight * (src[2] - dst[2]);
218 if (anti_r) dst[3] += weight * (src[3] - dst[3]);
225 static void filterimage(struct ImBuf * ibuf, struct ImBuf * cbuf, ListBase * listarray, int dir)
227 int step, pixels, lines, nextline, y, pos, drawboth;
228 unsigned int * irect, * crect;
229 Edge * left, * middle, * right, temp, * any;
233 step = 1; nextline = ibuf->x;
234 pixels = ibuf->x; lines = ibuf->y;
237 step = ibuf->x; nextline = 1;
238 pixels = ibuf->y; lines = ibuf->x;
241 for (y = 1; y < lines - 1; y++){
243 irect += y * nextline;
245 crect += y * nextline;
247 middle = listarray[y].first;
249 left = findmatch(listarray[y - 1].first, middle);
250 right = findmatch(listarray[y + 1].first, middle);
253 if (left == 0 || right == 0) {
256 if (right) any = right;
259 pos = 2 * middle->position - any->position;
261 if (any->position < middle->position) {
262 if (pos > pixels - 1) pos = pixels - 1;
264 if (pos > middle->next->position) pos = middle->next->position;
267 if (pos > any->next->position) pos = any->next->position;
270 if (pos < 0) pos = 0;
272 if (pos < middle->prev->position) pos = middle->prev->position;
275 if (pos < any->prev->position) pos = any->prev->position;
279 if (left) right = &temp;
283 } else if (left->position == middle->position || right->position == middle->position) {
285 /* small corner, with one of the two at distance 2 (the other is at dist 0) ? */
287 if (abs(left->position - right->position) == 2) drawboth = TRUE;
288 } else if (left->position < middle->position && right->position > middle->position){
291 } else if (left->position > middle->position && right->position < middle->position){
300 filterdraw(irect, crect - nextline, left->position, middle->position, step);
301 filterdraw(irect, crect + nextline, right->position, middle->position, step);
304 middle = middle->next;
310 void IMB_antialias(struct ImBuf * ibuf)
313 ListBase * listarray;
315 if (ibuf == 0) return;
316 cbuf = IMB_dupImBuf(ibuf);
318 anti_a = (anti_mask >> 24) & 0xff;
319 anti_b = (anti_mask >> 16) & 0xff;
320 anti_g = (anti_mask >> 8) & 0xff;
321 anti_r = (anti_mask >> 0) & 0xff;
323 listarray = scanimage(cbuf, 'h');
325 filterimage(ibuf, cbuf, listarray, 'h');
326 anti_free_listarray(ibuf->y, listarray);
328 listarray = scanimage(cbuf, 'v');
330 filterimage(ibuf, cbuf, listarray, 'v');
331 anti_free_listarray(ibuf->x, listarray);
339 /* intelligent scaling */
341 static void _intel_scale(struct ImBuf * ibuf, ListBase * listarray, int dir)
343 int step, lines, nextline, x, y, col;
344 unsigned int * irect, * trect;
346 Edge * left, * right;
351 step = 1; nextline = ibuf->x;
353 tbuf = IMB_double_fast_y(ibuf);
356 step = 2 * ibuf->x; nextline = 1;
358 tbuf = IMB_double_fast_x(ibuf);
364 imb_freerectImBuf(ibuf);
365 ibuf->rect = tbuf->rect;
366 ibuf->mall |= IB_rect;
374 for (y = 0; y < lines - 2; y++){
376 irect += ((2 * y) + 1) * nextline;
378 left = listarray[y].first;
380 right = findmatch(listarray[y + 1].first, left);
382 if (left->col2 == right->col2) {
383 if (left->next && right->next) {
384 if (left->next->position >= right->position) {
385 start = ((left->position + right->position) >> 1);
386 end = ((left->next->position + right->next->position) >> 1);
388 trect = irect + (start * step);
389 for (x = start; x < end; x++) {
397 if (left->col1 == right->col1) {
398 if (left->prev && right->prev) {
399 if (left->prev->position <= right->position) {
400 end = ((left->position + right->position) >> 1);
401 start = ((left->prev->position + right->prev->position) >> 1);
403 trect = irect + (start * step);
404 for (x = start; x < end; x++) {
419 void IMB_clever_double(struct ImBuf * ibuf)
421 ListBase * listarray, * curlist;
426 if (ibuf == 0) return;
429 listarray = scanimage(ibuf, 'v');
431 for (i = 0; i < size; i++) {
432 curlist = listarray + i;
433 new = (Edge*)MEM_callocN(sizeof(Edge),"Edge");
434 new->col2 = ibuf->rect[i]; /* upper pixel */
435 new->col1 = new->col2 - 1;
436 BLI_addhead(curlist, new);
437 new = (Edge*)MEM_callocN(sizeof(Edge),"Edge");
438 new->position = ibuf->y - 1;
439 new->col1 = ibuf->rect[i + ((ibuf->y -1) * ibuf->x)]; /* bottom pixel */
440 new->col2 = new->col1 - 1;
441 BLI_addtail(curlist, new);
443 _intel_scale(ibuf, listarray, 'v');
444 anti_free_listarray(size, listarray);
447 listarray = scanimage(ibuf, 'h');
449 for (i = 0; i < size; i++) {
450 curlist = listarray + i;
451 new = (Edge*)MEM_callocN(sizeof(Edge),"Edge");
452 new->col2 = ibuf->rect[i * ibuf->x]; /* left pixel */
453 new->col1 = new->col2 - 1;
454 BLI_addhead(curlist, new);
455 new = (Edge*)MEM_callocN(sizeof(Edge),"Edge");
456 new->position = ibuf->x - 1;
457 new->col1 = ibuf->rect[((i + 1) * ibuf->x) - 1]; /* right pixel */
458 new->col2 = new->col1 - 1;
459 BLI_addtail(curlist, new);
461 _intel_scale(ibuf, listarray, 'h');
462 anti_free_listarray(size, listarray);