All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.monte.media.anim.ANIMDeltaFrame Maven / Gradle / Ivy

The newest version!

package org.monte.media.anim;

import org.monte.media.image.BitmapImage;


public class ANIMDeltaFrame
        extends ANIMFrame {

    private int leftBound, topBound, rightBound, bottomBound;
    private final static int
            ENCODING_BYTE_VERTICAL = 5,
            ENCODING_VERTICAL_7_SHORT = 6,
            ENCODING_VERTICAL_7_LONG = 7,
            ENCODING_VERTICAL_8_SHORT = 8,
            ENCODING_VERTICAL_8_LONG = 9,
            ENCODING_J = 74;
    public final static int
            OP_Direct = 0,
            OP_XOR = 1,
            OP_LongDelta = 2,
            OP_ShortDelta = 3,
            OP_GeneralDelta = 4,
            OP_ByteVertical = 5,
            OP_StereoDelta = 6,
            OP_Vertical7 = 7,
            OP_Vertical8 = 8,
            OP_J = 74;

    private boolean isWarningPrinted = false;

    public ANIMDeltaFrame() {
    }

    private int getEncoding() {
        switch (getOperation()) {
            case OP_Direct:
                throw new InternalError("Key Frames not yet supported (Anim Op0)");
            case OP_ByteVertical:
                if (getBits() == BIT_XOR) {

                } else if ((getBits() & BadBitsOP_ByteVertical) != 0) {
                    throw new InternalError("Unknown Bits for Anim Op5 in ANHD; Bits:" + getBits());
                }
                return ENCODING_BYTE_VERTICAL;
            case OP_Vertical7:
                if ((getBits() & BIT_LongData) == 0) {
                    return ENCODING_VERTICAL_7_SHORT;
                } else {
                    return ENCODING_VERTICAL_7_LONG;
                }
            case OP_Vertical8:
                if ((getBits() & BIT_LongData) == 0) {
                    return ENCODING_VERTICAL_8_SHORT;
                } else {
                    return ENCODING_VERTICAL_8_LONG;
                }
            case OP_J:
                return ENCODING_J;
            default:
                throw new InternalError("ANIM Op" + getOperation() + " not supported.");
        }
    }

    @Override
    public void decode(BitmapImage bitmap, ANIMMovieTrack track) {
        switch (getEncoding()) {
            case ENCODING_BYTE_VERTICAL:
                decodeByteVertical(bitmap, track);
                break;
            case ENCODING_VERTICAL_7_SHORT:
                decodeVertical7Short(bitmap, track);
                break;
            case ENCODING_VERTICAL_7_LONG:
                decodeVertical7Long(bitmap, track);
                break;
            case ENCODING_VERTICAL_8_SHORT:
                decodeVertical8Short(bitmap, track);
                break;
            case ENCODING_VERTICAL_8_LONG:
                decodeVertical8Long(bitmap, track);
                break;
            case ENCODING_J:
                decodeJ(bitmap, track);
                break;
            default:
                throw new InternalError("Unsupported encoding." + getEncoding());
        }
    }

    private void decodeByteVertical(BitmapImage bitmap, ANIMMovieTrack track) {
        int columns = 0;
        int iOp = 0;
        byte[] planeBytes = bitmap.getBitmap();
        int iPl = 0;
        int widthInBytes = bitmap.getBitplaneStride();
        int interleave = track.getNbPlanes() * widthInBytes;
        int opCode = 0;
        int opCount = 0;
        byte copyByte = 0;
        leftBound = widthInBytes;
        rightBound = 0;
        topBound = track.getHeight();
        bottomBound = 0;
        int height = track.getHeight();
        boolean isXOR = getBits() == BIT_XOR;


        for (int i = 0,n=track.getNbPlanes();i 0) {

                for (columns = 0; columns < widthInBytes; ++columns) {


                    iPl = columns + i * widthInBytes;
                    opCount = data[iOp++] & 0xff;

                    if (opCount > 0) {
                        if (columns < leftBound) {
                            leftBound = columns;
                        }
                        if (columns > rightBound) {
                            rightBound = columns;
                        }
                        opCode = data[iOp];
                        if (opCode <= 0) {
                            topBound = 0;
                        } else {
                            if (opCode < topBound) {
                                topBound = opCode;
                            }
                        }

                        if (isXOR) {
                            for (; opCount > 0; opCount--) {
                                opCode = data[iOp++];
                                if (opCode > 0) {
                                    iPl += opCode * interleave;
                                } else if (opCode < 0) {
                                    opCode &= 0x7f;
                                    while (opCode-- > 0) {
                                        planeBytes[iPl] ^= data[iOp++];
                                        iPl += interleave;
                                    }
                                } else {
                                    opCode = data[iOp++] & 0xff;
                                    if (opCode == 0) {
                                        return;
                                    }
                                    copyByte = data[iOp++];
                                    while (opCode-- > 0) {
                                        planeBytes[iPl] ^= copyByte;
                                        iPl += interleave;
                                    }
                                }
                            }
                        } else {
                            for (; opCount > 0; opCount--) {
                                opCode = data[iOp++];
                                if (opCode > 0) {
                                    iPl += opCode * interleave;
                                } else if (opCode < 0) {
                                    opCode &= 0x7f;
                                    while (opCode-- > 0) {
                                        planeBytes[iPl] = data[iOp++];
                                        iPl += interleave;
                                    }
                                } else {
                                    opCode = data[iOp++] & 0xff;
                                    if (opCode == 0) {
                                        return;
                                    }
                                    copyByte = data[iOp++];
                                    while (opCode-- > 0) {
                                        planeBytes[iPl] = copyByte;
                                        iPl += interleave;
                                    }
                                }
                            }
                        }

                        if (opCode <= 0) {
                            int bottom = (iPl - (columns + i * widthInBytes)) / interleave;
                            if (bottom > bottomBound) {
                                bottomBound = bottom;
                            }
                        } else {
                            if (height - opCode > bottomBound) {
                                bottomBound = height - opCode;
                            }
                        }
                    }
                }
            }
                } catch (ArrayIndexOutOfBoundsException e) {
                    e.printStackTrace();
                }
        }

        if (leftBound <= rightBound) {
            leftBound *= 8;
            rightBound = rightBound * 8 + 8;
        }
    }

    private void decodeVertical8Short(BitmapImage bitmap, ANIMMovieTrack track) {
        int columns = 0;
        int iOp = 0;
        byte[] planeBytes = bitmap.getBitmap();
        int iPl = 0;
        int widthInBytes = bitmap.getBitplaneStride();
        int interleave = track.getNbPlanes() * widthInBytes;
        int opCode = 0;
        int opCount = 0;
        byte copyByte1 = 0;
        byte copyByte2 = 0;
        leftBound = widthInBytes;
        rightBound = 0;
        topBound = track.getHeight() - 1;
        bottomBound = 0;
        int height = track.getHeight() - 1;


        for (int i = 0; i < track.getNbPlanes(); i++) {


            iOp = ((data[i * 4] & 0xff) << 24)
                    + ((data[i * 4 + 1] & 0xff) << 16)
                    + ((data[i * 4 + 2] & 0xff) << 8)
                    + (data[i * 4 + 3] & 0xff);

            if (iOp > 0) {

                for (columns = 0; columns < widthInBytes; columns += 2) {


                    iPl = columns + i * widthInBytes;
                    opCount = ((data[iOp++] & 0xff) << 8) | (data[iOp++] & 0xff);

                    if (opCount > 0) {
                        if (columns < leftBound) {
                            leftBound = columns;
                        }
                        if (columns > rightBound) {
                            rightBound = columns;
                        }
                        opCode = (data[iOp] << 8) | (data[iOp + 1] & 0xff);
                        if (opCode <= 0) {
                            topBound = 0;
                        } else {
                            if (opCode < topBound) {
                                topBound = opCode;
                            }
                        }

                        for (; opCount > 0; opCount--) {
                            opCode = (data[iOp++] << 8) | (data[iOp++] & 0xff);
                            if (opCode > 0) {
                                iPl += opCode * interleave;
                            } else if (opCode < 0) {
                                opCode &= 0x7fff;
                                while (opCode-- > 0) {
                                    planeBytes[iPl] = data[iOp++];
                                    planeBytes[iPl + 1] = data[iOp++];
                                    iPl += interleave;
                                }
                            } else {
                                opCode = ((data[iOp++] << 8) | (data[iOp++] & 0xff)) & 0xffff;
                                if (opCode == 0) {
                                    return;
                                }
                                copyByte1 = data[iOp++];
                                copyByte2 = data[iOp++];
                                while (opCode-- > 0) {
                                    planeBytes[iPl] = copyByte1;
                                    planeBytes[iPl + 1] = copyByte2;
                                    iPl += interleave;
                                }
                            }
                        }

                        if (opCode <= 0) {
                            int bottom = (iPl - (columns + i * widthInBytes)) / interleave;
                            if (bottom > bottomBound) {
                                bottomBound = bottom;
                            }
                        } else {
                            if (height - opCode > bottomBound) {
                                bottomBound = height - opCode;
                            }
                        }
                    }
                }
            }
        }
        if (leftBound <= rightBound) {
            leftBound *= 8;
            rightBound = rightBound * 8 + 16;
        }
    }

    private void decodeVertical8Long(BitmapImage bitmap, ANIMMovieTrack track) {
        int columns = 0;
        int iOp = 0;
        byte[] planeBytes = bitmap.getBitmap();
        int iPl = 0;
        int widthInBytes = bitmap.getBitplaneStride();
        int interleave = track.getNbPlanes() * widthInBytes;
        int opCode = 0;
        int opCount = 0;
        byte copyByte1 = 0;
        byte copyByte2 = 0;
        byte copyByte3 = 0;
        byte copyByte4 = 0;
        leftBound = widthInBytes;
        rightBound = 0;
        topBound = track.getHeight() - 1;
        bottomBound = 0;
        int height = track.getHeight() - 1;


        for (int i = 0; i < track.getNbPlanes(); i++) {


            iOp = ((data[i * 4] & 0xff) << 24)
                    + ((data[i * 4 + 1] & 0xff) << 16)
                    + ((data[i * 4 + 2] & 0xff) << 8)
                    + (data[i * 4 + 3] & 0xff);

            if (iOp > 0) {

                for (columns = 0; columns < widthInBytes; columns += 4) {


                    iPl = columns + i * widthInBytes;
                    opCount = ((data[iOp++] & 0xff) << 24)
                            + ((data[iOp++] & 0xff) << 16)
                            + ((data[iOp++] & 0xff) << 8)
                            + (data[iOp++] & 0xff);

                    if (opCount > 0) {
                        if (columns < leftBound) {
                            leftBound = columns;
                        }
                        if (columns > rightBound) {
                            rightBound = columns;
                        }
                        opCode = ((data[iOp] & 0xff) << 24)
                                + ((data[iOp + 1] & 0xff) << 16)
                                + ((data[iOp + 2] & 0xff) << 8)
                                + (data[iOp + 3] & 0xff);
                        if (opCode <= 0) {
                            topBound = 0;
                        } else {
                            if (opCode < topBound) {
                                topBound = opCode;
                            }
                        }

                        for (; opCount > 0; opCount--) {
                            opCode = ((data[iOp++] & 0xff) << 24)
                                    + ((data[iOp++] & 0xff) << 16)
                                    + ((data[iOp++] & 0xff) << 8)
                                    + (data[iOp++] & 0xff);
                            if (opCode > 0) {
                                iPl += opCode * interleave;
                            } else if (opCode < 0) {
                                opCode &= 0x7fffffff;
                                while (opCode-- > 0) {
                                    planeBytes[iPl] = data[iOp++];
                                    planeBytes[iPl + 1] = data[iOp++];
                                    planeBytes[iPl + 2] = data[iOp++];
                                    planeBytes[iPl + 3] = data[iOp++];
                                    iPl += interleave;
                                }
                            } else {
                                opCode = ((data[iOp++] & 0xff) << 24)
                                        + ((data[iOp++] & 0xff) << 16)
                                        + ((data[iOp++] & 0xff) << 8)
                                        + (data[iOp++] & 0xff);
                                if (opCode == 0) {
                                    return;
                                }
                                copyByte1 = data[iOp++];
                                copyByte2 = data[iOp++];
                                copyByte3 = data[iOp++];
                                copyByte4 = data[iOp++];
                                while (opCode-- > 0) {
                                    planeBytes[iPl] = copyByte1;
                                    planeBytes[iPl + 1] = copyByte2;
                                    planeBytes[iPl + 2] = copyByte3;
                                    planeBytes[iPl + 3] = copyByte4;
                                    iPl += interleave;
                                }
                            }
                        }

                        if (opCode <= 0) {
                            int bottom = (iPl - (columns + i * widthInBytes)) / interleave;
                            if (bottom > bottomBound) {
                                bottomBound = bottom;
                            }
                        } else {
                            if (height - opCode > bottomBound) {
                                bottomBound = height - opCode;
                            }
                        }
                    }
                }
            }
        }
        if (leftBound <= rightBound) {
            leftBound *= 8;
            rightBound = rightBound * 8 + 32;
        }
    }

    private void decodeVertical7Short(BitmapImage bitmap, ANIMMovieTrack track) {
        int columns = 0;
        int iOp = 0;
        int iData = 0;
        byte[] planeBytes = bitmap.getBitmap();
        int iPl = 0;
        int widthInBytes = bitmap.getBitplaneStride();
        int interleave = bitmap.getScanlineStride();
        int opCode = 0;
        int opCount = 0;
        byte copyByte1 = 0;
        byte copyByte2 = 0;
        leftBound = widthInBytes;
        rightBound = 0;
        topBound = track.getHeight() - 1;
        bottomBound = 0;
        int height = track.getHeight() - 1;

        for (int i = 0; i < track.getNbPlanes(); i++) {
            iOp = ((data[i * 4] & 0xff) << 24)
                    + ((data[i * 4 + 1] & 0xff) << 16)
                    + ((data[i * 4 + 2] & 0xff) << 8)
                    + (data[i * 4 + 3] & 0xff);

            iData = ((data[i * 4 + 32] & 0xff) << 24)
                    + ((data[i * 4 + 33] & 0xff) << 16)
                    + ((data[i * 4 + 34] & 0xff) << 8)
                    + (data[i * 4 + 35] & 0xff);

            if (iOp > 0) {
                for (columns = 0; columns < widthInBytes; columns += 2) {
                    iPl = columns + i * widthInBytes;
                    opCount = data[iOp++] & 0xff;

                    if (opCount > 0) {
                        if (columns < leftBound) {
                            leftBound = columns;
                        }
                        if (columns > rightBound) {
                            rightBound = columns;
                        }
                        opCode = data[iOp];
                        if (opCode <= 0) {
                            topBound = 0;
                        } else {
                            if (opCode < topBound) {
                                topBound = opCode;
                            }
                        }

                        for (; opCount > 0; opCount--) {
                            opCode = data[iOp++];
                            if (opCode > 0) {
                                iPl += opCode * interleave;
                            } else if (opCode < 0) {
                                opCode &= 0x7f;
                                while (opCode-- > 0) {
                                    planeBytes[iPl] = data[iData++];
                                    planeBytes[iPl + 1] = data[iData++];
                                    iPl += interleave;
                                }
                            } else {
                                opCode = data[iOp++] & 0xff;
                                if (opCode == 0) {
                                    return;
                                }
                                copyByte1 = data[iData++];
                                copyByte2 = data[iData++];
                                while (opCode-- > 0) {
                                    planeBytes[iPl] = copyByte1;
                                    planeBytes[iPl + 1] = copyByte2;
                                    iPl += interleave;
                                }
                            }
                        }

                        if (opCode <= 0) {
                            int bottom = (iPl - (columns + i * widthInBytes)) / interleave;
                            if (bottom > bottomBound) {
                                bottomBound = bottom;
                            }
                        } else {
                            if (height - opCode > bottomBound) {
                                bottomBound = height - opCode;
                            }
                        }
                    }
                }
            }
        }
        if (leftBound <= rightBound) {
            leftBound *= 8;
            rightBound = rightBound * 8 + 32;
        }
    }

    private void decodeVertical7Long(BitmapImage bitmap, ANIMMovieTrack track) {
        int columns = 0;
        int iOp = 0;
        int iData = 0;
        byte[] planeBytes = bitmap.getBitmap();
        int iPl = 0;
        int widthInBytes = bitmap.getBitplaneStride();
        int interleave = track.getNbPlanes() * widthInBytes;
        int opCode = 0;
        int opCount = 0;
        byte copyByte1 = 0;
        byte copyByte2 = 0;
        byte copyByte3 = 0;
        byte copyByte4 = 0;
        leftBound = widthInBytes;
        rightBound = 0;
        topBound = track.getHeight() - 1;
        bottomBound = 0;
        int height = track.getHeight() - 1;

        for (int i = 0; i < track.getNbPlanes(); i++) {
            iOp = ((data[i * 4] & 0xff) << 24)
                    + ((data[i * 4 + 1] & 0xff) << 16)
                    + ((data[i * 4 + 2] & 0xff) << 8)
                    + (data[i * 4 + 3] & 0xff);

            iData = ((data[i * 4 + 32] & 0xff) << 24)
                    + ((data[i * 4 + 33] & 0xff) << 16)
                    + ((data[i * 4 + 34] & 0xff) << 8)
                    + (data[i * 4 + 35] & 0xff);

            if (iOp > 0) {
                for (columns = 0; columns < widthInBytes; columns += 4) {
                    try {
                        iPl = columns + i * widthInBytes;
                        opCount = data[iOp++] & 0xff;

                        if (opCount > 0) {
                            if (columns < leftBound) {
                                leftBound = columns;
                            }
                            if (columns > rightBound) {
                                rightBound = columns;
                            }
                            opCode = data[iOp];
                            if (opCode <= 0) {
                                topBound = 0;
                            } else {
                                if (opCode < topBound) {
                                    topBound = opCode;
                                }
                            }

                            for (; opCount > 0; opCount--) {
                                opCode = data[iOp++];
                                if (opCode > 0) {
                                    iPl += opCode * interleave;
                                } else if (opCode < 0) {
                                    opCode &= 0x7f;
                                    while (opCode-- > 0) {
                                        planeBytes[iPl] = data[iData++];
                                        planeBytes[iPl + 1] = data[iData++];
                                        planeBytes[iPl + 2] = data[iData++];
                                        planeBytes[iPl + 3] = data[iData++];
                                        iPl += interleave;
                                    }
                                } else {
                                    opCode = data[iOp++] & 0xff;
                                    if (opCode == 0) {
                                        return;
                                    }
                                    copyByte1 = data[iData++];
                                    copyByte2 = data[iData++];
                                    copyByte3 = data[iData++];
                                    copyByte4 = data[iData++];
                                    while (opCode-- > 0) {
                                        planeBytes[iPl] = copyByte1;
                                        planeBytes[iPl + 1] = copyByte2;
                                        planeBytes[iPl + 2] = copyByte3;
                                        planeBytes[iPl + 3] = copyByte4;
                                        iPl += interleave;
                                    }
                                }
                            }

                            if (opCode <= 0) {
                                int bottom = (iPl - (columns + i * widthInBytes)) / interleave;
                                if (bottom > bottomBound) {
                                    bottomBound = bottom;
                                }
                            } else {
                                if (height - opCode > bottomBound) {
                                    bottomBound = height - opCode;
                                }
                            }
                        }
                    } catch (IndexOutOfBoundsException e) {


                        if (!isWarningPrinted) {
                            e.printStackTrace();
                            isWarningPrinted = true;
                        }
                    }
                }
            }
        }
        if (leftBound <= rightBound) {
            leftBound *= 8;
            rightBound = rightBound * 8 + 64;
        }
    }


    private void decodeJ(BitmapImage bitmap, ANIMMovieTrack track) {

        int nbPlanes = track.getNbPlanes();
        int widthInBytes = bitmap.getBitplaneStride();




        leftBound = track.getWidth() - 1;
        rightBound = 0;
        topBound = track.getHeight() - 1;
        bottomBound = 0;


        int pos = 0;


        byte[] planeBytes = bitmap.getBitmap();


        int changeType;
        try {
            decodingLoop:
            while (pos < data.length) {
                changeType = ((data[pos++] & 0xff) << 8) | ((data[pos++]) & 0xff);

                switch (changeType) {
                    case 0:
                        break decodingLoop;

                    case 1: {





                        int uniFlag = ((data[pos++] & 0xff) << 8) | ((data[pos++]) & 0xff);
                        int ySize = ((data[pos++] & 0xff) << 8) | ((data[pos++]) & 0xff);
                        int numBlocks = ((data[pos++] & 0xff) << 8) | ((data[pos++]) & 0xff);


                        for (int b = 0; b < numBlocks; b++) {
                            int offset = ((data[pos++] & 0xff) << 8) | ((data[pos++]) & 0xff);

                            leftBound = Math.min(leftBound, (offset % widthInBytes) * 8);
                            rightBound = Math.max(rightBound, (offset % widthInBytes) * 8 + 8);
                            topBound = Math.min(topBound, (offset / widthInBytes));
                            bottomBound = Math.max(bottomBound, (offset / widthInBytes) + ySize);

                            int realOffset = (offset / widthInBytes) * nbPlanes;
                            realOffset *= widthInBytes;
                            realOffset += offset % widthInBytes;

                            if (uniFlag == 1) {
                                for (int z = 0; z < nbPlanes; z++) {
                                    for (int y = 0; y < ySize; y++) {
                                        int dest = z * widthInBytes * ySize
                                                + y * widthInBytes
                                                + realOffset;
                                        planeBytes[dest] ^= data[pos++];
                                    }
                                }
                            } else {
                                for (int z = 0; z < nbPlanes; z++) {
                                    for (int y = 0; y < ySize; y++) {
                                        int dest = z * widthInBytes * ySize
                                                + y * widthInBytes
                                                + realOffset;
                                        planeBytes[dest] = data[pos++];
                                    }
                                }
                            }



                            if (pos % 2 == 1) {
                                pos++;
                            }
                        }
                        break;
                    }
                    case 2: {






                        int uniFlag = ((data[pos++] & 0xff) << 8) | ((data[pos++]) & 0xff);
                        int ySize = ((data[pos++] & 0xff) << 8) | ((data[pos++]) & 0xff);
                        int xSize = ((data[pos++] & 0xff) << 8) | ((data[pos++]) & 0xff);
                        int numBlocks = ((data[pos++] & 0xff) << 8) | ((data[pos++]) & 0xff);


                        for (int b = 0; b < numBlocks; b++) {
                            int offset = ((data[pos++] & 0xff) << 8) | ((data[pos++]) & 0xff);

                            leftBound = Math.min(leftBound, (offset % widthInBytes) * 8);
                            rightBound = Math.max(rightBound, (offset % widthInBytes + xSize) * 8 + 8);
                            topBound = Math.min(topBound, (offset / widthInBytes));
                            bottomBound = Math.max(bottomBound, (offset / widthInBytes) + ySize);

                            int realOffset = (offset / widthInBytes) * nbPlanes;
                            realOffset *= widthInBytes;
                            realOffset += offset % widthInBytes;

                            if (uniFlag == 1) {
                                for (int z = 0; z < nbPlanes; z++) {
                                    for (int y = 0; y < ySize; y++) {
                                        for (int x = 0; x < xSize; x++) {
                                            int dest = z * widthInBytes * ySize
                                                    + y * widthInBytes
                                                    + realOffset + x;
                                            planeBytes[dest] ^= data[pos++];
                                        }
                                    }
                                }
                            } else {
                                for (int z = 0; z < nbPlanes; z++) {
                                    for (int y = 0; y < ySize; y++) {
                                        for (int x = 0; x < xSize; x++) {
                                            int dest = z * widthInBytes * ySize
                                                    + y * widthInBytes
                                                    + realOffset + x;
                                            planeBytes[dest] = data[pos++];
                                        }
                                    }
                                }
                            }



                            if (pos % 2 == 1) {
                                pos++;
                            }
                        }
                        break;
                    }
                    default:
                        System.out.println("Unsupported changeType in 'J' delta frame:" + changeType);
                        break decodingLoop;

                }
            }
        } catch (IndexOutOfBoundsException e) {


            if (!isWarningPrinted) {
                e.printStackTrace();
                isWarningPrinted = true;
            }
        }

    }

    @Override
    public int getTopBound(ANIMMovieTrack track) {
        return topBound;
    }

    @Override
    public int getBottomBound(ANIMMovieTrack track) {
        return bottomBound;
    }

    @Override
    public int getLeftBound(ANIMMovieTrack track) {
        return leftBound;
    }

    @Override
    public int getRightBound(ANIMMovieTrack track) {
        return rightBound;
    }


    @Override
    public boolean isBidirectional() {
        switch (getOperation()) {
            case OP_Direct:
                return true;
            case OP_ByteVertical:
                if (getBits() == BIT_XOR) {
                    return true;
                }
                break;
            case OP_J:
                return true;
            default:
                break;
        }
        return false;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy