home *** CD-ROM | disk | FTP | other *** search
- /*
- ˚¿¶±˙»¯ä¶Æ»ý¸¡
-
- Mean Density Approximation Method
- by Y.Kurosawa: "A Bilevel Display Technique for Gray Pictures Using
- Mean Density Approximation", Trans. IPSJ, Vol.26, No.1, pp.153-160,
- Jan. 1985 (in Japanese).
-
- This routine uses modified MDA method coded by Takeshi Ogihara.
- */
- #import "MDAmethod.h"
- #import <stdlib.h>
- #import <string.h>
-
- @implementation MDAmethod
-
- #define CUR_WEIGHT 10
- static const unsigned char weight[3][5] = {
- {0, 1, 2, 1, 0},
- {1, 2, 5, 2, 1},
- {2, 5, 0, 5, 2}
- };
-
-
- - init:(int)pixellevel width:(int)width
- {
- [super init];
- if ((buffer = (unsigned char *)malloc(width * 3)) == NULL) {
- [super init];
- return nil;
- }
- lines[0] = buffer;
- lines[1] = lines[0] + width;
- lines[2] = lines[1] + width;
- lnwidth = width;
- return [self reset: pixellevel];
- }
-
- - reset:(int)pixellevel
- {
- int i, v;
- float thresh, wadd;
-
- first = 1;
- thresh = 256.0 / (pixellevel - 1) + 0.1;
- leftToRight = YES;
- if (pixellevel == 2) {
- for (i = 0; i < 128; i++) grad[i] = 0;
- for ( ; i < 256; i++) grad[i] = 255;
- threshold[0] = 0;
- threshold[1] = 255;
- }else {
- wadd = thresh / 2.0;
- for (i = 0; i < 256; i++) {
- v = (int)((i + wadd) / thresh) * thresh;
- if (v >= 255) break;
- grad[i] = (v < 0) ? 0 : v;
- }
- for ( ; i < 256; i++) grad[i] = 255;
- for (i = 0; i < 16; i++) {
- if ((v = thresh * i) >= 255) {
- threshold[i] = 255;
- break;
- }
- threshold[i] = v;
- }
- }
- return self;
- }
-
- - free
- {
- free((void *)buffer);
- [super free];
- return nil;
- }
-
- - (unsigned char *)buffer
- {
- return lines[2];
- }
-
- - (unsigned char *)getNewLine
- {
- int totalv, totalw;
- int idx, i, j, w, low, high;
- unsigned char *p;
-
- if (first) {
- memcpy(lines[0], lines[2], lnwidth);
- memcpy(lines[1], lines[2], lnwidth);
- first = 0;
- }
- idx = leftToRight ? 0 : (lnwidth - 1);
- do {
- if ((low = idx - 2) < 0) low = 0;
- if ((high = idx + 2) >= lnwidth) high = lnwidth - 1;
- totalv = 0;
- totalw = 0;
- for (i = 0; i < 3; i++)
- for (j = low; j < high; j++) {
- if ((w = weight[i][j + 2 - idx]) == 0)
- continue;
- totalw += w;
- totalv += lines[i][j] * w;
- }
-
- /* (totalv + X * WEIGHT) / (totalw + WEIGHT) ~= val */
- /* (totalv + X * WEIGHT) ~= val * (totalw + WEIGHT) */
- /* X * WEIGHT ~= val * (totalw + WEIGHT) - totalv */
- w = (lines[2][idx] * (totalw + CUR_WEIGHT) - totalv)
- / CUR_WEIGHT;
- lines[2][idx] = (w > 255) ? 255 : ((w < 0) ? 0 : grad[w]);
- }while (leftToRight ? (++idx < lnwidth) : (--idx >= 0));
-
- p = lines[0];
- lines[0] = lines[1];
- lines[1] = lines[2];
- lines[2] = p;
- leftToRight = !leftToRight;
-
- return lines[1];
- }
-
- - (const unsigned char *)threshold
- {
- return threshold;
- }
-
- @end
-