001    /*
002     * PaletteSerialization
003     *
004     * Copyright (c) 2001, 2002, 2003 Marco Schmidt.
005     * All rights reserved.
006     */
007    
008    package net.sourceforge.jiu.color.io;
009    
010    import java.io.File;
011    import java.io.FileOutputStream;
012    import java.io.IOException;
013    import java.util.Vector;
014    import net.sourceforge.jiu.codecs.ImageLoader;
015    import net.sourceforge.jiu.codecs.PNMCodec;
016    import net.sourceforge.jiu.data.MemoryRGB24Image;
017    import net.sourceforge.jiu.data.Palette;
018    import net.sourceforge.jiu.data.PixelImage;
019    import net.sourceforge.jiu.data.RGB24Image;
020    import net.sourceforge.jiu.data.RGBIndex;
021    import net.sourceforge.jiu.ops.OperationFailedException;
022    
023    /**
024     * This class loads and saves palettes.
025     * Loading is done using the {@link ImageLoader} class - an image
026     * is loaded which is supposed to have no more than 256 pixels, the palette entries.
027     * When saving, the {@link PNMCodec} is used to store palettes as .ppm files.
028     *
029     * @author Marco Schmidt
030     * @since 0.5.0
031     */
032    public class PaletteSerialization implements RGBIndex
033    {
034            private PaletteSerialization()
035            {
036            }
037    
038            /**
039             * Create a palette from the pixels of the argument image.
040             */
041            public static Palette convertImageToPalette(RGB24Image image)
042            {
043                    if (image == null)
044                    {
045                            return null;
046                    }
047                    int numPixels = image.getWidth() * image.getHeight();
048                    if (numPixels > 256)
049                    {
050                            // too many pixels
051                            return null;
052                    }
053                    Palette result = new Palette(numPixels, 255);
054                    int index = 0;
055                    for (int y = 0; y < image.getHeight(); y++)
056                    {
057                            for (int x = 0; x < image.getWidth(); x++)
058                            {
059                                    result.put(index++, image.getSample(INDEX_RED, x, y), 
060                                            image.getSample(INDEX_GREEN, x, y), 
061                                            image.getSample(INDEX_BLUE, x, y));
062                            }
063                    }
064                    return result;
065            }
066    
067            /**
068             * Creates an RGB24Image from the palette entries, each entry
069             * becomes a pixel in an image of width 1 and height
070             * palette.getNumEntries().
071             */
072            public static RGB24Image convertPaletteToImage(Palette palette)
073            {
074                    RGB24Image result = new MemoryRGB24Image(1, palette.getNumEntries());
075                    for (int index = 0; index < palette.getNumEntries(); index++)
076                    {
077                            result.putSample(INDEX_RED, 0, index, palette.getSample(INDEX_RED, index));
078                            result.putSample(INDEX_GREEN, 0, index, palette.getSample(INDEX_GREEN, index));
079                            result.putSample(INDEX_BLUE, 0, index, palette.getSample(INDEX_BLUE, index));
080                    }
081                    return result;
082            }
083    
084            /**
085             * Loads a palette from the argument file.
086             * Uses {@link net.sourceforge.jiu.codecs.ImageLoader} to load an
087             * image from the argument file, then calls {@link #convertImageToPalette}
088             * and returns the palette created that way.
089             */
090            public static Palette load(File paletteFile)
091            {
092                    PixelImage image;
093                    try
094                    {
095                            image = ImageLoader.load(paletteFile, (Vector)null);
096                    }
097                    catch (Exception e)
098                    {
099                            return null;
100                    }
101                    if (!(image instanceof RGB24Image))
102                    {
103                            return null;
104                    }
105                    return convertImageToPalette((RGB24Image)image);
106            }
107    
108            /** 
109             * Saves the palette to the given file as a PPM image file.
110             * Uses {@link net.sourceforge.jiu.codecs.PNMCodec}.
111             */
112            public static void save(Palette palette, File paletteFile) throws
113                    IOException
114            {
115                    RGB24Image image = convertPaletteToImage(palette);
116                    PNMCodec codec = new PNMCodec();
117                    codec.setOutputStream(new FileOutputStream(paletteFile));
118                    codec.setAscii(true);
119                    codec.setImage(image);
120                    try
121                    {
122                            codec.process();
123                    }
124                    catch(OperationFailedException ofe)
125                    {
126                            throw new IOException("I/O error: " + ofe.toString());
127                    }
128            }
129    }