@@ -2107,8 +2107,8 @@ int bbepFullUpdate(FASTEPDSTATE *pState, int iClearMode, bool bKeepOn, BB_RECT *
21072107 bbepClear (pState, BB_CLEAR_LIGHTEN, 8 , pRect);
21082108 break ;
21092109 case CLEAR_FAST:
2110- bbepClear (pState, BB_CLEAR_DARKEN, 6 , pRect);
2111- bbepClear (pState, BB_CLEAR_LIGHTEN, 6 , pRect);
2110+ bbepClear (pState, BB_CLEAR_DARKEN, 8 , pRect);
2111+ bbepClear (pState, BB_CLEAR_LIGHTEN, 8 , pRect);
21122112 break ;
21132113 case CLEAR_WHITE:
21142114 if (pState->panelDef .flags & BB_PANEL_FLAG_DARK) {
@@ -2383,6 +2383,115 @@ int bbepFullUpdate(FASTEPDSTATE *pState, int iClearMode, bool bKeepOn, BB_RECT *
23832383 return BBEP_SUCCESS;
23842384} /* bbepFullUpdate() */
23852385//
2386+ // Convert the previous image buffer contents to be
2387+ // the same bit depth as the current mode (1 or 2-bpp) so that
2388+ // it can do a differential (partial/non-flickering) update
2389+ //
2390+ void bbepConvertPrevBuffer (FASTEPDSTATE *pState)
2391+ {
2392+ uint8_t *s, *d, *c;
2393+ int i, n, x, y, iSrcPitch, iDestPitch;
2394+
2395+ switch (pState->prev_mode ) {
2396+ case BB_MODE_1BPP:
2397+ iSrcPitch = pState->native_width / 8 ;
2398+ break ;
2399+ case BB_MODE_2BPP:
2400+ iSrcPitch = pState->native_width / 4 ;
2401+ break ;
2402+ case BB_MODE_4BPP:
2403+ iSrcPitch = pState->native_width / 2 ;
2404+ break ;
2405+ }
2406+ if (pState->mode == BB_MODE_1BPP) { // convert to 1-bpp
2407+ iDestPitch = pState->native_width / 8 ;
2408+ for (y=0 ; y<pState->native_height ; y++) {
2409+ s = &pState->pPrevious [iSrcPitch * y];
2410+ d = &pState->pTemp [iDestPitch * y];
2411+ c = &pState->pCurrent [iDestPitch * y];
2412+ if (pState->prev_mode == BB_MODE_2BPP) {
2413+ for (x=0 ; x<pState->native_width ; x+=8 ) { // work 8 pixels at a time
2414+ uint8_t ucSrc, ucCurr, ucDest = 0 ;
2415+ ucCurr = *c++; // get current pixels in case we need to make a decision
2416+ for (n=0 ; n<2 ; n++) { // work on 2 sets of 4 pixels
2417+ ucSrc = *s++; // get 4 source pixels
2418+ for (i=0 ; i<4 ; i++) {
2419+ ucDest <<= 1 ;
2420+ switch (ucSrc & 0xc0 ) {
2421+ case 0xc0 : // white - easy
2422+ ucDest |= 1 ; // compared pixel will be white
2423+ case 0x00 : // black - easy
2424+ break ;
2425+ case 0x80 : // light or dark gray - difficult, check current pixel
2426+ case 0x40 :
2427+ ucDest |= ((ucCurr >> 7 ) ^ 1 ); // opposite of current color
2428+ break ;
2429+ }
2430+ ucCurr <<= 1 ;
2431+ ucSrc <<= 2 ;
2432+ } // for i
2433+ } // for n
2434+ *d++ = ucDest;
2435+ } // for x
2436+ } else { // 4bpp => 1bpp
2437+ for (x=0 ; x<pState->native_width ; x+=8 ) { // work 8 pixels at a time
2438+ uint8_t ucSrc, ucCurr, ucDest = 0 ;
2439+ ucCurr = *c++; // get current pixels in case we need to make a decision
2440+ for (n=0 ; n<4 ; n++) { // work on 4 sets of 2 pixels
2441+ ucSrc = *s++; // get 2 source pixels
2442+ for (i=0 ; i<2 ; i++) {
2443+ ucDest <<= 1 ;
2444+ switch (ucSrc & 0xf0 ) {
2445+ case 0xf0 : // white - easy
2446+ ucDest |= 1 ; // compared pixel will be white
2447+ case 0x00 : // black - easy
2448+ break ;
2449+ default : // middle grays - difficult, check current pixel
2450+ ucDest |= ((ucCurr >> 7 ) ^ 1 ); // opposite of current color
2451+ break ;
2452+ }
2453+ ucCurr <<= 1 ;
2454+ ucSrc <<= 4 ;
2455+ } // for i
2456+ } // for n
2457+ *d++ = ucDest;
2458+ } // for x
2459+ } // previous pixels are 4-bpp
2460+ } // for y
2461+ } else { // convert to 2-bpp
2462+ iDestPitch = pState->native_width / 4 ;
2463+ for (y=0 ; y<pState->native_height ; y++) {
2464+ s = &pState->pPrevious [iSrcPitch * y];
2465+ d = &pState->pTemp [iDestPitch * y];
2466+ c = &pState->pCurrent [iDestPitch * y];
2467+ if (pState->prev_mode == BB_MODE_1BPP) {
2468+ const uint8_t u8Conv1To2[16 ] = {0 , 3 , 0xc , 0xf , 0x30 , 0x33 , 0x3c , 0x3f ,
2469+ 0xc0 , 0xc3 , 0xcc , 0xcf , 0xf0 , 0xf3 , 0xfc , 0xff }; // convert each nibble
2470+ // Simple direct convertsion: 0->00, 1->11
2471+ for (x=0 ; x<pState->native_width ; x += 8 ) { // work 8 pixels at a time
2472+ uint8_t ucSrc = *s++; // get 8 source pixels
2473+ *d++ = u8Conv1To2[ucSrc>>4 ];
2474+ *d++ = u8Conv1To2[ucSrc & 0xf ];
2475+ } // for x
2476+ } else { // 4bpp => 2bpp
2477+ for (x=0 ; x<pState->native_width ; x += 4 ) { // work 4 pixels at a time
2478+ uint8_t ucSrc, ucDest;
2479+ ucSrc = *s++; // get 2 source pixels
2480+ ucDest = (ucSrc & 0xc0 ); // left pixel top 2 bits
2481+ ucDest |= ((ucSrc >> 2 ) << 4 ); // right pixel top 2 bits
2482+ ucSrc = *s++; // another 2 source pixels
2483+ ucDest |= ((ucSrc >> 6 ) << 2 );
2484+ ucDest |= (ucSrc >> 2 );
2485+ *d++ = ucDest;
2486+ } // for x
2487+ } // previous pixels are 4-bpp
2488+ } // for y
2489+ }
2490+ // Now we can overwrite the old pixels with the converted ones
2491+ memcpy (pState->pPrevious , pState->pTemp , iDestPitch * pState->native_height );
2492+ pState->prev_mode = pState->mode ;
2493+ } /* bbepConvertPrevBuffer() */
2494+ //
23862495// Non-flickering update in 2-bpp gray mode
23872496//
23882497int bbep2BppPartial (FASTEPDSTATE *pState, bool bKeepOn, int iStartLine, int iEndLine)
@@ -2574,6 +2683,11 @@ int bbepPartialUpdate(FASTEPDSTATE *pState, bool bKeepOn, int iStartLine, int iE
25742683
25752684// Only supported in 1-bit mode (for now)
25762685 if (pState->mode != BB_MODE_1BPP && pState->mode != BB_MODE_2BPP) return BBEP_ERROR_BAD_PARAMETER;
2686+ if (pState->prev_mode == BB_MODE_NONE) return BBEP_ERROR_BAD_PARAMETER;
2687+
2688+ if (pState->prev_mode != pState->mode ) { // convert 1/2/4-bpp previous image to make current bit depth
2689+ bbepConvertPrevBuffer (pState);
2690+ }
25772691
25782692 if (bbepEinkPower (pState, 1 ) != BBEP_SUCCESS) return BBEP_IO_ERROR;
25792693
0 commit comments