Fix the error  java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 . 
	private void cannyImage() {
		if (image != null) {
		String inputMask = JOptionPane.showInputDialog(this, "Enter a mask size (odd number >= 3):");
		int kernelSize = Integer.parseInt(inputMask);
		if (kernelSize % 2 == 0 || kernelSize < 3) {
		JOptionPane.showMessageDialog(this, "Invalid mask size. Please enter an odd number >= 3.");
		return;
		}
		float[][] mask = new float[kernelSize][kernelSize];
		for (int i = 0; i < mask.length; i++) {
		for (int j = 0; j < mask[i].length; j++) {
		mask[i][j] = 1.0f / (mask.length * mask[i].length);
		}
		}
		// Use a custom input dialog with a slider for the threshold values
		JPanel panel = new JPanel(new GridLayout(0, 1));
		JSlider lowThresholdSlider = new JSlider(JSlider.HORIZONTAL, 0, 255, 50);
		JSlider highThresholdSlider = new JSlider(JSlider.HORIZONTAL, 0, 255, 100);
		panel.add(new JLabel("Low Threshold:"));
		panel.add(lowThresholdSlider);
		panel.add(new JLabel("High Threshold:"));
		panel.add(highThresholdSlider);
		int result = JOptionPane.showOptionDialog(this, panel, "Enter Threshold Values", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null);
		if (result == JOptionPane.OK_OPTION) {
		int lowThreshold = lowThresholdSlider.getValue();
		int highThreshold = highThresholdSlider.getValue();
		applyCannyEdgeDetector(image, mask, lowThreshold, highThreshold, kernelSize);
		}
		}
		}
		private BufferedImage applyCannyEdgeDetector(BufferedImage image, float[][] mask, int lowThreshold, int highThreshold, int kernelSize) {
		int width = image.getWidth();
		int height = image.getHeight();
		BufferedImage resultImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		int[] pixels = new int[width * height];
		int[] edges = new int[width * height];

		image.getRGB(0, 0, width, height, pixels, 0, width);

		int[][] sobelX = { { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } };
		int[][] sobelY = { { -1, -2, -1 }, { 0, 0, 0 }, { 1, 2, 1 } };

		int[] grayPixels = convertToGrayscale(pixels);

		int[] gradientX = getConvolution(grayPixels, sobelX, width, height, kernelSize);
		int[] gradientY = getConvolution(grayPixels, sobelY, width, height, kernelSize);

		for (int i = 0; i < pixels.length; i++) {
		int gx = gradientX[i];
		int gy = gradientY[i];
		edges[i] = (int) Math.sqrt(gx * gx + gy * gy);
		}

		int[] thresholdEdges = applyHysteresis(edges, lowThreshold, highThreshold, width, height);

		for (int i = 0; i < pixels.length; i++) {
		if (thresholdEdges[i] != 0) {
		resultImage.setRGB(i % width, i / width, 0);
		} else {
		resultImage.setRGB(i % width, i / width, 0xFFFFFF);
		}
		}

		return resultImage;
		}

		private int[] applyHysteresis(int[] edges, int low, int high, int width, int height) {
		int[] result = new int[edges.length];
		Arrays.fill(result, 0);
		for (int i = 0; i < edges.length; i++) {
		if (edges[i] >= high && result[i] == 0) {
		trace(result, edges, low, high, i, width, height);
		}
		}

		return result;
		}

		private void trace(int[] result, int[] edges, int low, int high, int i, int width, int height) {
		result[i] = 255;
		LinkedList<Integer> queue = new LinkedList<>();
		queue.offer(i);

		while (!queue.isEmpty()) {
		int currIndex = queue.poll();
		int currX = currIndex % width;
		int currY = currIndex / width;

		for (int j = -1; j <= 1; j++) {
		for (int k = -1; k <= 1; k++) {
		int neighborX = currX + k;
		int neighborY = currY + j;
		int neighborIndex = neighborY * width + neighborX;

		if (neighborX >= 0 && neighborX < width &&
		neighborY >= 0 && neighborY < height &&
		neighborIndex >= 0 && neighborIndex < edges.length &&
		result[neighborIndex] == 0 && edges[neighborIndex] >= low &&
		edges[neighborIndex] <= high) {
		result[neighborIndex] = 255;
		queue.offer(neighborIndex);
		}
		}
		}
		}
		}

		private int[] getConvolution(int[] pixels, int[][] filter, int width, int height, int kernelSize) {
		int[] result = new int[pixels.length];
		int radius = kernelSize / 2;
		for (int y = 0; y < height; y++) {
		for (int x = 0; x < width; x++) {
		double sum = 0.0;

		for (int ky = -radius; ky <= radius; ky++) {
		for (int kx = -radius; kx <= radius; kx++) {
		int px = x + kx;
		int py = y + ky;

		if (px >= 0 && px < width && py >= 0 && py < height) {
		int i = py * width + px;
		double value = (double) pixels[i];
		sum += value * filter[ky + radius][kx + radius];
		}
		}
		}

		int i = y * width + x;
		result[i] = (int) sum;
		}
		}
		return result;
		}

		private int[] convertToGrayscale(int[] pixels) {
		int[] grayPixels = new int[pixels.length];
		for (int i = 0; i < pixels.length; i++) {
		int r = (pixels[i] >> 16) & 0xFF;
		int g = (pixels[i] >> 8) & 0xFF;
		int b = pixels[i] & 0xFF;
		int gray = (int) (0.2126 * r + 0.7152 * g + 0.0722 * b);
		grayPixels[i] = (gray << 16) + (gray << 8) + gray;
		}
		return grayPixels;
		}