Пример #1
0
static void
ditherImage(struct pam *           const inpamP,
            const scaler *         const scalerP,
            unsigned int           const dithPower,
            struct colorResolution const colorRes,
            struct pam *           const outpamP,
            tuple ***              const outTuplesP) {

    unsigned int const dithDim = 1 << dithPower;
    unsigned int const ditherMatrixArea = SQR(dithDim);

    unsigned int const modMask = (dithDim - 1);
       /* And this into N to compute N % dithDim cheaply, since we
          know (though the compiler doesn't) that dithDim is a power of 2
       */
    unsigned int ** const ditherMatrix = dithMatrix(dithPower);

    tuple * inrow;
    tuple ** outTuples;
    unsigned int row; 
    struct pam ditherPam;
        /* Describes the tuples that ditherRow() sees */

    assert(dithPower < sizeof(unsigned int) * 8);
    assert(UINT_MAX / dithDim >= dithDim);
    
    validateNoDitherOverflow(ditherMatrixArea, inpamP, colorRes);

    inrow = pnm_allocpamrow(inpamP);

    outTuples = pnm_allocpamarray(outpamP);

    /* We will modify the input to promote it to depth 3 */
    ditherPam = *inpamP;
    ditherPam.depth = 3;

    for (row = 0; row < inpamP->height; ++row) {
        pnm_readpamrow(inpamP, inrow);

        pnm_makerowrgb(inpamP, inrow);

        ditherRow(&ditherPam, inrow, scalerP, ditherMatrix, ditherMatrixArea,
                  colorRes, row, modMask,
                  outpamP, outTuples[row]);
    }
    free(ditherMatrix);
    pnm_freepamrow(inrow);
    *outTuplesP = outTuples;
}
Пример #2
0
static void 
colormapToSquare(struct pam * const pamP,
                 tupletable2  const colormap,
                 tuple ***    const outputRasterP) {
    {
        unsigned int const intsqrt = (int)sqrt((float)colormap.size);
        if (intsqrt * intsqrt == colormap.size) 
            pamP->width = intsqrt;
        else 
            pamP->width = intsqrt + 1;
    }
    {
        unsigned int const intQuotient = colormap.size / pamP->width;
        if (pamP->width * intQuotient == colormap.size)
            pamP->height = intQuotient;
        else
            pamP->height = intQuotient + 1;
    }
    {
        tuple ** outputRaster;
        unsigned int row;
        unsigned int colormapIndex;
        
        outputRaster = pnm_allocpamarray(pamP);

        colormapIndex = 0;  /* initial value */
        
        for (row = 0; row < pamP->height; ++row) {
            unsigned int col;
            for (col = 0; col < pamP->width; ++col) {
                unsigned int plane;
                for (plane = 0; plane < pamP->depth; ++plane) {
                    outputRaster[row][col][plane] = 
                        colormap.table[colormapIndex]->tuple[plane];
                }
                if (colormapIndex < colormap.size-1)
                    ++colormapIndex;
            }
        }
        *outputRasterP = outputRaster;
    } 
}
Пример #3
0
static void 
colormapToSingleRow(struct pam * const pamP,
                    tupletable2  const colormap,
                    tuple ***    const outputRasterP) {

    tuple ** outputRaster;
    unsigned int col;
    
    pamP->width = colormap.size;
    pamP->height = 1;
    
    outputRaster = pnm_allocpamarray(pamP);
    
    for (col = 0; col < pamP->width; ++col) {
        int plane;
        for (plane = 0; plane < pamP->depth; ++plane)
            outputRaster[0][col][plane] = colormap.table[col]->tuple[plane];
    }
    *outputRasterP = outputRaster;
}
Пример #4
0
static void 
doHilbert(FILE *       const ifP,
          unsigned int const clumpSize) {
/*----------------------------------------------------------------------------
  Use hilbert space filling curve dithering
-----------------------------------------------------------------------------*/
    /*
     * This is taken from the article "Digital Halftoning with
     * Space Filling Curves" by Luiz Velho, proceedings of
     * SIGRAPH '91, page 81.
     *
     * This is not a terribly efficient or quick version of
     * this algorithm, but it seems to work. - Graeme Gill.
     * [email protected]
     *
     */
    struct pam graypam;
    struct pam bitpam;
    tuple ** grays;
    tuple ** bits;

    int end;
    int *x,*y;
    int sum;

    grays = pnm_readpam(ifP, &graypam, PAM_STRUCT_SIZE(tuple_type));

    bitpam = makeOutputPam(graypam.width, graypam.height);

    bits = pnm_allocpamarray(&bitpam);

    MALLOCARRAY(x, clumpSize);
    MALLOCARRAY(y, clumpSize);
    if (x == NULL  || y == NULL)
        pm_error("out of memory");
    initHilbert(graypam.width, graypam.height);

    sum = 0;
    end = clumpSize;

    while (end == clumpSize) {
        unsigned int i;
        /* compute the next cluster co-ordinates along hilbert path */
        for (i = 0; i < end; i++) {
            if (hilbert(&x[i],&y[i])==0)
                end = i;    /* we reached the end */
        }
        /* sum levels */
        for (i = 0; i < end; i++)
            sum += grays[y[i]][x[i]][0];
        /* dither half and half along path */
        for (i = 0; i < end; i++) {
            unsigned int const row = y[i];
            unsigned int const col = x[i];
            if (sum >= graypam.maxval) {
                bits[row][col][0] = 1;
                sum -= graypam.maxval;
            } else
                bits[row][col][0] = 0;
        }
    }
    pnm_writepam(&bitpam, bits);

    pnm_freepamarray(bits, &bitpam);
    pnm_freepamarray(grays, &graypam);
}
Пример #5
0
int
main(int argc, char **argv) {

    struct cmdlineInfo cmdline;
    FILE * ifP;
    tuplen ** tuplenarray;
    struct pam inpam;
    struct pam mappam;
    tuple ** map;
    int row;
    float * sharpness;

	pnm_init(&argc, argv);

    parseCommandLine(argc, argv, &cmdline);

    ifP = pm_openr(cmdline.inputFilespec);

	tuplenarray = pnm_readpamn(ifP, &inpam, sizeof(inpam));

    mappam = inpam;
    mappam.file = stdout;
    mappam.maxval = 255;

    MALLOCARRAY_NOFAIL(sharpness, inpam.depth);
            
    map = pnm_allocpamarray(&mappam);
    makeBlackRown(&inpam, tuplenarray[0]);
    for (row = 1; row < inpam.height-1; ++row) {
        int col;
        makeBlackTuplen(&inpam, tuplenarray[row][0]);
        for (col = 1; col < inpam.width-1; ++col) {
            int dy;
            unsigned int plane;
            
            for (plane = 0; plane < inpam.depth; ++plane)
                sharpness[plane] = 0.0;

            for (dy = -1; dy <= 1; ++dy) {
                int dx;
                for (dx = -1; dx <= 1; ++dx) {
                    if (dx != 0 || dy != 0) {
                        unsigned int plane;
                        for (plane = 0; plane < inpam.depth; ++plane) {
                            samplen const sampleval = 
                                tuplenarray[row][col][plane];
                            samplen const sampleval2 = 
                                tuplenarray[row+dy][col+dx][plane];
                            sharpness[plane] += fabs(sampleval - sampleval2);
                        }
                    }
                }
            }
            makeSharpnessPixel(&mappam, sharpness, map[row][col]);
        }
        makeBlackTuplen(&inpam, tuplenarray[row][inpam.width-1]);
    }
    makeBlackRown(&inpam, tuplenarray[inpam.height-1]);
    free(sharpness);
    
    pnm_writepam(&mappam, map);

    pnm_freepamarray(map, &mappam);
	pnm_freepamarrayn(tuplenarray, &inpam);

	return 0;
}