BitmapImagePixelsTest.java

/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2025 Apryse Group NV
    Authors: Apryse Software.

    This program is offered under a commercial and under the AGPL license.
    For commercial licensing, contact us at https://itextpdf.com/sales.  For AGPL licensing, see below.

    AGPL licensing:
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package com.itextpdf.kernel.utils;

import com.itextpdf.commons.utils.MessageFormatUtil;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.exceptions.KernelExceptionMessageConstant;
import com.itextpdf.kernel.pdf.PdfName;
import com.itextpdf.kernel.pdf.PdfNumber;
import com.itextpdf.kernel.pdf.xobject.PdfImageXObject;
import com.itextpdf.test.ExtendedITextTest;

import java.net.MalformedURLException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

@Tag("UnitTest")
public class BitmapImagePixelsTest extends ExtendedITextTest {
    private static final String SOURCE_FOLDER = "./src/test/resources/com/itextpdf/kernel/utils/BitmapImagePixelsTest/";

    @Test
    public void constructorWithImageByteArrayParameterTest() {
        byte[] imageBytes = new byte[] {1, 2, 3, 4, 5, 6};
        BitmapImagePixels imagePixels = new BitmapImagePixels(1, 3, 8, 2, imageBytes);
        Assertions.assertEquals(1, imagePixels.getWidth());
        Assertions.assertEquals(3, imagePixels.getHeight());
        Assertions.assertEquals(8, imagePixels.getBitsPerComponent());
        Assertions.assertEquals(2, imagePixels.getNumberOfComponents());
        Assertions.assertArrayEquals(imageBytes, imagePixels.getData());
    }

    @Test
    public void constructorWithImageByteArrayParameterInvalidParamsTest() {
        byte[] imageBytes = new byte[] {1, 2, 3, 4, 5};
        Exception exception = Assertions.assertThrows(IllegalArgumentException.class,
                () -> new BitmapImagePixels(30, 40, 8, 3, imageBytes));
        Assertions.assertEquals(
                MessageFormatUtil.format(KernelExceptionMessageConstant.INVALID_DATA_LENGTH, 28800, 40),
                exception.getMessage());
    }

    @Test
    public void constructorWithParametersTest() {
        BitmapImagePixels imagePixels = new BitmapImagePixels(30, 40, 8, 3);
        Assertions.assertEquals(30, imagePixels.getWidth());
        Assertions.assertEquals(40, imagePixels.getHeight());
        Assertions.assertEquals(8, imagePixels.getBitsPerComponent());
        Assertions.assertEquals(3, imagePixels.getNumberOfComponents());
        byte[] expectedArray = new byte[30 * 40 * 8 * 3 / 8];
        Assertions.assertArrayEquals(expectedArray, imagePixels.getData());
    }

    @Test
    // Tests that each row ends on the byte border
    public void constructorWithParametersWithTrashBitsOnEahRowTest() {
        BitmapImagePixels imagePixels = new BitmapImagePixels(15, 15, 4, 3);
        Assertions.assertEquals(15, imagePixels.getWidth());
        Assertions.assertEquals(15, imagePixels.getHeight());
        Assertions.assertEquals(4, imagePixels.getBitsPerComponent());
        Assertions.assertEquals(3, imagePixels.getNumberOfComponents());
        Assertions.assertEquals(15, imagePixels.getMaxComponentValue());
        byte[] expectedArray = new byte[15 * (15 * 4 * 3 / 8 + 1)];
        Assertions.assertArrayEquals(expectedArray, imagePixels.getData());
    }

    @Test
    public void constructorWithPdfXObjectTest() throws MalformedURLException {
        final String sourceImage = SOURCE_FOLDER + "png-example.png";
        PdfImageXObject image = new PdfImageXObject(ImageDataFactory.create(sourceImage));
        BitmapImagePixels imagePixels = new BitmapImagePixels(image);
        Assertions.assertEquals(200, imagePixels.getWidth());
        Assertions.assertEquals(200, imagePixels.getHeight());
        Assertions.assertEquals(8, imagePixels.getBitsPerComponent());
        Assertions.assertEquals(3, imagePixels.getNumberOfComponents());
        Assertions.assertEquals(255, imagePixels.getMaxComponentValue());
        byte[] expectedArray = image.getPdfObject().getBytes();
        Assertions.assertArrayEquals(expectedArray, imagePixels.getData());
    }

    @Test
    public void constructorWithPdfXObjectWithoutBpcTest() {
        Exception exception = Assertions.assertThrows(IllegalArgumentException.class, () -> {
            final String sourceImage = SOURCE_FOLDER + "png-example.png";
            PdfImageXObject image = new PdfImageXObject(ImageDataFactory.create(sourceImage));
            image.getPdfObject().put(PdfName.BitsPerComponent, new PdfNumber(1));
            new BitmapImagePixels(image);
        });

        Assertions.assertEquals(
                MessageFormatUtil.format(KernelExceptionMessageConstant.INVALID_DATA_LENGTH, 120000, 960000),
                exception.getMessage());
    }

    @Test
    public void getPixelsAsLongs1bit1channelTest() {
        byte[] imageBytes = new byte[] {(byte) 0b10001000, 0b00100000,
                0b01000100, (byte) 0b10000000,
                0b00100000, (byte) 0b11100000};
        BitmapImagePixels imagePixels = new BitmapImagePixels(11, 3, 1, 1, imageBytes);

        for (int x = 0; x < 11; x++) {
            for (int y = 0; y < 3; y++) {
                final int mx = x;
                final int my = y;
                if (y==0 && x==0
                        || y==0 && x==4
                        || y==0 && x==10
                        || y==1 && x==1
                        || y==1 && x==5
                        || y==1 && x==8
                        || y==2 && x==2
                        || y==2 && x==8
                        || y==2 && x==9
                        || y==2 && x==10) {
                    Assertions.assertEquals(1, imagePixels.getPixelAsLongs(x,y)[0], () -> String.format("Expected a value of 1 for pixel %d, %d", my, mx));
                } else {
                    Assertions.assertEquals(0, imagePixels.getPixelAsLongs(x,y)[0], () -> String.format("Expected a value of 0 for pixel %d, %d", my, mx));
                }
            }
        }
    }

    @Test
    public void getPixelsAsLongs1bit3channelsTest() {
        byte[] imageBytes = new byte[] {
                /*              00011122           23334445           55666777           888
                /* 0 */(byte) 0b11100000, (byte) 0b00001110, (byte) 0b00111000, (byte) 0b11100000,
                /* 1 */(byte) 0b00011100, (byte) 0b01110000, (byte) 0b00000111, (byte) 0b00000000,
                /* 2 */(byte) 0b00000011, (byte) 0b10000001, (byte) 0b11000000, (byte) 0b00000000};
        BitmapImagePixels imagePixels = new BitmapImagePixels(9, 3, 1, 3, imageBytes);

        for (int x = 0; x < 9; x++) {
            for (int y = 0; y < 3; y++) {
                final int mx = x;
                final int my = y;
                if (y==0 && x==0
                        || y==0 && x==4
                        || y==0 && x==6
                        || y==0 && x==8
                        || y==1 && x==1
                        || y==1 && x==3
                        || y==1 && x==7
                        || y==2 && x==2
                        || y==2 && x==5) {
                    Assertions.assertEquals(1, imagePixels.getPixelAsLongs(x,y)[0], () -> String.format("Expected a value of 1 for pixel %d, %d", my, mx));
                } else {
                    Assertions.assertEquals(0, imagePixels.getPixelAsLongs(x,y)[0], () -> String.format("Expected a value of 0 for pixel %d, %d", my, mx));
                }
            }
        }
    }

    @Test
    public void getPixelsAsLongs2bit1channelTest() {
        byte[] imageBytes = new byte[] {
                /*              00112233           44556677           889900
                /* 0 */(byte) 0b11000000, (byte) 0b00001100, (byte) 0b00110000,
                /* 1 */(byte) 0b00001100, (byte) 0b00110000, (byte) 0b00000000,
                /* 2 */(byte) 0b00000011, (byte) 0b11000000, (byte) 0b11000000};
        BitmapImagePixels imagePixels = new BitmapImagePixels(11, 3, 2, 1, imageBytes);

        for (int x = 0; x < 9; x++) {
            for (int y = 0; y < 3; y++) {
                final int mx = x;
                final int my = y;
                if (y==0 && x==0
                        || y==0 && x==6
                        || y==0 && x==9
                        || y==1 && x==2
                        || y==1 && x==5
                        || y==2 && x==3
                        || y==2 && x==4
                        || y==2 && x==8) {
                    Assertions.assertEquals(3, imagePixels.getPixelAsLongs(x,y)[0], () -> String.format("Expected a value of 3 for pixel %d, %d", my, mx));
                } else {
                    Assertions.assertEquals(0, imagePixels.getPixelAsLongs(x,y)[0], () -> String.format("Expected a value of 0 for pixel %d, %d", my, mx));
                }
            }
        }
    }

    @Test
    public void getPixelsAsLongs2bit3channelTest() {
        byte[] imageBytes = new byte[] {
                /*              00000011           11112222           22333333           444444
                /* 0 */(byte) 0b11111100, (byte) 0b00001111, (byte) 0b11000000, (byte) 0b11111100,
                /* 1 */(byte) 0b00000011, (byte) 0b11110000, (byte) 0b00111111, (byte) 0b00000000,
                /* 2 */(byte) 0b00000000, (byte) 0b00001111, (byte) 0b11000000, (byte) 0b00000000};
        BitmapImagePixels imagePixels = new BitmapImagePixels(5, 3, 2, 3, imageBytes);

        for (int x = 0; x < 5; x++) {
            for (int y = 0; y < 3; y++) {
                final int mx = x;
                final int my = y;
                if (y==0 && x==0
                        || y==0 && x==2
                        || y==0 && x==4
                        || y==1 && x==1
                        || y==1 && x==3
                        || y==2 && x==2) {
                    Assertions.assertEquals(3, imagePixels.getPixelAsLongs(x,y)[0], () -> String.format("Expected a value of 1 for pixel %d, %d", my, mx));
                    Assertions.assertEquals(3, imagePixels.getPixelAsLongs(x,y)[1], () -> String.format("Expected a value of 1 for pixel %d, %d", my, mx));
                    Assertions.assertEquals(3, imagePixels.getPixelAsLongs(x,y)[2], () -> String.format("Expected a value of 1 for pixel %d, %d", my, mx));
                } else {
                    Assertions.assertEquals(0, imagePixels.getPixelAsLongs(x,y)[0], () -> String.format("Expected a value of 0 for pixel %d, %d", my, mx));
                    Assertions.assertEquals(0, imagePixels.getPixelAsLongs(x,y)[1], () -> String.format("Expected a value of 0 for pixel %d, %d", my, mx));
                    Assertions.assertEquals(0, imagePixels.getPixelAsLongs(x,y)[2], () -> String.format("Expected a value of 0 for pixel %d, %d", my, mx));
                }
            }
        }
    }

    @Test
    public void getPixelsAsLongs4bit1channelTest() {
        byte[] imageBytes = new byte[] {
                /*              00001111           22223333           44445555           6666
                /* 0 */(byte) 0b11110000, (byte) 0b00001111, (byte) 0b11110000, (byte) 0b11110000,
                /* 1 */(byte) 0b00001111, (byte) 0b11110000, (byte) 0b00001111, (byte) 0b00000000,
                /* 2 */(byte) 0b00000000, (byte) 0b00001111, (byte) 0b00000000, (byte) 0b11110000};
        BitmapImagePixels imagePixels = new BitmapImagePixels(7, 3, 4, 1, imageBytes);

        for (int x = 0; x < 7; x++) {
            for (int y = 0; y < 3; y++) {
                final int mx = x;
                final int my = y;
                if (y==0 && x==0
                        || y==0 && x==3
                        || y==0 && x==4
                        || y==0 && x==6
                        || y==1 && x==1
                        || y==1 && x==2
                        || y==1 && x==5
                        || y==2 && x==3
                        || y==2 && x==6) {
                    Assertions.assertEquals(15, imagePixels.getPixelAsLongs(x,y)[0], () -> String.format("Expected a value of 15 for pixel %d, %d", my, mx));
                } else {
                    Assertions.assertEquals(0, imagePixels.getPixelAsLongs(x,y)[0], () -> String.format("Expected a value of 0 for pixel %d, %d", my, mx));
                }
            }
        }
    }

    @Test
    public void getPixelsAsLongs4bit3channelTest() {
        byte[] imageBytes = new byte[] {
                /*              00000000           00001111           11111111           22222222           22220000
                /* 0 */(byte) 0b11111111, (byte) 0b11110000, (byte) 0b00000000, (byte) 0b11111111, (byte) 0b11110000,
                /* 1 */(byte) 0b00000000, (byte) 0b00001111, (byte) 0b11111111, (byte) 0b00000000, (byte) 0b00000000,
                /* 2 */(byte) 0b00000000, (byte) 0b00001111, (byte) 0b11111111, (byte) 0b11111111, (byte) 0b11110000};
        BitmapImagePixels imagePixels = new BitmapImagePixels(3, 3, 4, 3, imageBytes);

        for (int x = 0; x < 3; x++) {
            for (int y = 0; y < 3; y++) {
                final int mx = x;
                final int my = y;
                if (y==0 && x==0
                        || y==0 && x==2
                        || y==1 && x==1
                        || y==2 && x==1
                        || y==2 && x==2) {
                    Assertions.assertEquals(15, imagePixels.getPixelAsLongs(x,y)[0], () -> String.format("Expected a value of 15 for pixel %d, %d", my, mx));
                    Assertions.assertEquals(15, imagePixels.getPixelAsLongs(x,y)[1], () -> String.format("Expected a value of 15 for pixel %d, %d", my, mx));
                    Assertions.assertEquals(15, imagePixels.getPixelAsLongs(x,y)[2], () -> String.format("Expected a value of 15 for pixel %d, %d", my, mx));
                } else {
                    Assertions.assertEquals(0, imagePixels.getPixelAsLongs(x,y)[0], () -> String.format("Expected a value of 0 for pixel %d, %d", my, mx));
                    Assertions.assertEquals(0, imagePixels.getPixelAsLongs(x,y)[1], () -> String.format("Expected a value of 0 for pixel %d, %d", my, mx));
                    Assertions.assertEquals(0, imagePixels.getPixelAsLongs(x,y)[2], () -> String.format("Expected a value of 0 for pixel %d, %d", my, mx));
                }
            }
        }
    }

    @Test
    public void getPixelsAsLongs16bit1channelTest() {
        byte[] imageBytes = new byte[] {
                /*              00000000           00000000           11111111           11111111
                /* 0 */(byte) 0b00000010, (byte) 0b00000010, (byte) 0b00000011, (byte) 0b00000011, /*514, 771*/
                /* 1 */(byte) 0b00000100, (byte) 0b00000100, (byte) 0b00000101, (byte) 0b00000101, /* 1028, 1258 */
                /* 2 */(byte) 0b00001000, (byte) 0b00001000, (byte) 0b00001001, (byte) 0b00001001}; /* 2056, 2313 */
        BitmapImagePixels imagePixels = new BitmapImagePixels(2, 3, 16, 1, imageBytes);

        for (int x = 0; x < 2; x++) {
            for (int y = 0; y < 3; y++) {
                final int mx = x;
                final int my = y;
                int expected = (2<<y) + x;
                expected <<= 8;
                expected += (2<<y) + x;
                final int mexpected = expected;
                Assertions.assertEquals(expected , imagePixels.getPixelAsLongs(x,y)[0], () -> String.format("Expected a value of %d for pixel %d, %d",mexpected, my, mx));
            }
        }
    }


    @Test
    public void getPixelsAsLongs16bit3channelTest() {
        final int[] testData = new int[] {
                /*       1r 1g 1b 2r 2g 2b 3r 3g 3b */
                /* 0 */  1, 2, 3, 4, 5, 6, 7, 8, 9,
                /* 1 */ 10,11,12,13,14,15,16,17,18,
                /* 2 */ 19,20,21,22,23,24,25,26,27};

        byte[] imageBytes = new byte[testData.length * 2];
        for (int i = 0; i < testData.length; i++) {
            imageBytes[i*2] = 0;
            imageBytes[i*2 + 1] = (byte) testData[i];
        }


        BitmapImagePixels imagePixels = new BitmapImagePixels(3, 3, 16, 3, imageBytes);

        for (int x = 0; x < 2; x++) {
            for (int y = 0; y < 3; y++) {
                final int mx = x;
                final int my = y;
                for (int c = 0; c < 3; c++) {
                    final int mc = c;
                    Assertions.assertEquals(testData[x*3+c +y*9] ,
                    imagePixels.getPixelAsLongs(x, y)[c], () -> String.format("Expected a value of %d for pixel %d, %d",
                                    testData[mx*3+mc +my*9], my, mx));
                }
            }
        }
    }



    @Test
    public void getPixelsAsLongsTest() throws MalformedURLException {
        final String sourceImage = SOURCE_FOLDER + "png-example.png";
        PdfImageXObject image = new PdfImageXObject(ImageDataFactory.create(sourceImage));
        BitmapImagePixels imagePixels = new BitmapImagePixels(image);
        long[] greyColor = new long[] {195, 195, 195};
        long[] redColor = new long[] {237, 28, 36};
        Assertions.assertArrayEquals(greyColor, imagePixels.getPixelAsLongs(0, 0));
        Assertions.assertArrayEquals(redColor, imagePixels.getPixelAsLongs(100, 50));
    }

    @Test
    public void getPixelsTest() throws MalformedURLException {
        final String sourceImage = SOURCE_FOLDER + "png-example.png";
        PdfImageXObject image = new PdfImageXObject(ImageDataFactory.create(sourceImage));
        BitmapImagePixels imagePixels = new BitmapImagePixels(image);
        double[] greyColor = new double[] {(double) 195 / 255, (double) 195 / 255, (double) 195 / 255};
        double[] redColor = new double[] {(double) 237 / 255, (double) 28 / 255, (double) 36 / 255};
        Assertions.assertArrayEquals(greyColor, imagePixels.getPixel(0, 0), 0.0001);
        Assertions.assertArrayEquals(redColor, imagePixels.getPixel(100, 50), 0.0001);
    }

    @Test
    public void setPixelsTest() throws MalformedURLException {
        final String sourceImage = SOURCE_FOLDER + "png-example.png";
        final String cmpImage = SOURCE_FOLDER + "png-example-modified.png";
        PdfImageXObject image = new PdfImageXObject(ImageDataFactory.create(sourceImage));
        BitmapImagePixels imagePixels = new BitmapImagePixels(image);
        double[] orangeColor = new double[] {(double) 255 / 255, (double) 170 / 255, (double) 0};
        for (int i = 0; i < imagePixels.getWidth(); i++) {
            imagePixels.setPixel(i, i, orangeColor);
        }
        PdfImageXObject cmpImageObject = new PdfImageXObject(ImageDataFactory.create(cmpImage));
        Assertions.assertArrayEquals(cmpImageObject.getPdfObject().getBytes(), imagePixels.getData());
    }

    @Test
    public void xCoordinateCannotBeNegativeGetterTest() {
        Exception exception = Assertions.assertThrows(IllegalArgumentException.class, () -> {
            BitmapImagePixels imagePixels = new BitmapImagePixels(30, 40, 8, 3);
            imagePixels.getPixel(-1, 0);
        });

        Assertions.assertEquals(
                MessageFormatUtil.format(KernelExceptionMessageConstant.PIXEL_OUT_OF_BORDERS, -1, 0, 30, 40),
                exception.getMessage());
    }

    @Test
    public void xCoordinateCannotBeNegativeSetterTest() {
        Exception exception = Assertions.assertThrows(IllegalArgumentException.class, () -> {
            BitmapImagePixels imagePixels = new BitmapImagePixels(30, 40, 8, 3);
            double[] orangePixel = new double[] {1., (double) 170 / 255, 0.};
            imagePixels.setPixel(-1, 0, orangePixel);
        });

        Assertions.assertEquals(
                MessageFormatUtil.format(KernelExceptionMessageConstant.PIXEL_OUT_OF_BORDERS, -1, 0, 30, 40),
                exception.getMessage());
    }

    @Test
    public void yCoordinateCannotBeNegativeGetterTest() {
        Exception exception = Assertions.assertThrows(IllegalArgumentException.class, () -> {
            BitmapImagePixels imagePixels = new BitmapImagePixels(30, 40, 8, 3);
            imagePixels.getPixel(0, -1);
        });

        Assertions.assertEquals(
                MessageFormatUtil.format(KernelExceptionMessageConstant.PIXEL_OUT_OF_BORDERS, 0, -1, 30, 40),
                exception.getMessage());

    }

    @Test
    public void yCoordinateCannotBeNegativeSetterTest() {
        Exception exception = Assertions.assertThrows(IllegalArgumentException.class, () -> {
            BitmapImagePixels imagePixels = new BitmapImagePixels(30, 40, 8, 3);
            double[] orangePixel = new double[] {1., (double) 170 / 255, 0.};
            imagePixels.setPixel(0, -1, orangePixel);
        });

        Assertions.assertEquals(
                MessageFormatUtil.format(KernelExceptionMessageConstant.PIXEL_OUT_OF_BORDERS, 0, -1, 30, 40),
                exception.getMessage());
    }

    @Test
    public void xCoordinateOutOfPictureGetterTest() {
        Exception exception = Assertions.assertThrows(IllegalArgumentException.class, () -> {
            BitmapImagePixels imagePixels = new BitmapImagePixels(30, 40, 8, 3);
            imagePixels.getPixel(31, 0);
        });

        Assertions.assertEquals(
                MessageFormatUtil.format(KernelExceptionMessageConstant.PIXEL_OUT_OF_BORDERS, 31, 0, 30, 40),
                exception.getMessage());
    }

    @Test
    public void xCoordinateOutOfPictureSetterTest() {
        Exception exception = Assertions.assertThrows(IllegalArgumentException.class, () -> {
            BitmapImagePixels imagePixels = new BitmapImagePixels(30, 40, 8, 3);
            double[] orangePixel = new double[] {1., (double) 170 / 255, 0.};
            imagePixels.setPixel(31, 0, orangePixel);
        });

        Assertions.assertEquals(
                MessageFormatUtil.format(KernelExceptionMessageConstant.PIXEL_OUT_OF_BORDERS, 31, 0, 30, 40),
                exception.getMessage());
    }

    @Test
    public void yCoordinateOutOfPictureGetterTest() {
        Exception exception = Assertions.assertThrows(IllegalArgumentException.class, () -> {
            BitmapImagePixels imagePixels = new BitmapImagePixels(30, 40, 8, 3);
            imagePixels.getPixel(0, 41);
        });

        Assertions.assertEquals(
                MessageFormatUtil.format(KernelExceptionMessageConstant.PIXEL_OUT_OF_BORDERS, 0, 41, 30, 40),
                exception.getMessage());
    }

    @Test
    public void yCoordinateOutOfPictureSetterTest() {
        Exception exception = Assertions.assertThrows(IllegalArgumentException.class, () -> {
            BitmapImagePixels imagePixels = new BitmapImagePixels(30, 40, 8, 3);
            double[] orangePixel = new double[] {1., (double) 170 / 255, 0.};
            imagePixels.setPixel(0, 41, orangePixel);
        });

        Assertions.assertEquals(
                MessageFormatUtil.format(KernelExceptionMessageConstant.PIXEL_OUT_OF_BORDERS, 0, 41, 30, 40),
                exception.getMessage());
    }

    @Test
    public void pixelArrayShouldMatchColorSpaceTest() {
        Exception exception = Assertions.assertThrows(IllegalArgumentException.class, () -> {
            BitmapImagePixels imagePixels = new BitmapImagePixels(30, 40, 8, 3);
            double[] blackPixel = new double[] {0., 0., 0., 0.};
            imagePixels.setPixel(0, 0, blackPixel);
        });

        Assertions.assertEquals(MessageFormatUtil.format(
                        KernelExceptionMessageConstant.LENGTH_OF_ARRAY_SHOULD_MATCH_NUMBER_OF_COMPONENTS, 4, 3),
                exception.getMessage());
    }

    @Test
    public void pixelArrayNormalizationTest() {
        BitmapImagePixels imagePixels = new BitmapImagePixels(30, 40, 8, 3);
        double[] greenPixel = new double[] {-10., 10., -10., };
        imagePixels.setPixel(0, 0, greenPixel);
        double[] expectedPixel = new double[] {0., 1., 0.};
        Assertions.assertArrayEquals(expectedPixel, imagePixels.getPixel(0, 0), 0.0001);
    }
}