Page 1 of 1

Trying to create a colormap for a PNG8

Posted: 2009-11-09T20:42:27-07:00
by BleuLlama
Hi all. I've been struggling today to try to get this code working. It's failing now on creation of any colormap entries other than index 0. Truecolor, truecolor with transparency work. The transparency channel of PNG8 seems to work. but I can't fill colormap entries other than entry 0 using MagickSetImageColormapColor() Any help or suggestions would be appreciated. Apologies for the organization of the code. I plan on getting it working first, then cleaning it up...

I think i need to set the number of colors for the colormap, but i can't figure out what call does this. (??)

The two parameters are image structures that contain width, height, and a data array of N pixels, where a pixel has 4 8-bit components, red, green, blue, and index. Both RGB and Index are populated with correct data. palette is simply an image of N pixels where each pixel is a palette color.

Code: Select all

void
PNG_Save (
        char * filename,        /* filename to save out to */
        IMAGE * tosave,         /* the image to save */
        IMAGE * palette         /* a palette disguised as an image - null if truecolor */
)
{
        FILE * fp = NULL;
        int width, height;

        if( tosave == NULL ) {
                fprintf( stderr, "Nothing to save.\n" );
                return;
        }
        height = tosave->height;
        width = tosave->width;

        if( width == 0 || height == 0)
        {
                fprintf(stderr, "%dx%d: Illegal image dimensions\n",
                            tosave->width, tosave->height);
                return;
        }

        fp = LS_WritableOpen( filename );
        if( !fp || tosave == NULL || filename == NULL)
        {
                if( fp ) fclose(fp);
                printf("Didn't saved nothing.\n");
                return;
        }
        fclose( fp );


        do {
                MagickWand *image_wand;
                MagickBooleanType status;
                PixelWand * aColor;
                PixelWand **pixels;
                PixelIterator *iterator;
                int x,y;
                unsigned long nw;

                MagickWandGenesis();
                image_wand = NewMagickWand();

                aColor = NewPixelWand();
                PixelSetColor( aColor, "black" );

                /* create our image */
                status = MagickNewImage( image_wand, (int)width, (int)height, aColor );
                printf( "MagickNewImage %s\n", status?"TRUE":"false" );

                status = MagickSetImageColorspace( image_wand, RGBColorspace );
                printf( "MagickSetImageColorspace %s\n", status?"TRUE":"false" );
                status = MagickSetImageDepth( image_wand, 8 );
                printf( "MagickSetImageDepth %s\n", status?"TRUE":"false" );
                status = MagickSetImageChannelDepth( image_wand, AllChannels, 8 );
                printf( "MagickSetImageChannelDepth %s\n", status?"TRUE":"false" );

                /* set the appropriate image format */
                if( palette ) {
                        status = MagickSetImageFormat( image_wand, "PNG8" );
                        printf( "MagickSetImageFormat %s\n", status?"TRUE":"false" );
                        if( ti->up->trn ) {
                                status = MagickSetImageType( image_wand, PaletteMatteType );
                                printf( "MagickSetImageType PaletteMatteType %s\n", status?"TRUE":"false" );
                        } else {
                                status = MagickSetImageType( image_wand, PaletteType );
                                printf( "MagickSetImageType PaletteType %s\n", status?"TRUE":"false" );
                        }
                } else {
                        status = MagickSetImageFormat( image_wand, "PNG32" );
                        printf( "MagickSetImageFormat %s\n", status?"TRUE":"false" );
                        if( ti->up->trn ) {
                                status = MagickSetImageType( image_wand, TrueColorMatteType );
                                printf( "MagickSetImageType TrueColorMatteType %s\n", status?"TRUE":"false" );
                        } else {
                                status = MagickSetImageType( image_wand, TrueColorType );
                                printf( "MagickSetImageType TrueColorType %s\n", status?"TRUE":"false" );
                        }
                }
                printf( "MagickSetImageType %s\n", status?"TRUE":"false" );

                /* set up the palette - fails if before or after the image buffer stuff */
                if( palette ) {
                        int cmapidx = 0;
                        for( y=0 ; y<palette->height ; y++ )
                        {
                                for( x=0 ; x<palette->width ; x++ )
                                {
                                        PixelWand * pw = NewPixelWand(); /* trying to create a new pixel wand each time. doesn't help. */
                                        int ppos = (y*palette->width) + x;
                                        int r = palette->data[ppos].r;
                                        int g = palette->data[ppos].g;
                                        int b = palette->data[ppos].b;
                                        PixelSetRed( pw, r );
                                        PixelSetGreen( pw, g );
                                        PixelSetBlue( pw, b );

                                        /*PixelSetIndex( aColor, cmapidx ); */
                                        status = MagickSetImageColormapColor( image_wand, cmapidx, pw );

                                        printf( "%s %d: %d %d %d\n", status==MagickTrue?"OK":"BAD", cmapidx, r, g, b );
                                        cmapidx++;
                                        DestroyPixelWand( pw );
                                }
                        }
                }
                /* iterate over the loaded png, and shove it into our user buf */
                iterator = NewPixelIterator( image_wand );
                if( iterator == (PixelIterator *) NULL) {
                        /* fail */
                        fprintf( stderr, "Couldn't access pixels.  Fail.\n" );
                } else {
                        for( y=0 ; y<height ; y++ )
                        {
                                pixels = PixelGetNextIteratorRow( iterator, &nw );
                                if( pixels == (PixelWand **)NULL) break;
                                for( x=0 ; x<nw ; x++ )
                                {
                                        int dpos = (y * width) + x;
                                        int r = tosave->data[dpos].r;
                                        int g = tosave->data[dpos].g;
                                        int b = tosave->data[dpos].b;
                                        int idx = tosave->data[dpos].idx;

                                        if( palette ) {
                                                PixelSetIndex( pixels[x], idx );
                                        } else {
                                                PixelSetRed( pixels[x], r );
                                                PixelSetGreen( pixels[x], g );
                                                PixelSetBlue( pixels[x], b );
                                        }

                                        /* set transparency */
                                        if( ti->up->trn ) {
                                                PixelSetAlpha( pixels[x], (idx==0)?0:255 );
                                        }
                                }
                                (void) PixelSyncIterator( iterator );
                        }
                }
                iterator = DestroyPixelIterator( iterator );

                status = MagickWriteImage( image_wand, filename );

                if( status == MagickFalse ) {
                        printf( "%s: file save error\n", filename );
                }

                image_wand = DestroyMagickWand( image_wand );
                MagickWandTerminus();

        } while( 0 );


Re: Trying to create a colormap for a PNG8

Posted: 2009-11-10T11:53:17-07:00
by BleuLlama

Code: Select all

status = AllocateImageColormap( GetImageFromMagickWand(image_wand), 255 );
This is what I had to do. I couldn't figure out any other way to set the number of colors in the colormap in the wand otherwise, and the docs (HA!) make it seem like it will expand the colormap to fit the index specified.

Re: Trying to create a colormap for a PNG8

Posted: 2009-11-10T11:55:31-07:00
by BleuLlama
nevermind. the calls don't fail now, but the colormap isn't being filled with anything.