Aurelon Open API 8.1.1
Loading...
Searching...
No Matches
AOI_Screener.cpp
1#include "./AOI_Screener.h"
2#include "../GInstance.h"
3#include <ACPL/SwapStream.h>
4
5using namespace aur;
6using namespace aur::PDF;
7using namespace aur::ACPL;
8
9typedef int16_t EDErr;
10#define kMaxDotSizes 8
11
26class AOI_Screener::Internal
27{
28public:
29 class Params
30 {
31 public:
32 // Input bitmap paramaters
33 const uint8_t* inputData;
34 uint32_t bytesPerPixel;
35 const uint16_t* transferCurve;
36 int32_t maxPixelWidth;
37 // Output device parameters
38 uint8_t* rawBuffer;
39 };
40protected:
41 uint16_t mLinCurve[256];
42 Params mParam;
43 int32_t mWidth;
44 //
45 // Aurelon screen members
46 //
47 uint16_t* mCellHandle;
48 uint16_t* mCell;
49 uint32_t mOffset;
50 uint32_t mYInCell;
51 int mBalance[256];
52 int mAntiClogLevel;
53 //
54 // Error difussion members
55 //
56 EDErr* mHorBuffer; // store the errors for the next line
57 int32_t mRightOff;
58 uint8_t mRightMask;
59 uint8_t mLevels;
60 int16_t mTreshHold[kMaxDotSizes];
61 int16_t mWeight[kMaxDotSizes];
62 const int16_t* mThreshold;
63 int16_t mThresholdArray[1000];
64 void (*mDo)( Internal* );
65public:
66 Internal( const Params&, uint16_t*, uint32_t, uint8_t, const float* );
67 ~Internal();
68 void StartPage( int32_t );
69 void Do( const uint8_t*, uint8_t* );
70 void SetNoiseFactor( int );
71private:
72 static void LeftToRight2( Internal* );
73 static void RightToLeft2( Internal* );
74 static void LeftToRight3( Internal* );
75 static void RightToLeft3( Internal* );
76 static void LeftToRight4( Internal* );
77 static void RightToLeft4( Internal* );
78 static void LeftToRight6( Internal* );
79 static void RightToLeft6( Internal* );
80 static void LeftToRight16( Internal* );
81 static void RightToLeft16( Internal* );
82 static void LeftToRight256( Internal* );
83 static void RightToLeft256( Internal* );
84
85 static void LeftToRight2_AntiClog( Internal* );
86 static void RightToLeft2_AntiClog1( Internal* );
87 static void RightToLeft2_AntiClog2( Internal* );
88};
89
90const int16_t kThresholdArray[1000] =
91{
92-30, -22, 17, -1, 3, -16, -27, 12, 12, 28, -6, 2, 22, -28, -27, 2, 11, -30, -6, -26, -4, 12, 6, 28, 23,
932, -25, 10, -4, 13, 27, 17, -14, -27, 16, -9, 9, 17, 32, -7, -15, 31, 15, 17, 10, -26, 9, 25, -13, -3,
9418, 0, -15, -13, -8, -20, 1, 26, 27, -27, 26, 1, 2, -10, 32, 1, -13, -25, 29, -26, 1, -6, -13, 27, 2,
95-1, 29, -27, 17, 18, 21, -22, -29, 13, 24, 9, 16, 15, 32, 25, -16, -11, -8, 1, 6, 23, -4, 22, -13, -4,
963, -1, -12, -19, -21, 5, 20, -28, 3, 1, 30, 16, 4, 26, 8, 22, -20, -17, 14, -22, -25, -13, -30, -4, -29,
9714, 29, -15, -20, -11, 24, 9, -22, 11, -7, -7, 0, -22, 5, 22, 5, 29, 3, -22, 30, -5, -22, 4, -15, 0,
98-2, 29, -23, -19, -11, 8, -23, 9, 7, 19, -16, -1, -7, -18, -30, 25, -4, -22, 28, -5, -23, 24, -26, -21, -27,
99-8, -15, -23, 18, -2, -9, -3, 19, 27, 9, -18, 11, 26, -15, 23, -1, 0, 6, 20, 16, -2, 28, 8, -3, 20,
10012, 12, 31, 29, 22, -13, 2, 0, -25, -5, 4, 24, -3, 14, 23, 13, 19, 13, 15, -30, 24, 1, -2, -27, 13,
1010, 10, 11, -19, 26, 23, 24, 2, -23, -3, 31, -18, -3, -11, 0, 24, -3, -2, 19, -8, -18, 31, -22, 8, 7,
102-31, -31, 17, 14, -11, -5, 11, 11, -18, 21, 13, 21, -25, -26, 16, 8, -18, -18, -26, -7, 28, 28, -7, -14, 12,
103-13, 17, 18, -4, -13, -19, -31, -19, 30, -16, 20, -23, -6, 6, -20, 21, -21, 31, -15, -17, -25, -17, 8, 12, 18,
10412, 16, 10, 8, -28, 6, -17, -11, 12, -24, 16, 1, 3, 5, -10, 12, -22, -21, 0, 23, 20, 3, 15, -11, -23,
1051, -12, 5, 1, -4, -15, -8, -6, -3, -1, -7, -14, -26, -8, -15, 10, 11, 0, 14, 14, 28, -2, 28, -11, -2,
1061, 10, -6, 6, 31, -22, 10, -9, 2, 1, 21, -31, -14, 9, 2, 26, -14, 30, -16, 22, 12, -2, 20, -30, -21,
10713, 13, -4, 5, 16, 31, 12, -14, 16, -21, -31, 0, -26, -21, 25, 18, 15, -4, -31, 5, 1, -27, 2, -7, -18,
108-7, 8, 10, 13, 2, -14, 20, -8, 11, -12, -31, -25, 1, 17, -17, -28, -27, -21, 14, -12, -28, -1, -2, 1, -3,
109-22, -13, 21, 12, 4, 11, -10, -28, 31, 2, -31, 22, -30, -7, 0, 4, 15, 11, 2, -29, -24, 30, -19, -9, 7,
1106, -23, 3, 29, -9, 21, 30, -15, -15, -4, 20, 25, -16, 16, 12, -3, -15, 10, -24, -18, -24, 3, -31, -20, 6,
111-4, -26, 11, -7, 21, -24, 30, -30, -26, 0, 17, 27, -15, -8, 17, 0, 15, 11, 11, 16, -29, -17, -17, 4, 9,
1127, -8, -17, -17, 9, -21, 15, -21, -28, 10, -24, 28, -1, 7, 26, -30, 5, 14, 0, -28, -3, 1, 17, -27, -3,
11330, -2, -10, -3, 15, -18, -21, -8, 28, 29, -15, -27, -24, 1, -21, 1, -25, 21, -8, -4, -11, 13, 4, 23, 16,
11421, 12, -7, 27, 6, -8, 2, -2, -6, -16, -26, -5, -1, -13, -25, -18, 19, 1, 10, 23, -16, 13, -15, -7, -26,
115-2, -17, 18, 0, -31, -14, 10, -4, -20, 29, -23, 18, 28, -21, 6, -27, -9, -13, 0, 20, 21, 14, -10, 19, 8,
116-29, -29, -22, 17, -28, 1, 27, -17, -18, -26, 12, 13, 0, -15, 13, -7, -19, -17, -4, -1, 23, 30, -3, -29, 1,
117-29, 16, 5, 20, -10, -17, 2, -4, -6, 31, 29, 22, 23, -12, -22, 31, 8, -2, 27, 12, 20, 2, 4, -21, 28,
11820, -22, -29, -10, -24, -25, 1, -30, 3, 22, 1, 11, 15, 12, -30, -19, 10, -9, -27, -22, 26, -17, -7, 5, -21,
119-30, 12, 16, 13, -27, 5, 27, 27, -4, 0, 21, 26, 6, 14, 1, 0, -21, 30, 4, -14, 2, 12, 10, -25, 3,
1207, 10, 0, 4, 5, -3, -22, 0, 14, -29, -28, 1, -11, -29, -16, -25, -7, 3, 6, 7, 27, 17, 0, 0, 9,
12112, -5, 0, -1, 13, 2, -14, 6, -14, 13, 1, 28, -16, -5, 6, 18, 26, 11, 20, 1, -17, -22, 25, -15, 9,
122-31, 27, -14, 22, -14, 28, 0, -24, -5, 12, -4, -25, 17, -25, -3, -9, -12, 16, -10, -10, -28, 4, 0, -19, -24,
12330, 23, 0, -8, 19, -21, -21, -28, -22, -2, -7, 24, -4, -5, 9, -12, -28, 20, 25, 26, 25, 17, -21, 4, -29,
12419, 1, 23, -14, 23, 5, -7, 19, 1, 28, -5, 5, 15, 24, -10, -19, 15, 14, 24, -27, 13, 24, -8, -26, -21,
125-5, -25, 11, 4, 20, 24, 17, 8, 25, 24, 0, -24, -7, -7, 12, -24, -27, -22, -1, 13, -16, -6, 30, 8, 11,
12626, -8, 22, 18, -4, -27, 0, -1, -3, 0, 15, 27, -12, -22, -24, -26, 30, -5, -16, 29, 21, -19, -23, -19, -10,
1274, -3, 5, -4, -8, -7, 6, -4, -22, 10, 31, 12, -6, 22, 20, 18, -8, -31, -1, 8, 9, 9, 19, -7, -9,
128-7, -10, 12, -22, -13, 10, 22, -11, -22, 6, -31, 26, -7, 1, -9, -15, -13, 21, -24, 8, -28, -2, -7, -22, 16,
12910, -31, 18, 3, -13, -5, -11, 0, 14, 21, -17, -2, -8, -28, -27, -19, 4, 21, -4, 21, -13, -20, -9, 27, 5,
130-8, -2, 8, 28, -6, -28, -3, 6, 15, 23, -23, -25, 10, 21, 5, 10, 30, -30, 26, -19, 29, 1, -14, 14, 5,
13121, 21, 10, 14, 9, -9, 2, 10, -11, 23, -3, 26, -14, 28, -24, -5, 21, 29, -10, 1, 2, 20, 27, 10, -16
132};
133const int16_t* gTresholdArray = kThresholdArray;
134
135#define CELLSIZE 1024
136#define MOD_CELLSIZE( x ) ( x & 0x3FF )
137#define MUL_CELLSIZE( x ) ( x << 10 )
138#define kTreshold 1024
139#define kTransferTo8Bit 7
140#define FloydSteinberg 0
141#define kTransferResolution 32768
142
143static const int16_t kMaxPixelWeight = ( kTransferResolution >> (kTransferTo8Bit-3) ) - 1;
144
145AOI_Screener::Internal::Internal( const Params& params, uint16_t* inCell, uint32_t offset, uint8_t levels, const float* dotSize )
146{
147 mParam = params;
148 mCellHandle = NULL;
149 mOffset = offset;
150 mAntiClogLevel = 0;
151
152 uint8_t i;
153 for( i = levels; i > 0; --i )
154 mWeight[i-1] = int16_t( dotSize[ levels-i-1 ] * kMaxPixelWeight + 0.5f );
155 mWeight[ levels-1 ] = 0;
156 //
157 // Set the threshold at half between the dotsizes. Then offset the
158 // threshold down with 4/5 of the smallest threshold to avoid
159 // wavefront effects
160 //
161 for( i = 0; i < levels-1; ++i )
162 {
163 mTreshHold[i] = ( mWeight[i] + mWeight[i+1] ) / 2;
164 mTreshHold[i] -= ( mWeight[ levels - 2 ] * 2 ) / 5;
165 }
166 mTreshHold[ levels-1 ] = 0;
167 mLevels = levels;
168 int32_t pixels = mParam.maxPixelWidth + 6;
169 mHorBuffer = new EDErr[ pixels ];
170 ::memset( mHorBuffer, 0, sizeof(EDErr) * pixels );
171 mCell = inCell;
172 if( mCell == NULL )
173 {
174 FileSpec spec;
175 char name[32];
176 ::snprintf( name, sizeof(name), "%dx%d.cell", int(CELLSIZE), int(CELLSIZE) );
177 spec.Make( Instance::sDefault->ResourceDirectory(), name );
178#if ARCH_PPC
179 FileStream cellStream( spec, eReadPermission );
180#else
181 SwapStream cellStream( spec, eReadPermission );
182#endif
183 mCellHandle = new uint16_t[ CELLSIZE * CELLSIZE ];
184 uint16_t* c = mCellHandle;
185 for( uint32_t j = 0; j != CELLSIZE * CELLSIZE; ++j )
186 {
187 cellStream >> *c;
188 ++c;
189 }
190 mCell = mCellHandle;
191 }
192 for( int j = 0; j != 256; ++j )
193 {
194 mLinCurve[j] = mParam.transferCurve[j] >> 1;
195 if( mLinCurve[j] == 0 )
196 mBalance[j] = 0;
197 else
198 mBalance[j] = int( 64 / ( double( mLinCurve[j] ) / kTransferResolution ) );
199 }
200 mParam.transferCurve = mLinCurve;
201
202 SetNoiseFactor( 1 );
203 mThreshold = mThresholdArray;
204}
205
206AOI_Screener::Internal::~Internal()
207{
208 delete[] mHorBuffer;
209 delete[] mCellHandle;
210}
211
212void AOI_Screener::Internal::SetNoiseFactor( int f )
213{
214 for( uint32_t i = 0; i != 1000; ++i )
215 mThresholdArray[i] = kThresholdArray[i] * f;
216}
217
218// init2
219//
220// returns : error if something went wrong
221void AOI_Screener::Internal::StartPage( int32_t w )
222{
223 mWidth = w;
224
225 int32_t width = mWidth;
226 switch( mLevels )
227 {
228 case 2 :
229/*
230 switch( mAntiClogLevel )
231 {
232 case 0 :
233 mDo = LeftToRight2;
234 break;
235 case 1 :
236 case 2 :
237 mDo = LeftToRight2_AntiClog;
238 break;
239 }
240*/
241 mDo = LeftToRight2_AntiClog;
242 mRightOff = width >> 3;
243 if( width % 8 )
244 mRightMask = 128 >> ( ( width % 8 ) - 1 );
245 else
246 {
247 --mRightOff;
248 mRightMask = 1;
249 }
250 break;
251 case 3 :
252 case 4 :
253 if( mLevels == 3 )
254 mDo = LeftToRight3;
255 else
256 mDo = LeftToRight4;
257 mRightOff = width >> 2;
258 if( width % 4 )
259 mRightMask = 0x40 >> ( ( ( width % 4 ) - 1 ) * 2 );
260 else
261 {
262 --mRightOff;
263 mRightMask = 1;
264 }
265 break;
266 case 5 :
267 case 6 :
268 case 7 :
269 case 8 :
270 mDo = LeftToRight6;
271 break;
272 default:
273 if( mLevels <= 16 )
274 {
275 mDo = LeftToRight16;
276 mRightOff = width >> 1;
277 if( width % 2 )
278 mRightMask = 4;
279 else
280 {
281 --mRightOff;
282 mRightMask = 0;
283 }
284 }
285 else
286 {
287 mDo = LeftToRight256;
288 mRightOff = width - 1;
289 }
290 }
291
292 mYInCell = mOffset;
293}
294
295// Do
296//
297// The main loop for Internal
298// walks through all offscreens to produce one plane of data
299// reads and writes in horBuffer
300//
301// returns : error if something went wrong
302void AOI_Screener::Internal::Do( const uint8_t* inData, uint8_t* outData )
303{
304 mParam.inputData = inData;
305 mParam.rawBuffer = outData;
306 ::memset( outData, 0, mRightOff );
307 mDo( this );
308}
309
310void AOI_Screener::Internal::LeftToRight2( Internal* obj )
311{
312 const uint8_t* src = obj->mParam.inputData;
313 uint8_t* raw = obj->mParam.rawBuffer;
314 int32_t bpp = obj->mParam.bytesPerPixel;
315 uint8_t rawMask = 0x80;
316 EDErr* horBuf = obj->mHorBuffer + 3;
317 EDErr theError = *horBuf;
318 uint16_t* cellRow = &obj->mCell[ MUL_CELLSIZE( obj->mYInCell ) ];
319 uint16_t source;
320 int threshold;
321
322 for( int32_t x = 0; x != obj->mWidth; ++x, src += bpp )
323 {
324 threshold = *obj->mThreshold + kTreshold;
325 source = obj->mParam.transferCurve[ *src ];
326 theError = EDErr( ( int32_t( theError ) + source ) >> 4 );
327 if( source && source >= cellRow[ MOD_CELLSIZE( x ) ] )
328 threshold -= obj->mBalance[ *src ];
329
330 if( theError >= threshold )
331 {
332 *raw |= rawMask;
333 theError -= kMaxPixelWeight;
334 }
335
336 if( obj->mThreshold == obj->mThresholdArray )
337 obj->mThreshold += 999;
338 else
339 --obj->mThreshold;
340
341 if( ( rawMask >>= 1 ) == 0 )
342 {
343 rawMask = 0x80;
344 ++raw;
345 }
346#if FloydSteinberg
347 horBuf[-2] += ( theError << 1 ) + theError;
348 horBuf[-1] += ( theError << 2 ) + theError;
349 *horBuf += theError;
350 ++horBuf;
351 theError = ( ( theError << 3 ) - theError ) + *horBuf;
352 *horBuf = 0;
353#else
354 theError <<= 1;
355 horBuf[-3] += theError;
356 horBuf[-1] += theError;
357 theError <<= 1;
358 *horBuf += theError;
359 ++horBuf;
360 theError <<= 1;
361 theError += *horBuf;
362 *horBuf = 0;
363#endif
364 }
365 obj->mDo = RightToLeft2;
366 if( ++obj->mYInCell == CELLSIZE )
367 obj->mYInCell = 0;
368}
369
370void AOI_Screener::Internal::RightToLeft2( Internal* obj )
371{
372 int32_t bpp = obj->mParam.bytesPerPixel;
373 uint8_t* raw = obj->mParam.rawBuffer + obj->mRightOff;
374 const uint8_t* src = obj->mParam.inputData + bpp * ( obj->mWidth - 1 );
375 EDErr* horBuf = obj->mHorBuffer + 3 + obj->mWidth - 1;
376 EDErr theError = *horBuf;
377 uint8_t rawMask = obj->mRightMask;
378 uint16_t* cellRow = &obj->mCell[ MUL_CELLSIZE( obj->mYInCell ) ];
379 uint16_t source;
380 int threshold;
381
382 for( int32_t x = obj->mWidth - 1; x >= 0 ; --x, src -= bpp )
383 {
384 threshold = *obj->mThreshold + kTreshold;
385 source = obj->mParam.transferCurve[ *src ];
386 theError = EDErr( ( int32_t( theError ) + source ) >> 4 );
387 if( source && source >= cellRow[ MOD_CELLSIZE( x ) ] )
388 threshold -= obj->mBalance[ *src ];
389
390 if( theError >= threshold )
391 {
392 *raw |= rawMask;
393 theError -= kMaxPixelWeight;
394 }
395
396 if( obj->mThreshold == obj->mThresholdArray )
397 obj->mThreshold += 999;
398 else
399 --obj->mThreshold;
400
401 if( ( rawMask <<= 1 ) == 0 )
402 {
403 rawMask = 1;
404 --raw;
405 }
406
407#if FloydSteinberg
408 horBuf[2] += ( theError << 1 ) + theError;
409 horBuf[1] += ( theError << 2 ) + theError;
410 *horBuf += theError;
411 --horBuf;
412 theError = ( ( theError << 3 ) - theError ) + *horBuf;
413 *horBuf = 0;
414#else
415 theError <<= 1;
416 horBuf[3] += theError;
417 horBuf[1] += theError;
418 theError <<= 1;
419 *horBuf += theError;
420 --horBuf;
421 theError <<= 1;
422 theError += *horBuf;
423 *horBuf = 0;
424#endif
425 }
426 obj->mDo = LeftToRight2;
427 if( ++obj->mYInCell == CELLSIZE )
428 obj->mYInCell = 0;
429}
430
431void AOI_Screener::Internal::LeftToRight3( Internal* obj )
432{
433 const uint8_t* src = obj->mParam.inputData;
434 uint8_t* raw = obj->mParam.rawBuffer;
435 int32_t bpp = obj->mParam.bytesPerPixel;
436 uint8_t rawMask = 0x40;
437 EDErr* horBuf = obj->mHorBuffer + 3;
438 EDErr theError = *horBuf;
439 EDErr treshHold0 = obj->mTreshHold[0];
440 int16_t weight0 = obj->mWeight[0];
441 EDErr treshHold1 = obj->mTreshHold[1];
442 int16_t weight1 = obj->mWeight[1];
443 int randThreshold;
444 uint16_t* cellRow = &obj->mCell[ MUL_CELLSIZE( obj->mYInCell ) ];
445 uint16_t source;
446
447 for( int32_t x = 0; x != obj->mWidth ; ++x, src += bpp )
448 {
449 randThreshold = *obj->mThreshold;
450 if( obj->mThreshold == obj->mThresholdArray )
451 obj->mThreshold += 999;
452 else
453 --obj->mThreshold;
454 source = obj->mParam.transferCurve[ *src ];
455 theError = EDErr( ( int32_t( theError ) + source ) >> 4 );
456 if( theError >= randThreshold + treshHold0 )
457 {
458 *raw |= rawMask << 1;
459 theError -= weight0;
460 }
461 else
462 {
463 if( source && source >= cellRow[ MOD_CELLSIZE( x ) ] )
464 randThreshold -= obj->mBalance[ *src ];
465 if( theError >= randThreshold + treshHold1 )
466 {
467 *raw |= rawMask;
468 theError -= weight1;
469 }
470 }
471
472 if( ( rawMask >>= 2 ) == 0 )
473 {
474 rawMask = 0x40;
475 ++raw;
476 }
477
478 theError <<= 1;
479 horBuf[-3] += theError;
480 horBuf[-1] += theError;
481 theError <<= 1;
482 *horBuf += theError;
483 ++horBuf;
484 theError <<= 1;
485 theError += *horBuf;
486 *horBuf = 0;
487 }
488 obj->mDo = RightToLeft3;
489 if( ++obj->mYInCell == CELLSIZE )
490 obj->mYInCell = 0;
491}
492
493void AOI_Screener::Internal::RightToLeft3( Internal* obj )
494{
495 uint8_t* raw = obj->mParam.rawBuffer + obj->mRightOff;
496 int32_t bpp = obj->mParam.bytesPerPixel;
497 const uint8_t* src = obj->mParam.inputData + bpp * ( obj->mWidth - 1 );
498 EDErr* horBuf = obj->mHorBuffer + 3 + obj->mWidth - 1;
499 EDErr theError = *horBuf;
500 uint8_t rawMask = obj->mRightMask;
501 EDErr treshHold0 = obj->mTreshHold[0];
502 int16_t weight0 = obj->mWeight[0];
503 EDErr treshHold1 = obj->mTreshHold[1];
504 int16_t weight1 = obj->mWeight[1];
505 int randThreshold;
506 uint16_t* cellRow = &obj->mCell[ MUL_CELLSIZE( obj->mYInCell ) ];
507 uint16_t source;
508
509
510 for( int32_t x = obj->mWidth - 1; x >= 0 ; --x, src -= bpp )
511 {
512 randThreshold = *obj->mThreshold;
513 if( obj->mThreshold == obj->mThresholdArray )
514 obj->mThreshold += 999;
515 else
516 --obj->mThreshold;
517 source = obj->mParam.transferCurve[ *src ];
518 theError = EDErr( ( int32_t( theError ) + source ) >> 4 );
519 if( theError >= randThreshold + treshHold0 )
520 {
521 *raw |= rawMask << 1;
522 theError -= weight0;
523 }
524 else
525 {
526 if( source && source >= cellRow[ MOD_CELLSIZE( x ) ] )
527 randThreshold -= obj->mBalance[ *src ];
528 if( theError >= randThreshold + treshHold1 )
529 {
530 *raw |= rawMask;
531 theError -= weight1;
532 }
533 }
534
535 if( ( rawMask <<= 2 ) == 0 )
536 {
537 rawMask = 1;
538 --raw;
539 }
540
541 theError <<= 1;
542 horBuf[3] += theError;
543 horBuf[1] += theError;
544 theError <<= 1;
545 *horBuf += theError;
546 --horBuf;
547 theError <<= 1;
548 theError += *horBuf;
549 *horBuf = 0;
550 }
551 obj->mDo = LeftToRight3;
552 if( ++obj->mYInCell == CELLSIZE )
553 obj->mYInCell = 0;
554}
555
556void AOI_Screener::Internal::LeftToRight4( Internal* obj )
557{
558 const uint8_t* src = obj->mParam.inputData;
559 uint8_t* raw = obj->mParam.rawBuffer;
560 int32_t bpp = obj->mParam.bytesPerPixel;
561 uint8_t rawMask = 0x40;
562 EDErr* horBuf = obj->mHorBuffer + 3;
563 EDErr theError = *horBuf;
564 EDErr treshHold0 = obj->mTreshHold[0];
565 EDErr treshHold1 = obj->mTreshHold[1];
566 EDErr treshHold2 = obj->mTreshHold[2];
567 int randThreshold;
568 uint16_t* cellRow = &obj->mCell[ MUL_CELLSIZE( obj->mYInCell ) ];
569 uint16_t source;
570
571 for( int32_t x = 0; x != obj->mWidth; ++x, src += bpp )
572 {
573 randThreshold = *obj->mThreshold;
574 if( obj->mThreshold == obj->mThresholdArray )
575 obj->mThreshold += 999;
576 else
577 --obj->mThreshold;
578
579 source = obj->mParam.transferCurve[ *src ];
580 theError = EDErr( ( int32_t( theError ) + source ) >> 4 );
581 if( theError >= randThreshold + treshHold0 )
582 {
583 *raw |= rawMask | ( rawMask << 1 );
584 theError -= obj->mWeight[0];
585 }
586 else if( theError >= randThreshold + treshHold1 )
587 {
588 *raw |= rawMask << 1;
589 theError -= obj->mWeight[1];
590 }
591 else
592 {
593 if( source && source >= cellRow[ MOD_CELLSIZE( x ) ] )
594 randThreshold -= obj->mBalance[ *src ];
595 if( theError >= randThreshold + treshHold2 )
596 {
597 *raw |= rawMask;
598 theError -= obj->mWeight[2];
599 }
600 }
601
602 theError <<= 1;
603 horBuf[-3] += theError;
604 horBuf[-1] += theError;
605 theError <<= 1;
606 *horBuf += theError;
607 ++horBuf;
608 theError <<= 1;
609 theError += *horBuf;
610 *horBuf = 0;
611
612 if( ( rawMask >>= 2 ) == 0 )
613 {
614 rawMask = 0x40;
615 ++raw;
616 }
617 }
618 obj->mDo = RightToLeft4;
619 if( ++obj->mYInCell == CELLSIZE )
620 obj->mYInCell = 0;
621}
622
623void AOI_Screener::Internal::RightToLeft4( Internal* obj )
624{
625 uint8_t* raw = obj->mParam.rawBuffer + obj->mRightOff;
626 int32_t bpp = obj->mParam.bytesPerPixel;
627 const uint8_t* src = obj->mParam.inputData + bpp * ( obj->mWidth - 1 );
628 EDErr* horBuf = obj->mHorBuffer + 3 + obj->mWidth - 1;
629 EDErr theError = *horBuf;
630 uint8_t rawMask = obj->mRightMask;
631 EDErr treshHold0 = obj->mTreshHold[0];
632 EDErr treshHold1 = obj->mTreshHold[1];
633 EDErr treshHold2 = obj->mTreshHold[2];
634 int randThreshold;
635 uint16_t* cellRow = &obj->mCell[ MUL_CELLSIZE( obj->mYInCell ) ];
636 uint16_t source;
637
638 for( int32_t x = obj->mWidth - 1; x >= 0 ; --x, src -= bpp )
639 {
640 randThreshold = *obj->mThreshold;
641 if( obj->mThreshold == obj->mThresholdArray )
642 obj->mThreshold += 999;
643 else
644 --obj->mThreshold;
645
646 source = obj->mParam.transferCurve[ *src ];
647 theError = EDErr( ( int32_t( theError ) + source ) >> 4 );
648 if( theError >= randThreshold + treshHold0 )
649 {
650 *raw |= rawMask | ( rawMask << 1 );
651 theError -= obj->mWeight[0];
652 }
653 else if( theError >= randThreshold + treshHold1 )
654 {
655 *raw |= rawMask << 1;
656 theError -= obj->mWeight[1];
657 }
658 else
659 {
660 if( source && source >= cellRow[ MOD_CELLSIZE( x ) ] )
661 randThreshold -= obj->mBalance[ *src ];
662 if( theError >= randThreshold + treshHold2 )
663 {
664 *raw |= rawMask;
665 theError -= obj->mWeight[2];
666 }
667 }
668
669 theError <<= 1;
670 horBuf[3] += theError;
671 horBuf[1] += theError;
672 theError <<= 1;
673 *horBuf += theError;
674 --horBuf;
675 theError <<= 1;
676 theError += *horBuf;
677 *horBuf = 0;
678
679 if( ( rawMask <<= 2 ) == 0 )
680 {
681 rawMask = 1;
682 --raw;
683 }
684 }
685 obj->mDo = LeftToRight4;
686 if( ++obj->mYInCell == CELLSIZE )
687 obj->mYInCell = 0;
688}
689
690void AOI_Screener::Internal::LeftToRight6( Internal* obj )
691{
692 const uint8_t* src = obj->mParam.inputData;
693 uint8_t* raw = obj->mParam.rawBuffer;
694 int32_t bpp = obj->mParam.bytesPerPixel;
695 const int rawShifts[] = { 5, 2, 0, 4, 1, 0, 3, 0 };
696 const int rawRestShifts[] = { 0, 0, 1, 0, 0, 2, 0, 0 };
697 uint8_t shiftIndex = 0;
698 int rest = 0;
699 int randThreshold;
700 int maxLevels = obj->mLevels - 1;
701 int l;
702 EDErr* horBuf = obj->mHorBuffer + 3;
703 EDErr theError = *horBuf;
704 uint16_t* cellRow = &obj->mCell[ MUL_CELLSIZE( obj->mYInCell ) ];
705 uint16_t source;
706
707 for( int32_t x = 0; x != obj->mWidth; ++x, src += bpp )
708 {
709 randThreshold = *obj->mThreshold;
710 if( obj->mThreshold == obj->mThresholdArray )
711 obj->mThreshold += 999;
712 else
713 --obj->mThreshold;
714
715 source = obj->mParam.transferCurve[ *src ];
716 theError = EDErr( ( int32_t( theError ) + source ) >> 4 );
717 for( l = 0; l != maxLevels; ++l )
718 {
719 if( source && l == maxLevels-1 && source >= cellRow[ MOD_CELLSIZE( x ) ] )
720 randThreshold -= obj->mBalance[ *src ];
721 if( theError >= randThreshold + obj->mTreshHold[l] )
722 {
723 if( rawShifts[ shiftIndex ] > 0 )
724 *raw |= ( maxLevels - l ) << rawShifts[ shiftIndex ];
725 else
726 {
727 *raw |= ( maxLevels - l ) >> rawRestShifts[ shiftIndex ];
728 rest = ( maxLevels - l ) & ( ( 1 << rawRestShifts[ shiftIndex ] ) - 1 );
729 }
730 theError -= obj->mWeight[l];
731 break;
732 }
733 }
734
735 theError <<= 1;
736 horBuf[-3] += theError;
737 horBuf[-1] += theError;
738 theError <<= 1;
739 *horBuf += theError;
740 ++horBuf;
741 theError <<= 1;
742 theError += *horBuf;
743 *horBuf = 0;
744
745 shiftIndex ++;
746 if( shiftIndex == 3 || shiftIndex == 6 || shiftIndex == 8 )
747 {
748 *(++raw) = rest << ( 8 - rawRestShifts[ shiftIndex - 1 ] );
749 if( shiftIndex == 8 )
750 shiftIndex = 0;
751 rest = 0;
752 }
753 }
754 obj->mRightOff = int32_t( raw - obj->mParam.rawBuffer );
755 obj->mRightMask = shiftIndex;
756 obj->mDo = RightToLeft6;
757 if( ++obj->mYInCell == CELLSIZE )
758 obj->mYInCell = 0;
759}
760
761void AOI_Screener::Internal::RightToLeft6( Internal* obj )
762{
763 uint8_t* raw = obj->mParam.rawBuffer + obj->mRightOff;
764 int32_t bpp = obj->mParam.bytesPerPixel;
765 const uint8_t* src = obj->mParam.inputData + bpp * ( obj->mWidth - 1 );
766 const int rawShifts[] = { 5, 2, 0, 4, 1, 0, 3, 0 };
767 const int rawRestShifts[] = { 0, 0, 1, 0, 0, 2, 0, 8 };
768 uint8_t shiftIndex = obj->mRightMask;
769 int rest = 0;
770 int randThreshold;
771 int maxLevels = obj->mLevels - 1;
772 int l;
773 EDErr* horBuf = obj->mHorBuffer + 3 + obj->mWidth - 1;
774 EDErr theError = *horBuf;
775 uint16_t* cellRow = &obj->mCell[ MUL_CELLSIZE( obj->mYInCell ) ];
776 uint16_t source;
777
778 if( --shiftIndex > 7 )
779 shiftIndex = 7;
780 for( int32_t x = obj->mWidth - 1; x >= 0 ; --x, src -= bpp )
781 {
782 randThreshold = *obj->mThreshold;
783 if( obj->mThreshold == obj->mThresholdArray )
784 obj->mThreshold += 999;
785 else
786 --obj->mThreshold;
787
788 source = obj->mParam.transferCurve[ *src ];
789 theError = EDErr( ( int32_t( theError ) + source ) >> 4 );
790 for( l = 0; l != maxLevels; ++l )
791 {
792 if( source && l == maxLevels-1 && source >= cellRow[ MOD_CELLSIZE( x ) ] )
793 randThreshold -= obj->mBalance[ *src ];
794 if( theError >= randThreshold + obj->mTreshHold[l] )
795 {
796 if( rawShifts[ shiftIndex ] > 0 )
797 *raw |= ( maxLevels - l ) << rawShifts[ shiftIndex ];
798 else
799 {
800 *raw |= ( maxLevels - l ) << ( 8 - rawRestShifts[ shiftIndex ] );
801 rest = ( maxLevels - l ) >> rawRestShifts[ shiftIndex ];
802 }
803 theError -= obj->mWeight[l];
804 break;
805 }
806 }
807
808 theError <<= 1;
809 horBuf[3] += theError;
810 horBuf[1] += theError;
811 theError <<= 1;
812 *horBuf += theError;
813 --horBuf;
814 theError <<= 1;
815 theError += *horBuf;
816 *horBuf = 0;
817
818 shiftIndex --;
819 if( shiftIndex == 1 || shiftIndex == 4 || shiftIndex == uint8_t( -1 ) )
820 {
821 if( raw - 1 >= obj->mParam.rawBuffer )
822 *(--raw) = rest;
823 if( shiftIndex == uint8_t( -1 ) )
824 shiftIndex = 7;
825 rest = 0;
826 }
827 }
828 obj->mDo = LeftToRight6;
829 if( ++obj->mYInCell == CELLSIZE )
830 obj->mYInCell = 0;
831}
832
833void AOI_Screener::Internal::LeftToRight16( Internal* obj )
834{
835 const uint8_t* src = obj->mParam.inputData;
836 uint8_t* raw = obj->mParam.rawBuffer;
837 int32_t bpp = obj->mParam.bytesPerPixel;
838 int rawShift = 4;
839 int randThreshold;
840 int maxLevels = obj->mLevels-1;
841 int l;
842 EDErr* horBuf = obj->mHorBuffer + 3;
843 EDErr theError = *horBuf;
844 uint16_t* cellRow = &obj->mCell[ MUL_CELLSIZE( obj->mYInCell ) ];
845 uint16_t source;
846
847 for( int32_t x = 0; x != obj->mWidth; ++x, src += bpp )
848 {
849 randThreshold = *obj->mThreshold;
850 if( obj->mThreshold == obj->mThresholdArray )
851 obj->mThreshold += 999;
852 else
853 --obj->mThreshold;
854
855 source = obj->mParam.transferCurve[ *src ];
856 theError = EDErr( ( int32_t( theError ) + source ) >> 4 );
857 for( l = 0; l != maxLevels; ++l )
858 {
859 if( source && l == maxLevels-1 && source >= cellRow[ MOD_CELLSIZE( x ) ] )
860 randThreshold -= obj->mBalance[ *src ];
861 if( theError >= randThreshold + obj->mTreshHold[l] )
862 {
863 *raw |= ( maxLevels - l ) << rawShift;
864 theError -= obj->mWeight[l];
865 break;
866 }
867 }
868
869 theError <<= 1;
870 horBuf[-3] += theError;
871 horBuf[-1] += theError;
872 theError <<= 1;
873 *horBuf += theError;
874 ++horBuf;
875 theError <<= 1;
876 theError += *horBuf;
877 *horBuf = 0;
878
879 if( rawShift == 0 )
880 {
881 rawShift = 4;
882 ++raw;
883 }
884 else
885 rawShift = 0;
886 }
887 obj->mDo = RightToLeft16;
888 if( ++obj->mYInCell == CELLSIZE )
889 obj->mYInCell = 0;
890}
891
892void AOI_Screener::Internal::RightToLeft16( Internal* obj )
893{
894 uint8_t* raw = obj->mParam.rawBuffer + obj->mRightOff;
895 int32_t bpp = obj->mParam.bytesPerPixel;
896 const uint8_t* src = obj->mParam.inputData + bpp * ( obj->mWidth - 1 );
897 int rawShift = obj->mRightMask;
898 int randThreshold;
899 int maxLevels = obj->mLevels-1;
900 int l;
901 EDErr* horBuf = obj->mHorBuffer + 3 + obj->mWidth - 1;
902 EDErr theError = *horBuf;
903 uint16_t* cellRow = &obj->mCell[ MUL_CELLSIZE( obj->mYInCell ) ];
904 uint16_t source;
905
906 for( int32_t x = obj->mWidth - 1; x >= 0 ; --x, src -= bpp )
907 {
908 randThreshold = *obj->mThreshold;
909 if( obj->mThreshold == obj->mThresholdArray )
910 obj->mThreshold += 999;
911 else
912 --obj->mThreshold;
913
914 source = obj->mParam.transferCurve[ *src ];
915 theError = EDErr( ( int32_t( theError ) + source ) >> 4 );
916 for( l = 0; l != maxLevels; ++l )
917 {
918 if( source && l == maxLevels-1 && source >= cellRow[ MOD_CELLSIZE( x ) ] )
919 randThreshold -= obj->mBalance[ *src ];
920 if( theError >= randThreshold + obj->mTreshHold[l] )
921 {
922 *raw |= ( maxLevels - l ) << rawShift;
923 theError -= obj->mWeight[l];
924 break;
925 }
926 }
927
928 theError <<= 1;
929 horBuf[3] += theError;
930 horBuf[1] += theError;
931 theError <<= 1;
932 *horBuf += theError;
933 --horBuf;
934 theError <<= 1;
935 theError += *horBuf;
936 *horBuf = 0;
937
938 if( rawShift == 0 )
939 rawShift = 4;
940 else
941 {
942 rawShift = 0;
943 --raw;
944 }
945 }
946 obj->mDo = LeftToRight16;
947 if( ++obj->mYInCell == CELLSIZE )
948 obj->mYInCell = 0;
949}
950
951void AOI_Screener::Internal::LeftToRight256( Internal* obj )
952{
953 const uint8_t* src = obj->mParam.inputData;
954 uint8_t* raw = obj->mParam.rawBuffer;
955 int32_t bpp = obj->mParam.bytesPerPixel;
956 int randThreshold;
957 int maxLevels = obj->mLevels-1;
958 int l;
959 EDErr* horBuf = obj->mHorBuffer + 3;
960 EDErr theError = *horBuf;
961 uint16_t* cellRow = &obj->mCell[ MUL_CELLSIZE( obj->mYInCell ) ];
962 uint16_t source;
963
964 for( int32_t x = 0; x != obj->mWidth; ++x, src += bpp )
965 {
966 randThreshold = *obj->mThreshold;
967 if( obj->mThreshold == obj->mThresholdArray )
968 obj->mThreshold += 999;
969 else
970 --obj->mThreshold;
971
972 source = obj->mParam.transferCurve[ *src ];
973 theError = EDErr( ( int32_t( theError ) + source ) >> 4 );
974 for( l = 0; l != maxLevels; ++l )
975 {
976 if( source && l == maxLevels-1 && source >= cellRow[ MOD_CELLSIZE( x ) ] )
977 randThreshold -= obj->mBalance[ *src ];
978 if( theError >= randThreshold + obj->mTreshHold[l] )
979 {
980 *raw = maxLevels - l;
981 theError -= obj->mWeight[l];
982 break;
983 }
984 }
985 ++raw;
986
987 theError <<= 1;
988 horBuf[-3] += theError;
989 horBuf[-1] += theError;
990 theError <<= 1;
991 *horBuf += theError;
992 ++horBuf;
993 theError <<= 1;
994 theError += *horBuf;
995 *horBuf = 0;
996 }
997 obj->mDo = RightToLeft256;
998 if( ++obj->mYInCell == CELLSIZE )
999 obj->mYInCell = 0;
1000}
1001
1002void AOI_Screener::Internal::RightToLeft256( Internal* obj )
1003{
1004 uint8_t* raw = obj->mParam.rawBuffer + obj->mRightOff;
1005 int32_t bpp = obj->mParam.bytesPerPixel;
1006 const uint8_t* src = obj->mParam.inputData + bpp * ( obj->mWidth - 1 );
1007 int randThreshold;
1008 int maxLevels = obj->mLevels-1;
1009 int l;
1010 EDErr* horBuf = obj->mHorBuffer + 3 + obj->mWidth - 1;
1011 EDErr theError = *horBuf;
1012 uint16_t* cellRow = &obj->mCell[ MUL_CELLSIZE( obj->mYInCell ) ];
1013 uint16_t source;
1014
1015 for( int32_t x = obj->mWidth - 1; x >= 0 ; --x, src -= bpp )
1016 {
1017 randThreshold = *obj->mThreshold;
1018 if( obj->mThreshold == obj->mThresholdArray )
1019 obj->mThreshold += 999;
1020 else
1021 --obj->mThreshold;
1022
1023 source = obj->mParam.transferCurve[ *src ];
1024 theError = EDErr( ( int32_t( theError ) + source ) >> 4 );
1025 for( l = 0; l != maxLevels; ++l )
1026 {
1027 if( source && l == maxLevels-1 && source >= cellRow[ MOD_CELLSIZE( x ) ] )
1028 randThreshold -= obj->mBalance[ *src ];
1029 if( theError >= randThreshold + obj->mTreshHold[l] )
1030 {
1031 *raw = maxLevels - l;
1032 theError -= obj->mWeight[l];
1033 break;
1034 }
1035 }
1036 --raw;
1037
1038 theError <<= 1;
1039 horBuf[3] += theError;
1040 horBuf[1] += theError;
1041 theError <<= 1;
1042 *horBuf += theError;
1043 --horBuf;
1044 theError <<= 1;
1045 theError += *horBuf;
1046 *horBuf = 0;
1047 }
1048 obj->mDo = LeftToRight256;
1049 if( ++obj->mYInCell == CELLSIZE )
1050 obj->mYInCell = 0;
1051}
1052
1053void AOI_Screener::Internal::LeftToRight2_AntiClog( Internal* obj )
1054{
1055 const uint8_t* src = obj->mParam.inputData;
1056 uint8_t* raw = obj->mParam.rawBuffer;
1057 int32_t bpp = obj->mParam.bytesPerPixel;
1058 uint8_t rawMask = 0x80;
1059 EDErr* horBuf = obj->mHorBuffer + 3;
1060 EDErr theError = *horBuf;
1061 uint16_t* cellRow = &obj->mCell[ MUL_CELLSIZE( obj->mYInCell ) ];
1062 uint16_t source;
1063 int threshold;
1064
1065 for( int32_t x = 0; x < obj->mWidth ; ++x, src += bpp )
1066 {
1067 threshold = *obj->mThreshold + kTreshold;
1068 source = obj->mParam.transferCurve[ *src ];
1069 theError = EDErr( ( int32_t( theError ) + source ) >> 4 );
1070 if( source && source >= cellRow[ MOD_CELLSIZE( x ) ] )
1071 threshold -= obj->mBalance[ *src ];
1072 //
1073 // Anti clog protection
1074 //
1075 if( rawMask == 2 ) // 7th bit of this byte
1076 {
1077 // 0x54 = Force a dot
1078 // 0xA8 = Avoid a dot
1079 if( *raw == 0x54 || ( *raw != 0xA8 && theError >= threshold ) )
1080 {
1081 *raw |= rawMask;
1082 theError -= kMaxPixelWeight;
1083 }
1084 }
1085 else // Regular behaviour
1086 {
1087 if( theError >= threshold )
1088 {
1089 *raw |= rawMask;
1090 theError -= kMaxPixelWeight;
1091 }
1092 }
1093
1094 if( obj->mThreshold == obj->mThresholdArray )
1095 obj->mThreshold += 999;
1096 else
1097 --obj->mThreshold;
1098
1099 if( ( rawMask >>= 1 ) == 0 )
1100 {
1101 rawMask = 0x80;
1102 ++raw;
1103 }
1104#if FloydSteinberg
1105 horBuf[-2] += ( theError << 1 ) + theError;
1106 horBuf[-1] += ( theError << 2 ) + theError;
1107 *horBuf += theError;
1108 ++horBuf;
1109 theError = ( ( theError << 3 ) - theError ) + *horBuf;
1110 *horBuf = 0;
1111#else
1112 theError <<= 1;
1113 horBuf[-3] += theError;
1114 horBuf[-1] += theError;
1115 theError <<= 1;
1116 *horBuf += theError;
1117 ++horBuf;
1118 theError <<= 1;
1119 theError += *horBuf;
1120 *horBuf = 0;
1121#endif
1122 }
1123/*
1124 obj->mDo = obj->mAntiClogLevel == 1 ? RightToLeft2_AntiClog1 : RightToLeft2_AntiClog2;
1125*/
1126 obj->mDo = RightToLeft2_AntiClog2;
1127 if( ++obj->mYInCell == CELLSIZE )
1128 obj->mYInCell = 0;
1129}
1130
1131void AOI_Screener::Internal::RightToLeft2_AntiClog1( Internal* obj )
1132{
1133 uint8_t* raw = obj->mParam.rawBuffer + obj->mRightOff;
1134 int32_t bpp = obj->mParam.bytesPerPixel;
1135 const uint8_t* src = obj->mParam.inputData + bpp * ( obj->mWidth - 1 );
1136 EDErr* horBuf = obj->mHorBuffer + 3 + obj->mWidth - 1;
1137 EDErr theError = *horBuf;
1138 uint8_t rawMask = obj->mRightMask;
1139 uint16_t* cellRow = &obj->mCell[ MUL_CELLSIZE( obj->mYInCell ) ];
1140 uint16_t source;
1141 int threshold;
1142
1143 for( int32_t x = obj->mWidth - 1; x >= 0 ; --x, src -= bpp )
1144 {
1145 threshold = *obj->mThreshold + kTreshold;
1146 source = obj->mParam.transferCurve[ *src ];
1147 theError = EDErr( ( int32_t( theError ) + source ) >> 4 );
1148 if( source && source >= cellRow[ MOD_CELLSIZE( x ) ] )
1149 threshold -= obj->mBalance[ *src ];
1150 //
1151 // Anti clog protection
1152 //
1153 if( rawMask == 0x80 ) // 8th bit of this byte
1154 {
1155 // 0x55 = Force a dot
1156 // 0xAA = Avoid a dot
1157 if( *raw == 0x55 || ( *raw != 0x2A && theError >= threshold ) )
1158 {
1159 *raw |= rawMask;
1160 theError -= kMaxPixelWeight;
1161 }
1162 }
1163 else // Regular behaviour
1164 {
1165 if( theError >= threshold )
1166 {
1167 *raw |= rawMask;
1168 theError -= kMaxPixelWeight;
1169 }
1170 }
1171
1172 if( obj->mThreshold == obj->mThresholdArray )
1173 obj->mThreshold += 999;
1174 else
1175 --obj->mThreshold;
1176
1177 if( ( rawMask <<= 1 ) == 0 )
1178 {
1179 rawMask = 1;
1180 --raw;
1181 }
1182
1183#if FloydSteinberg
1184 horBuf[2] += ( theError << 1 ) + theError;
1185 horBuf[1] += ( theError << 2 ) + theError;
1186 *horBuf += theError;
1187 --horBuf;
1188 theError = ( ( theError << 3 ) - theError ) + *horBuf;
1189 *horBuf = 0;
1190#else
1191 theError <<= 1;
1192 horBuf[3] += theError;
1193 horBuf[1] += theError;
1194 theError <<= 1;
1195 *horBuf += theError;
1196 --horBuf;
1197 theError <<= 1;
1198 theError += *horBuf;
1199 *horBuf = 0;
1200#endif
1201 }
1202 obj->mDo = LeftToRight2_AntiClog;
1203 if( ++obj->mYInCell == CELLSIZE )
1204 obj->mYInCell = 0;
1205}
1206
1207void AOI_Screener::Internal::RightToLeft2_AntiClog2( Internal* obj )
1208{
1209 uint8_t* raw = obj->mParam.rawBuffer + obj->mRightOff;
1210 int32_t bpp = obj->mParam.bytesPerPixel;
1211 const uint8_t* src = obj->mParam.inputData + bpp * ( obj->mWidth - 1 );
1212 EDErr* horBuf = obj->mHorBuffer + 3 + obj->mWidth - 1;
1213 EDErr theError = *horBuf;
1214 uint8_t rawMask = obj->mRightMask;
1215 uint16_t* cellRow = &obj->mCell[ MUL_CELLSIZE( obj->mYInCell ) ];
1216 uint16_t source;
1217 int threshold;
1218
1219 for( int32_t x = obj->mWidth - 1; x >= 0 ; --x, src -= bpp )
1220 {
1221 threshold = *obj->mThreshold + kTreshold;
1222 source = obj->mParam.transferCurve[ *src ];
1223 theError = EDErr( ( int32_t( theError ) + source ) >> 4 );
1224 if( source && source >= cellRow[ MOD_CELLSIZE( x ) ] )
1225 threshold -= obj->mBalance[ *src ];
1226 //
1227 // Anti clog protection
1228 //
1229 if( rawMask == 0x80 ) // 8th bit of this byte
1230 {
1231 // 0x55 = Force a dot
1232 // 0xAA = Avoid a dot
1233 if( (*raw>>4) == 0x5 || ( (*raw>>4) != 0x2 && theError >= threshold ) )
1234 {
1235 *raw |= rawMask;
1236 theError -= kMaxPixelWeight;
1237 }
1238 }
1239 else if( rawMask == 0x08 ) // 4th bit of this byte
1240 {
1241 // 0x55 = Force a dot
1242 // 0xAA = Avoid a dot
1243 if( *raw == 0x5 || ( *raw != 0x2 && theError >= threshold ) )
1244 {
1245 *raw |= rawMask;
1246 theError -= kMaxPixelWeight;
1247 }
1248 }
1249 else // Regular behaviour
1250 {
1251 if( theError >= threshold )
1252 {
1253 *raw |= rawMask;
1254 theError -= kMaxPixelWeight;
1255 }
1256 }
1257
1258 if( obj->mThreshold == obj->mThresholdArray )
1259 obj->mThreshold += 999;
1260 else
1261 --obj->mThreshold;
1262
1263 if( ( rawMask <<= 1 ) == 0 )
1264 {
1265 rawMask = 1;
1266 --raw;
1267 }
1268
1269#if FloydSteinberg
1270 horBuf[2] += ( theError << 1 ) + theError;
1271 horBuf[1] += ( theError << 2 ) + theError;
1272 *horBuf += theError;
1273 --horBuf;
1274 theError = ( ( theError << 3 ) - theError ) + *horBuf;
1275 *horBuf = 0;
1276#else
1277 theError <<= 1;
1278 horBuf[3] += theError;
1279 horBuf[1] += theError;
1280 theError <<= 1;
1281 *horBuf += theError;
1282 --horBuf;
1283 theError <<= 1;
1284 theError += *horBuf;
1285 *horBuf = 0;
1286#endif
1287 }
1288 obj->mDo = LeftToRight2_AntiClog;
1289 if( ++obj->mYInCell == CELLSIZE )
1290 obj->mYInCell = 0;
1291}
1292
1306AOI_Screener::AOI_Screener( const char* /* screenerType */ )
1307{
1308 if( strstr( Instance::sLicenseOptions, OPT_SCREENING ) == NULL )
1309 throw ::ExceptionCode( 1 );
1310 mInternal = NULL;
1311}
1312
1313AOI_Screener::~AOI_Screener()
1314{
1315 delete mInternal;
1316}
1317
1336void AOI_Screener::PageStart( uint32_t channelCnt, uint32_t width, uint32_t /* height */, uint32_t levels, const float* dotWeights, const uint16_t* linCurve )
1337{
1338 Internal::Params params;
1339 params.bytesPerPixel = channelCnt;
1340 params.transferCurve = linCurve;
1341 params.maxPixelWidth = width;
1342 mInternal = new Internal( params, NULL, 0, uint8_t( levels ), dotWeights + 1 );
1343 mInternal->StartPage( width );
1344}
1345
1352{
1353 delete mInternal;
1354 mInternal = NULL;
1355}
1356
1366void AOI_Screener::ProcessLine( const void* inLine, void* outLine )
1367{
1368 mInternal->Do( (const uint8_t*)inLine, (uint8_t*)outLine );
1369}
void PageStart(uint32_t channelCnt, uint32_t width, uint32_t height, uint32_t levels, const float *dotWeights, const uint16_t *linCurve)
void ProcessLine(const void *inLine, void *outLine)
AOI_Screener(const char *screenerType)