001    /*
002     * @(#)ArrayScaling   0.6.0   2001/06/25
003     * 
004     * Copyright (c) 2000, 2001 Marco Schmidt <marcoschmidt@users.sourceforge.net>
005     * All rights reserved.
006     */
007    
008    package net.sourceforge.jiu.util;
009    
010    import java.lang.IllegalArgumentException;
011    
012    /**
013     * This class currently only scales up an image given as a one-dimensional array
014     * of values.
015     * <p>
016     * <em>Note: This class should be adjusted if Java ever supports genericity.
017     * It could then work on all kinds of arrays.</em>
018     *
019     * @author Marco Schmidt
020     */
021    public class ArrayScaling
022    {
023            private ArrayScaling()
024            {
025            }
026    
027            /**
028             * Scales up the argument image by factor 2 in both directions.
029             * It is assumed that the first <code>width</code> times
030             * <code>height</code> values of <code>data</code> contain an image 
031             * (or image channel).
032             * The pixels (or samples) are assumed to be laid out rows top-to-bottom,
033             * within each row left-to-right.
034             * It is further assumed that the length of the <code>data</code> array is
035             * at least 4 times <code>width</code> times <code>height</code>.
036             * This method scales up the image in <code>data</code> so that after the call to this
037             * method <code>data</code> can be treated as an image (a channel) that has a horizontal
038         * resolution of <code>width * 2</code> and a vertical resolution of 
039         * <code>height * 2</code>.
040         *
041             * @param data the array of pixels that form the image to be flipped
042             * @param width the horizontal resolution of the image; must be larger than 0
043             * @param height the vertical resolution of the image; must be larger than 0
044             * @exception IllegalArgumentException if the arguments are invalid
045             */
046            public static final void scaleUp200Percent(byte[] data, int width, int height)
047                    throws IllegalArgumentException
048            {
049                    if (data == null)
050                    {
051                            throw new IllegalArgumentException("Error -- data must be non-null.");
052                    }
053                    if (width < 1 || height < 1)
054                    {
055                            throw new IllegalArgumentException("Error -- both width and " +
056                                    "height must be larger than zero (width=" + width +
057                                    ", height=" + height + ").");
058                    }
059                    int numPixels = width * height;
060                    if (width * height * 4 > data.length)
061                    {
062                            throw new IllegalArgumentException("Error -- data array must hold " +
063                                    "at least width times height times 4 values.");
064                    }
065                    int newWidth = width * 2;
066                    int newHeight = height * 2;
067                    // (1) scale up each row in horizontal direction and copy it to its destination
068                    //     at the same time
069                    int y1 = height - 1;
070                    int y2 = newHeight - 1;
071                    while (y1 >= 0)
072                    {
073                            int x = width - 1;
074                            int offset1 = (y1 + 1) * width - 1;
075                            int offset2 = (y2 + 1) * newWidth - 1;
076                            while (x > 0)
077                            {
078                                    int v1 = data[offset1--] & 0xff;
079                                    int v2 = data[offset1] & 0xff;
080                                    data[offset2--] = (byte)v1;
081                                    data[offset2--] = (byte)((v1 + v2) >> 1);
082                                    x--;
083                            }
084                            byte v = data[offset1];
085                            data[offset2--] = v;
086                            data[offset2] = v;
087                            y1--;
088                            y2 -= 2;
089                    }
090                    // (2) take two already-copied rows from scaled image and
091                    //     interpolate the row between them
092                    int y = newHeight - 1;
093                    while (y > 1)
094                    {
095                            int offset1 = (y - 2) * newWidth;
096                            int offset2 = offset1 + newWidth;
097                            int offset3 = offset2 + newWidth;
098                            for (int x = 0; x < newWidth; x++)
099                            {
100                                    int v1 = data[offset1++] & 0xff;
101                                    int v2 = data[offset3++] & 0xff;
102                                    data[offset2++] = (byte)((v1 + v2) >> 1);
103                            }
104                            y -= 2;
105                    }
106                    // (3) copy second row of scaled image to first row
107                    int x1 = 0;
108                    int x2 = newWidth;
109                    while (x1 < newWidth)
110                    {
111                            data[x1++] = data[x2++];
112                    }
113            }
114    }