Пример #1
0
/*
** returns the index of a `key' for table traversals. First goes all
** elements in the array part, then elements in the hash part. The
** beginning of a traversal is signalled by -1.
*/
static int findindex (lua_State *L, Table *t, StkId key) {
  int i;
  if (ttisnil(key)) return -1;  /* first iteration */
  i = arrayindex(key);
  if (0 < i && i <= t->sizearray)  /* is `key' inside array part? */
    return i-1;  /* yes; that's the index (corrected to C) */
  else {
    Node *n = mainposition(t, key);
    do {  /* check whether `key' is somewhere in the chain */
      /* key may be dead already, but it is ok to use it in `next' */
      if (luaO_rawequalObj(key2tval(n), key) ||
            (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&
             gcvalue(gkey(n)) == gcvalue(key))) {
        i = cast_int(n - gnode(t, 0));  /* key index in hash table */
        /* hash elements are numbered after array ones */
        return i + t->sizearray;
      }
      else n = gnext(n);
    } while (n);
    luaG_runerror(L, "invalid key to " LUA_QL("next"));  /* key not found */
    return 0;  /* to avoid warnings */
  }
}
Пример #2
0
static int countint (const TValue *key, int *nums) {
    int k = arrayindex(key,MAXASIZE);
    if (k>0) {  /* appropriate array index? */
        nums[ceillog2( cast(unsigned int,k) )]++;  /* count as such */
        return 1;
    }
Пример #3
0
static PyObject *
dither(PyObject *self, PyObject *args) {
    /*
     * 
     */
    // params
    int w, h, type, treshhold;

    // iterators
    int x, y;

    // calculated array index
    int idx;

    

    int count;
    ERRBUFTYPE *errorBuffer, errdiv, newval, errval;
    const unsigned char *sourceImage;
    unsigned char *resultImage;
    PyObject *result;

    if (!PyArg_ParseTuple(args, "s#iiii", &sourceImage, &count, &w, &h, &type, &treshhold)) {
        return (NULL);
    }

    // create the buffers
    resultImage = (unsigned char *)malloc( count );
    errorBuffer = (ERRBUFTYPE *)malloc( count*sizeof(ERRBUFTYPE));

    // init & check the buffers
    memcpy( (void *)resultImage, (const void *)sourceImage, count);
    memset( errorBuffer, 0, count*sizeof(ERRBUFTYPE));

    if (!resultImage) {
        PyErr_NoMemory();
        return NULL;
    }

    if (!errorBuffer) {
        PyErr_NoMemory();
        return NULL;
    }


    // iterate over all pixels (x,y)
    for (y = 0; y < h; y++) {
        for (x = 0; x < w; x++) {
            // calc array index for image and error buffers
            idx = arrayindex(x, y, w);
            newval = errorBuffer[idx] + resultImage[idx];
            
            // set pixel value
            if (newval >= treshhold) {
                errval = newval - 255;
                errdiv = errval / 8;
                resultImage[idx] = 255;
            } else {
                errval = newval;
                errdiv = errval / 8;
                resultImage[idx] = 0;
            }

            // cut short if nothing to add			
            if (errdiv == 0)
                continue;
            distributeError( x, y, w, h, type, errval, resultImage, errorBuffer);
        }
    }

    // build the return value
    result = Py_BuildValue("s#", resultImage, count);
    free(errorBuffer);
    free(resultImage);
    return result;
}
Пример #4
0
static void distributeError( int x, int y,
                             int w, int h,
                             int type,
                             ERRBUFTYPE errval,
                             unsigned char destImage[], ERRBUFTYPE errorBuffer[] ) {
    /*
     * Distribute the error to neighbouring pixels.
     *
     * The distributions have been taken from
     * 
     * http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/
     *
     *
     * The errors are mine. kw 2018-01
     */

    ERRBUFTYPE errdiv1, errdiv2, errdiv3, errdiv4;
    int idx;

    if (type < 0) {
        type = 0;
    }
    if  (type >= zzsentinel) {
        type = zzsentinel-1;
    }

    switch (type){
        case atkinsondither:
            // distribute the error
            // atkinson dithering divides by eight but distributes only 6/8
            errdiv1 = errval / (UNIT * 8);
            if ( x+1 < w ) {
                // x+1 ,y
                idx = arrayindex(x+1, y, w);
                errorBuffer[idx] += errdiv1;
                if ( x+2 < w ) {
                    // x+2 ,y
                    idx = arrayindex(x+2, y, w);
                    errorBuffer[idx] += errdiv1;
                }
            }

            if ( y+1 < h ) {
                // x ,y+1
                idx = arrayindex(x, y+1, w);
                errorBuffer[idx] += errdiv1;
                if (x-1 >= 0) {
                    // x-1, y+1
                    idx = arrayindex(x-1, y+1, w);
                    errorBuffer[idx] += errdiv1;
                }
                if ( y+2 < h ) {
                    // x, y+2
                    idx = arrayindex(x, y+2, w);
                    errorBuffer[idx] += errdiv1;
                }
                if (x+1 < w) {
                    // x+1, y+1
                    idx = arrayindex(x+1, y+1, w);
                    errorBuffer[idx] += errdiv1;
                }
            }
            break;

        case floydsteinbergdither:
            errdiv1 = errval / (UNIT * 16) * 7;
            errdiv2 = errval / (UNIT * 16) * 3;
            errdiv3 = errval / (UNIT * 16) * 5;
            errdiv4 = errval / (UNIT * 16) * 1;

            if ( x+1 < w ) {
                // x+1 ,y
                idx = arrayindex(x+1, y, w);
                // 7/16
                errorBuffer[idx] += errdiv1;
                if ( y+1 < h ) {
                    // x+1 ,y+1
                    idx = arrayindex(x+1, y+1, w);
                    // 1/16
                    errorBuffer[idx] += errdiv4;
                }
            }
            if ( y+1 < h ) {
                // x ,y+1
                idx = arrayindex(x, y+1, w);
                // 5/16
                errorBuffer[idx] += errdiv3;
                
                if (x > 0) {
                    // x-1 ,y+1
                    idx = arrayindex(x-1, y+1, w);
                    // 3/16
                    errorBuffer[idx] += errdiv2;
                }
            }

            break;

        case jarvisjudiceninkedithering:
            errdiv1 = errval / (UNIT * 48) * 7;
            errdiv2 = errval / (UNIT * 48) * 5;
            errdiv3 = errval / (UNIT * 48) * 3;
            errdiv4 = errval / (UNIT * 48) * 1;

            if ( x+1 < w ) {
                // x+1 ,y
                idx = arrayindex(x+1, y, w);
                // 7/48
                errorBuffer[idx] += errdiv1;
                if ( y+1 < h ) {
                    // x+1 ,y+1
                    idx = arrayindex(x+1, y+1, w);
                    // 5/48
                    errorBuffer[idx] += errdiv2;
                }
                if ( y+2 < h ) {
                    // x+1 ,y+2
                    idx = arrayindex(x+1, y+2, w);
                    // 3/48
                    errorBuffer[idx] += errdiv3;
                }

                if ( x+2 < w ) {
                    // x+2 ,y
                    idx = arrayindex(x+2, y, w);
                    // 5/48
                    errorBuffer[idx] += errdiv2;
                    if ( y+1 < h ) {
                        // x+2 ,y+1
                        idx = arrayindex(x+2, y+1, w);
                        // 3/48
                        errorBuffer[idx] += errdiv3;
                    }
                    if ( y+2 < h ) {
                        // x+2 ,y+2
                        idx = arrayindex(x+2, y+2, w);
                        // 1/48
                        errorBuffer[idx] += errdiv4;
                    }
                }
            }

            if (y+1 < h) {
                // x, y+1
                idx = arrayindex(x, y+1, w);
                // 7/48
                errorBuffer[idx] += errdiv1;
            }
            if (y+2 < h) {
                // x, y+2
                idx = arrayindex(x, y+2, w);
                // 5/48
                errorBuffer[idx] += errdiv2;
            }

            if ( x-1 > 0 ) {
                if (y+1 < h) {
                    // x-1, y+1
                    idx = arrayindex(x-1, y+1, w);
                    // 5/48
                    errorBuffer[idx] += errdiv2;
                }
                if (y+2 < h) {
                    // x-1, y+2
                    idx = arrayindex(x-1, y+2, w);
                    // 3/48
                    errorBuffer[idx] += errdiv3;
                }
            }
            if ( x-2 > 0 ) {
                if (y+1 < h) {
                    // x-2, y+1
                    idx = arrayindex(x-2, y+1, w);
                    // 3/48
                    errorBuffer[idx] += errdiv3;
                }
                if (y+2 < h) {
                    // x-2, y+2
                    idx = arrayindex(x-2, y+2, w);
                    // 1/48
                    errorBuffer[idx] += errdiv4;
                }
            }
            break;

        case stuckidithering:
            errdiv1 = errval / (UNIT * 42) * 8;
            errdiv2 = errval / (UNIT * 42) * 4;
            errdiv3 = errval / (UNIT * 42) * 2;
            errdiv4 = errval / (UNIT * 42) * 1;
            if ( x+1 < w ) {
                // x+1 ,y
                idx = arrayindex(x+1, y, w);
                // 8/42
                errorBuffer[idx] += errdiv1;
                if ( y+1 < h ) {
                    // x+1, y+1
                    idx = arrayindex(x+1, y+1, w);
                    // 4/42
                    errorBuffer[idx] += errdiv2;
                }
                if ( y+2 < h ) {
                    // x+1, y+2
                    idx = arrayindex(x+1, y+2, w);
                    // 2/42
                    errorBuffer[idx] += errdiv3;
                }
                if ( x+2 < w ) {
                    // x+2 ,y
                    idx = arrayindex(x+2, y, w);
                    // 4/42
                    errorBuffer[idx] += errdiv2;
                    if ( y+1 < h ) {
                        // x+2, y+1
                        idx = arrayindex(x+2, y+1, w);
                        // 2/42
                        errorBuffer[idx] += errdiv3;
                    }
                    if ( y+2 < h ) {
                        // x+2, y+2
                        idx = arrayindex(x+2, y+2, w);
                        // 1/42
                        errorBuffer[idx] += errdiv4;
                    }
                }
            }
            if (y+1 < h) {
                if (x-2 > 0) {
                    idx = arrayindex(x-2, y+1, w);
                    // 2/42
                    errorBuffer[idx] += errdiv3;
                }
                if (x-1 > 0) {
                    idx = arrayindex(x-1, y+1, w);
                    // 4/42
                    errorBuffer[idx] += errdiv2;
                }
                idx = arrayindex(x, y+1, w);
                // 8/42
                errorBuffer[idx] += errdiv1;
            }
            if (y+2 < h) {
                if (x-2 > 0) {
                    idx = arrayindex(x-2, y+2, w);
                    // 1/42
                    errorBuffer[idx] += errdiv4;
                }
                if (x-1 > 0) {
                    idx = arrayindex(x-1, y+2, w);
                    // 2/42
                    errorBuffer[idx] += errdiv2;
                }
                idx = arrayindex(x, y+2, w);
                // 4/42
                errorBuffer[idx] += errdiv2;
            }
            break;

        case burkesdithering:
            errdiv1 = errval / (UNIT * 32) * 8;
            errdiv2 = errval / (UNIT * 32) * 4;
            errdiv3 = errval / (UNIT * 32) * 2;

            if ( x+1 < w ) {
                // x+1 ,y
                idx = arrayindex(x+1, y, w);
                // 8/32
                errorBuffer[idx] += errdiv1;
                if ( y+1 < h ) {
                    // x+1, y+1
                    idx = arrayindex(x+1, y+1, w);
                    // 4/32
                    errorBuffer[idx] += errdiv2;
                }
                if ( x+2 < w ) {
                    // x+2 ,y
                    idx = arrayindex(x+2, y, w);
                    // 4/32
                    errorBuffer[idx] += errdiv2;
                    if ( y+1 < h ) {
                        // x+2, y+1
                        idx = arrayindex(x+2, y+1, w);
                        // 2/32
                        errorBuffer[idx] += errdiv3;
                    }
                }
            }
            if (y+1 < h) {
                if (x-2 > 0) {
                    idx = arrayindex(x-2, y+1, w);
                    // 2/32
                    errorBuffer[idx] += errdiv3;
                }
                if (x-1 > 0) {
                    idx = arrayindex(x-1, y+1, w);
                    // 4/32
                    errorBuffer[idx] += errdiv2;
                }
                idx = arrayindex(x, y+1, w);
                // 8/32
                errorBuffer[idx] += errdiv1;
            }
            break;

        case sierra1dithering:
            errdiv1 = errval / (UNIT * 32) * 5;
            errdiv2 = errval / (UNIT * 32) * 4;
            errdiv3 = errval / (UNIT * 32) * 3;
            errdiv4 = errval / (UNIT * 32) * 2;
            if ( x+1 < w ) {
                // x+1 ,y
                idx = arrayindex(x+1, y, w);
                // 5/32
                errorBuffer[idx] += errdiv1;
                if ( y+1 < h ) {
                    // x+1, y+1
                    idx = arrayindex(x+1, y+1, w);
                    // 4/32
                    errorBuffer[idx] += errdiv2;
                }
                if ( y+2 < h ) {
                    // x+1, y+2
                    idx = arrayindex(x+1, y+2, w);
                    // 2/32
                    errorBuffer[idx] += errdiv4;
                }
                if ( x+2 < w ) {
                    // x+2 ,y
                    idx = arrayindex(x+2, y, w);
                    // 3/16
                    errorBuffer[idx] += errdiv3;
                    if ( y+1 < h ) {
                        // x+2, y+1
                        idx = arrayindex(x+2, y+1, w);
                        // 2/16
                        errorBuffer[idx] += errdiv4;
                    }
                }
            }
            if (y+1 < h) {
                if (x-2 > 0) {
                    idx = arrayindex(x-2, y+1, w);
                    // 2/32
                    errorBuffer[idx] += errdiv4;
                }
                if (x-1 > 0) {
                    idx = arrayindex(x-1, y+1, w);
                    // 4/32
                    errorBuffer[idx] += errdiv2;
                }
                idx = arrayindex(x, y+1, w);
                // 5/32
                errorBuffer[idx] += errdiv1;
            }

            if (y+2 < h) {
                if (x-1 > 0) {
                    idx = arrayindex(x-1, y+2, w);
                    // 2/32
                    errorBuffer[idx] += errdiv4;
                }
                if (x+1 < w) {
                    idx = arrayindex(x+1, y+2, w);
                    // 2/32
                    errorBuffer[idx] += errdiv4;
                }
                idx = arrayindex(x, y+2, w);
                // 3/32
                errorBuffer[idx] += errdiv3;
            }


            break;

        case sierra2dithering:
            errdiv1 = errval / (UNIT * 16) * 4;
            errdiv2 = errval / (UNIT * 16) * 3;
            errdiv3 = errval / (UNIT * 16) * 2;
            errdiv4 = errval / (UNIT * 16) * 1;
            if ( x+1 < w ) {
                // x+1 ,y
                idx = arrayindex(x+1, y, w);
                // 4/16
                errorBuffer[idx] += errdiv1;
                if ( y+1 < h ) {
                    // x+1, y+1
                    idx = arrayindex(x+1, y+1, w);
                    // 2/16
                    errorBuffer[idx] += errdiv2;
                }
                if ( x+2 < w ) {
                    // x+2 ,y
                    idx = arrayindex(x+2, y, w);
                    // 3/16
                    errorBuffer[idx] += errdiv2;
                    if ( y+1 < h ) {
                        // x+2, y+1
                        idx = arrayindex(x+2, y+1, w);
                        // 1/16
                        errorBuffer[idx] += errdiv4;
                    }
                }
            }
            if (y+1 < h) {
                if (x-2 > 0) {
                    idx = arrayindex(x-2, y+1, w);
                    // 1/16
                    errorBuffer[idx] += errdiv4;
                }
                if (x-1 > 0) {
                    idx = arrayindex(x-1, y+1, w);
                    // 2/16
                    errorBuffer[idx] += errdiv3;
                }
                idx = arrayindex(x, y+1, w);
                // 3/16
                errorBuffer[idx] += errdiv2;
            }
            break;

        case sierra3dithering:
            errdiv1 = errval / (UNIT * 4) * 2;
            errdiv2 = errval / (UNIT * 4) * 1;

            if ( x+1 < w ) {
                // x+1 ,y
                idx = arrayindex(x+1, y, w);
                // 2/4
                errorBuffer[idx] += errdiv1;
            }
            if ( y+1 < h ) {
                // x, y+1
                idx = arrayindex(x, y+1, w);
                // 1/4
                errorBuffer[idx] += errdiv2;
                if ( x-1 > 0 ) {
                    // x-1, y+1
                    idx = arrayindex(x-1, y+1, w);
                    // 1/4
                    errorBuffer[idx] += errdiv2;
                }
            }
            break;
    }
}