2 #include "fitz-stream.h"
4 /* TODO: check if this works with 16bpp images */
8 typedef struct fz_predict_s fz_predict
;
27 fz_newpredict(fz_filter
**fp
, fz_obj
*params
, int encode
)
31 FZ_NEWFILTER(fz_predict
, p
, predict
);
40 obj
= fz_dictgets(params
, "Predictor");
41 if (obj
) p
->predictor
= fz_toint(obj
);
43 obj
= fz_dictgets(params
, "Columns");
44 if (obj
) p
->columns
= fz_toint(obj
);
46 obj
= fz_dictgets(params
, "Colors");
47 if (obj
) p
->colors
= fz_toint(obj
);
49 obj
= fz_dictgets(params
, "BitsPerComponent");
50 if (obj
) p
->bpc
= fz_toint(obj
);
52 p
->stride
= (p
->bpc
* p
->colors
* p
->columns
+ 7) / 8;
53 p
->bpp
= (p
->bpc
* p
->colors
+ 7) / 8;
55 if (p
->predictor
>= 10) {
56 p
->ref
= fz_malloc(p
->stride
);
57 if (!p
->ref
) { fz_free(p
); return fz_outofmem
; }
58 memset(p
->ref
, 0, p
->stride
);
68 fz_droppredict(fz_filter
*filter
)
70 fz_predict
*p
= (fz_predict
*)filter
;
75 getcomponent(unsigned char *buf
, int x
, int bpc
)
79 case 1: return buf
[x
/ 8] >> (7 - (x
% 8)) & 0x01;
80 case 2: return buf
[x
/ 4] >> ((3 - (x
% 4)) * 2) & 0x03;
81 case 4: return buf
[x
/ 2] >> ((1 - (x
% 2)) * 4) & 0x0f;
82 case 8: return buf
[x
];
88 putcomponent(unsigned char *buf
, int x
, int bpc
, int value
)
92 case 1: buf
[x
/ 8] |= value
<< (7 - (x
% 8)); break;
93 case 2: buf
[x
/ 4] |= value
<< ((3 - (x
% 4)) * 2); break;
94 case 4: buf
[x
/ 2] |= value
<< ((1 - (x
% 2)) * 4); break;
95 case 8: buf
[x
] = value
; break;
100 paeth(int a
, int b
, int c
)
102 /* The definitions of ac and bc are correct, not a typo. */
103 int ac
= b
- c
, bc
= a
- c
, abcc
= ac
+ bc
;
104 int pa
= (ac
< 0 ? -ac
: ac
);
105 int pb
= (bc
< 0 ? -bc
: bc
);
106 int pc
= (abcc
< 0 ? -abcc
: abcc
);
107 return pa
<= pb
&& pa
<= pc
? a
: pb
<= pc
? b
: c
;
111 none(fz_predict
*p
, unsigned char *in
, unsigned char *out
)
113 memcpy(out
, in
, p
->stride
);
117 tiff(fz_predict
*p
, unsigned char *in
, unsigned char *out
)
122 for (k
= 0; k
< p
->colors
; k
++)
125 for (i
= 0; i
< p
->columns
; i
++) {
126 for (k
= 0; k
< p
->colors
; k
++) {
127 int a
= getcomponent(in
, i
* p
->colors
+ k
, p
->bpc
);
128 int b
= p
->encode
? a
- left
[k
] : a
+ left
[k
];
129 int c
= b
% (1 << p
->bpc
);
130 putcomponent(out
, i
* p
->colors
+ k
, p
->bpc
, c
);
131 left
[k
] = p
->encode
? a
: c
;
137 png(fz_predict
*p
, unsigned char *in
, unsigned char *out
, int predictor
)
139 int upleft
[MAXC
], left
[MAXC
], i
, k
;
141 for (k
= 0; k
< p
->bpp
; k
++) {
148 for (k
= 0, i
= 0; i
< p
->stride
; k
= (k
+ 1) % p
->bpp
, i
++)
152 case 0: out
[i
] = in
[i
]; break;
153 case 1: out
[i
] = in
[i
] - left
[k
]; break;
154 case 2: out
[i
] = in
[i
] - p
->ref
[i
]; break;
155 case 3: out
[i
] = in
[i
] - (left
[k
] + p
->ref
[i
]) / 2; break;
156 case 4: out
[i
] = in
[i
] - paeth(left
[k
], p
->ref
[i
], upleft
[k
]); break;
159 upleft
[k
] = p
->ref
[i
];
165 for (k
= 0, i
= 0; i
< p
->stride
; k
= (k
+ 1) % p
->bpp
, i
++)
169 case 0: out
[i
] = in
[i
]; break;
170 case 1: out
[i
] = in
[i
] + left
[k
]; break;
171 case 2: out
[i
] = in
[i
] + p
->ref
[i
]; break;
172 case 3: out
[i
] = in
[i
] + (left
[k
] + p
->ref
[i
]) / 2; break;
173 case 4: out
[i
] = in
[i
] + paeth(left
[k
], p
->ref
[i
], upleft
[k
]); break;
176 upleft
[k
] = p
->ref
[i
];
182 fz_processpredict(fz_filter
*filter
, fz_buffer
*in
, fz_buffer
*out
)
184 fz_predict
*dec
= (fz_predict
*)filter
;
185 int ispng
= dec
->predictor
>= 10;
190 if (in
->rp
+ dec
->stride
+ (!dec
->encode
&& ispng
) > in
->wp
) {
196 if (out
->wp
+ dec
->stride
+ (dec
->encode
&& ispng
) > out
->ep
)
199 if (dec
->predictor
== 1) {
200 none(dec
, in
->rp
, out
->wp
);
202 else if (dec
->predictor
== 2) {
204 memset(out
->wp
, 0, dec
->stride
);
205 tiff(dec
, in
->rp
, out
->wp
);
209 predictor
= dec
->predictor
- 10;
210 if (predictor
< 0 || predictor
> 4)
212 *out
->wp
++ = predictor
;
215 predictor
= *in
->rp
++;
217 png(dec
, in
->rp
, out
->wp
, predictor
);
221 memcpy(dec
->ref
, out
->wp
, dec
->stride
);
223 in
->rp
+= dec
->stride
;
224 out
->wp
+= dec
->stride
;
229 fz_newpredictd(fz_filter
**fp
, fz_obj
*params
)
231 return fz_newpredict(fp
, params
, 0);
235 fz_newpredicte(fz_filter
**fp
, fz_obj
*params
)
237 return fz_newpredict(fp
, params
, 1);