/*
 * SDK Pullenti Unitext, version 4.33, fabruary 2026. Copyright (c) 2013-2026, Pullenti. All rights reserved. 
 * Non-Commercial Freeware and Commercial Software. 
 * This class is generated using the converter Unisharping (www.unisharping.ru) from Pullenti C# project. 
 * The latest version of the code is available on the site www.pullenti.ru
 */

package com.pullenti.unitext.internal.misc;

public class PngWrapper {

    public PngWrapper(int width, int height, boolean isGray, byte[] colorMap, boolean createGrayImage) {
        m_Data = new java.util.ArrayList<byte[]>();
        m_RowSize = width;
        if (!isGray) {
            if (colorMap == null) 
                m_RowSize *= 3;
        }
        m_RowSize++;
        m_Chunks = new java.util.ArrayList<PngChunk>();
        m_Head = new PngHead();
        m_Chunks.add(m_Head);
        m_Head.setWidth(width);
        m_Head.setHeight(height);
        m_Head.setColorType((byte)((isGray ? 0 : 2)));
        if (colorMap != null) {
            m_ColorMap = colorMap;
            if (!isGray) {
                m_Head.setColorType((byte)3);
                PngChunk mmm = new PngChunk("PLTE");
                mmm.data = colorMap;
                if (!isGray && ((colorMap.length % 3)) != 0 && colorMap.length >= 6) {
                    int ii = colorMap.length % 3;
                    byte[] dat = new byte[colorMap.length - ii];
                    for (int j = 0; j < dat.length; j++) {
                        dat[j] = colorMap[j];
                    }
                    mmm.data = dat;
                }
                m_Chunks.add(mmm);
            }
        }
        if (createGrayImage) {
            m_GrayImage = new java.util.ArrayList<byte[]>(height);
            for (int i = 0; i < height; i++) {
                m_GrayImage.add(new byte[width]);
            }
        }
    }

    private PngHead m_Head;

    private java.util.ArrayList<byte[]> m_GrayImage;

    private int m_RowSize;

    private byte[] m_ColorMap;

    private java.util.ArrayList<byte[]> m_Data;

    private byte[] m_Row;

    private int m_RowPos;

    private java.util.ArrayList<PngChunk> m_Chunks;

    public void beginRow() {
        m_Row = new byte[m_RowSize];
        m_RowPos = 1;
    }

    public void endRow() {
        m_Data.add(m_Row);
    }

    public void addPixelRgb(byte r, byte g, byte b) {
        if ((m_RowPos + 2) >= m_RowSize) 
            return;
        m_Row[m_RowPos] = r;
        if (m_Head.getColorType() == ((byte)0)) 
            m_RowPos += 1;
        else {
            m_Row[m_RowPos + 1] = g;
            m_Row[m_RowPos + 2] = b;
            m_RowPos += 3;
        }
    }

    public void addPixelGray(byte gr) {
        if (m_RowPos >= m_RowSize) 
            return;
        if (m_GrayImage != null && (m_Data.size() < m_GrayImage.size())) {
            if (m_RowPos <= m_GrayImage.get(m_Data.size()).length) 
                m_GrayImage.get(m_Data.size())[m_RowPos - 1] = gr;
        }
        m_Row[m_RowPos] = gr;
        m_RowPos += 1;
    }

    public byte getPixelGray(int w, int h) {
        if (m_GrayImage == null || h >= m_GrayImage.size()) 
            return (byte)0;
        if (w < m_GrayImage.get(h).length) 
            return m_GrayImage.get(h)[w];
        return (byte)0;
    }

    public void addPixelIndex(byte gr) {
        if (m_RowPos >= m_RowSize) 
            return;
        if (m_ColorMap != null && m_Head.getColorType() == ((byte)0)) {
            int i = Byte.toUnsignedInt(gr);
            if (i >= 0 && (i < m_ColorMap.length)) {
                m_Row[m_RowPos] = m_ColorMap[i];
                m_RowPos += 1;
            }
        }
        else {
            m_Row[m_RowPos] = gr;
            m_RowPos += 1;
        }
    }

    public void commit() throws Exception, java.io.IOException {
        PngChunk dat = new PngChunk("IDAT");
        try (com.pullenti.unisharp.MemoryStream body = new com.pullenti.unisharp.MemoryStream()) {
            for (int r = 0; r < m_Data.size(); r++) {
                body.write(m_Data.get(r), 0, m_RowSize);
            }
            byte[] src0 = body.toByteArray();
            dat.data = com.pullenti.util.ArchiveHelper.compressZlib(src0);
            m_Head.setHeight(m_Data.size());
        }
        m_Chunks.add(dat);
        m_Chunks.add(new PngChunk("IEND"));
    }

    public byte[] getBytes() throws Exception, java.io.IOException {
        if (m_Chunks.size() < 1) 
            this.commit();
        try (com.pullenti.unisharp.MemoryStream res = new com.pullenti.unisharp.MemoryStream()) {
            res.write((byte)137);
            res.write((byte)80);
            res.write((byte)78);
            res.write((byte)71);
            res.write((byte)13);
            res.write((byte)10);
            res.write((byte)26);
            res.write((byte)10);
            for (PngChunk ch : m_Chunks) {
                ch.write(res);
            }
            return res.toByteArray();
        }
    }

    public static byte filterByte(int typ, boolean encode, byte x, byte a, byte b, byte c) {
        if (typ == 1) 
            return (encode ? (byte)(((Byte.toUnsignedInt(x)) - (Byte.toUnsignedInt(a)))) : (byte)(((Byte.toUnsignedInt(x)) + (Byte.toUnsignedInt(a)))));
        if (typ == 2) 
            return (encode ? (byte)(((Byte.toUnsignedInt(x)) - (Byte.toUnsignedInt(b)))) : (byte)(((Byte.toUnsignedInt(x)) + (Byte.toUnsignedInt(b)))));
        if (typ == 3) {
            int i = Byte.toUnsignedInt(a);
            i += (Byte.toUnsignedInt(b));
            i /= 2;
            return (encode ? (byte)(((Byte.toUnsignedInt(x)) - i)) : (byte)(((Byte.toUnsignedInt(x)) + i)));
        }
        if (typ == 4) {
            int p = Byte.toUnsignedInt(a);
            p += (Byte.toUnsignedInt(b));
            p -= (Byte.toUnsignedInt(c));
            int pa = p - (Byte.toUnsignedInt(a));
            if (pa < 0) 
                pa = -pa;
            int pb = p - (Byte.toUnsignedInt(b));
            if (pb < 0) 
                pb = -pb;
            int pc = p - (Byte.toUnsignedInt(c));
            if (pc < 0) 
                pc = -pc;
            int i = 0;
            if (pa <= pb && pa <= pc) 
                i = Byte.toUnsignedInt(a);
            else if (pb <= pc) 
                i = Byte.toUnsignedInt(b);
            else 
                i = Byte.toUnsignedInt(c);
            return (encode ? (byte)(((Byte.toUnsignedInt(x)) - i)) : (byte)(((Byte.toUnsignedInt(x)) + i)));
        }
        return x;
    }
    public PngWrapper() {
    }
}
