Chain code is a lossless compression technique used for representing an object in images. The co-ordinates of any continuous boundary of an object can be represented as a string of numbers where each number represents a particular direction in which the next point on the connected line is present. One point is taken as the reference/starting point and on plotting the points generated from the chain, the original figure can be re-drawn.
This article describes how to generate a 8-neighbourhood chain code of a 2-D straight line. In a rectangular grid, a point can have at most 8 surrounding points as shown below. The next point on the line has to be one of these 8 surrounding points. Each direction is assigned a code. Using this code we can find out which of the surrounding point should be plotted next.

The chain codes could be generated by using conditional statements for each direction but it becomes very tedious to describe for systems having large number of directions(3-D grids can have up to 26 directions). Instead we use a hash function. The difference in X(dx ) and Y(dy ) co-ordinates of two successive points are calculated and hashed to generate the key for the chain code between the two points.
Chain code list: [5, 6, 7, 4, -1, 0, 3, 2, 1]
Hash function: C(dx, dy) = 3dy + dx + 4
Hash table:-
dx | dy | C(dx, dy) | chainCode[C] |
---|
1 | 0 | 5 | 0 |
1 | 1 | 8 | 1 |
0 | 1 | 7 | 2 |
-1 | 1 | 6 | 3 |
-1 | 0 | 3 | 4 |
-1 | -1 | 0 | 5 |
0 | -1 | 1 | 6 |
1 | -1 | 2 | 7 |
The function does not generate the value 4 so a dummy value is stored there.
Examples:
Input : (2, -3), (-4, 2)
Output : Chain code for the straight line from (2, -3) to (-4, 2) is 333433

Input : (-7, -4), (9, 3)
Output : Chain code for the straight line from (-7, -4) to (9, 3) is 0101010100101010

C++
// C++ code for generating 8-neighbourhood chain
// code for a 2-D line
#include <iostream>
#include <math.h>
#include <vector>
std::vector<int> codeList = { 5, 6, 7, 4, -1, 0, 3, 2, 1 };
// This function generates the chaincode
// for transition between two neighbour points
int getChainCode(int x1, int y1, int x2, int y2)
{
int dx = x2 - x1;
int dy = y2 - y1;
int hashKey = 3 * dy + dx + 4;
return codeList[hashKey];
}
// This function generates the list of
// chaincodes for given list of points
std::vector<int> generateChainCode(
std::vector<std::vector<int> > ListOfPoints)
{
std::vector<int> chainCode;
for (int i = 0; i < ListOfPoints.size() - 1; i++) {
std::vector<int> a = ListOfPoints[i];
std::vector<int> b = ListOfPoints[i + 1];
chainCode.push_back(
getChainCode(a[0], a[1], b[0], b[1]));
}
return chainCode;
}
// This function generates the list of points for
// a straight line using Bresenham's Algorithm
std::vector<std::vector<int> > Bresenham2D(int x1, int y1,
int x2, int y2)
{
std::vector<std::vector<int> > ListOfPoints;
ListOfPoints.push_back({ x1, y1 });
int xdif = x2 - x1;
int ydif = y2 - y1;
int dx = abs(xdif);
int dy = abs(ydif);
int xs;
if (xdif > 0) {
xs = 1;
}
else {
xs = -1;
}
int ys;
if (ydif > 0) {
ys = 1;
}
else {
ys = -1;
}
if (dx > dy) {
// Driving axis is the X-axis
int p = 2 * dy - dx;
while (x1 != x2) {
x1 += xs;
if (p >= 0) {
y1 += ys;
p -= 2 * dx;
}
p += 2 * dy;
ListOfPoints.push_back({ x1, y1 });
}
}
else {
// Driving axis is the Y-axis
int p = 2 * dx - dy;
while (y1 != y2) {
y1 += ys;
if (p >= 0) {
x1 += xs;
p -= 2 * dy;
}
p += 2 * dx;
ListOfPoints.push_back({ x1, y1 });
}
}
return ListOfPoints;
}
void DriverFunction()
{
int x1 = -9;
int y1 = -3;
int x2 = 10;
int y2 = 1;
std::vector<std::vector<int> > ListOfPoints
= Bresenham2D(x1, y1, x2, y2);
std::vector<int> chainCode
= generateChainCode(ListOfPoints);
std::string chainCodeString = "";
for (int i = 0; i < chainCode.size(); i++) {
chainCodeString += std::to_string(chainCode[i]);
}
std::cout << "Chain code for the straight line from ("
<< x1 << "," << y1 << ") to (" << x2 << ","
<< y2 << ") is " << chainCodeString
<< std::endl;
}
int main()
{
DriverFunction();
return 0;
}
// This code is contributed by ishankhndelwals.
Java
import java.util.ArrayList;
import java.util.List;
public class Main {
static List<Integer> codeList
= new ArrayList<Integer>();
static
{
codeList.add(5);
codeList.add(6);
codeList.add(7);
codeList.add(4);
codeList.add(-1);
codeList.add(0);
codeList.add(3);
codeList.add(2);
codeList.add(1);
}
// This function generates the chaincode
// for transition between two neighbour points
static int getChainCode(int x1, int y1, int x2, int y2)
{
int dx = x2 - x1;
int dy = y2 - y1;
int hashKey = 3 * dy + dx + 4;
return codeList.get(hashKey);
}
// This function generates the list of
// chaincodes for given list of points
static List<Integer>
generateChainCode(List<List<Integer> > ListOfPoints)
{
List<Integer> chainCode = new ArrayList<Integer>();
for (int i = 0; i < ListOfPoints.size() - 1; i++) {
List<Integer> a = ListOfPoints.get(i);
List<Integer> b = ListOfPoints.get(i + 1);
chainCode.add(getChainCode(a.get(0), a.get(1),
b.get(0), b.get(1)));
}
return chainCode;
}
// This function generates the list of points for
// a straight line using Bresenham's Algorithm
static List<List<Integer> > Bresenham2D(int x1, int y1,
int x2, int y2)
{
List<List<Integer> > ListOfPoints
= new ArrayList<List<Integer> >();
ListOfPoints.add(List.of(x1, y1));
int xdif = x2 - x1;
int ydif = y2 - y1;
int dx = Math.abs(xdif);
int dy = Math.abs(ydif);
int xs;
if (xdif > 0) {
xs = 1;
}
else {
xs = -1;
}
int ys;
if (ydif > 0) {
ys = 1;
}
else {
ys = -1;
}
if (dx > dy) {
// Driving axis is the X-axis
int p = 2 * dy - dx;
while (x1 != x2) {
x1 += xs;
if (p >= 0) {
y1 += ys;
p -= 2 * dx;
}
p += 2 * dy;
ListOfPoints.add(List.of(x1, y1));
}
}
else {
// Driving axis is the Y-axis
int p = 2 * dx - dy;
while (y1 != y2) {
y1 += ys;
if (p >= 0) {
x1 += xs;
p -= 2 * dy;
}
p += 2 * dx;
ListOfPoints.add(List.of(x1, y1));
}
}
return ListOfPoints;
}
static void DriverFunction()
{
int x1 = -9;
int y1 = -3;
int x2 = 10;
int y2 = 1;
List<List<Integer> > ListOfPoints
= Bresenham2D(x1, y1, x2, y2);
List<Integer> chainCode
= generateChainCode(ListOfPoints);
StringBuilder chainCodeString = new StringBuilder();
for (int i = 0; i < chainCode.size(); i++) {
chainCodeString.append(
Integer.toString(chainCode.get(i)));
}
System.out.println(
"Chain code for the straight line from (" + x1
+ "," + y1 + ") to (" + x2 + "," + y2 + ") is "
+ chainCodeString);
}
public static void main(String[] args)
{
DriverFunction();
}
}
// This code is contributed by ishankhandelwals.
Python3
# Python3 code for generating 8-neighbourhood chain
# code for a 2-D line
codeList = [5, 6, 7, 4, -1, 0, 3, 2, 1]
# This function generates the chaincode
# for transition between two neighbour points
def getChainCode(x1, y1, x2, y2):
dx = x2 - x1
dy = y2 - y1
hashKey = 3 * dy + dx + 4
return codeList[hashKey]
'''This function generates the list of
chaincodes for given list of points'''
def generateChainCode(ListOfPoints):
chainCode = []
for i in range(len(ListOfPoints) - 1):
a = ListOfPoints[i]
b = ListOfPoints[i + 1]
chainCode.append(getChainCode(a[0], a[1], b[0], b[1]))
return chainCode
'''This function generates the list of points for
a straight line using Bresenham's Algorithm'''
def Bresenham2D(x1, y1, x2, y2):
ListOfPoints = []
ListOfPoints.append([x1, y1])
xdif = x2 - x1
ydif = y2 - y1
dx = abs(xdif)
dy = abs(ydif)
if(xdif > 0):
xs = 1
else:
xs = -1
if (ydif > 0):
ys = 1
else:
ys = -1
if (dx > dy):
# Driving axis is the X-axis
p = 2 * dy - dx
while (x1 != x2):
x1 += xs
if (p >= 0):
y1 += ys
p -= 2 * dx
p += 2 * dy
ListOfPoints.append([x1, y1])
else:
# Driving axis is the Y-axis
p = 2 * dx-dy
while(y1 != y2):
y1 += ys
if (p >= 0):
x1 += xs
p -= 2 * dy
p += 2 * dx
ListOfPoints.append([x1, y1])
return ListOfPoints
def DriverFunction():
(x1, y1) = (-9, -3)
(x2, y2) = (10, 1)
ListOfPoints = Bresenham2D(x1, y1, x2, y2)
chainCode = generateChainCode(ListOfPoints)
chainCodeString = "".join(str(e) for e in chainCode)
print ('Chain code for the straight line from', (x1, y1),
'to', (x2, y2), 'is', chainCodeString)
DriverFunction()
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CPP_to_C_Sharp
{
class Program
{
static List<int> codeList = new List<int> { 5, 6, 7, 4, -1, 0, 3, 2, 1 };
// This function generates the chaincode
// for transition between two neighbour points
static int getChainCode(int x1, int y1, int x2, int y2)
{
int dx = x2 - x1;
int dy = y2 - y1;
int hashKey = 3 * dy + dx + 4;
return codeList[hashKey];
}
// This function generates the list of
// chaincodes for given list of points
static List<int> generateChainCode(
List<List<int>> ListOfPoints)
{
List<int> chainCode = new List<int>();
for (int i = 0; i < ListOfPoints.Count - 1; i++)
{
List<int> a = ListOfPoints[i];
List<int> b = ListOfPoints[i + 1];
chainCode.Add(getChainCode(a[0], a[1], b[0], b[1]));
}
return chainCode;
}
// This function generates the list of points for
// a straight line using Bresenham's Algorithm
static List<List<int>> Bresenham2D(int x1, int y1,
int x2, int y2)
{
List<List<int>> ListOfPoints = new List<List<int>>();
ListOfPoints.Add(new List<int> { x1, y1 });
int xdif = x2 - x1;
int ydif = y2 - y1;
int dx = Math.Abs(xdif);
int dy = Math.Abs(ydif);
int xs;
if (xdif > 0)
{
xs = 1;
}
else
{
xs = -1;
}
int ys;
if (ydif > 0)
{
ys = 1;
}
else
{
ys = -1;
}
if (dx > dy)
{
// Driving axis is the X-axis
int p = 2 * dy - dx;
while (x1 != x2)
{
x1 += xs;
if (p >= 0)
{
y1 += ys;
p -= 2 * dx;
}
p += 2 * dy;
ListOfPoints.Add(new List<int> { x1, y1 });
}
}
else
{
// Driving axis is the Y-axis
int p = 2 * dx - dy;
while (y1 != y2)
{
y1 += ys;
if (p >= 0)
{
x1 += xs;
p -= 2 * dy;
}
p += 2 * dx;
ListOfPoints.Add(new List<int> { x1, y1 });
}
}
return ListOfPoints;
}
static void DriverFunction()
{
int x1 = -9;
int y1 = -3;
int x2 = 10;
int y2 = 1;
List<List<int>> ListOfPoints
= Bresenham2D(x1, y1, x2, y2);
List<int> chainCode
= generateChainCode(ListOfPoints);
string chainCodeString = "";
for (int i = 0; i < chainCode.Count; i++)
{
chainCodeString += chainCode[i].ToString();
}
Console.WriteLine("Chain code for the straight line from ("
+ x1 + "," + y1 + ") to (" + x2 + ","
+ y2 + ") is " + chainCodeString);
}
static void Main(string[] args)
{
DriverFunction();
}
}
}
// This code is contributed by ishankhandelwals.
JavaScript
// JavaScript code for generating 8-neighbourhood chain
// code for a 2-D line
let codeList = [5, 6, 7, 4, -1, 0, 3, 2, 1];
// This function generates the chaincode
// for transition between two neighbour points
function getChainCode(x1, y1, x2, y2){
let dx = x2 - x1;
let dy = y2 - y1;
let hashKey = 3 * dy + dx + 4;
return codeList[hashKey];
}
// This function generates the list of
// chaincodes for given list of points
function generateChainCode(ListOfPoints){
let chainCode = [];
for(let i = 0; i < ListOfPoints.length-1; i++){
let a = ListOfPoints[i];
let b = ListOfPoints[i + 1];
chainCode.push(getChainCode(a[0], a[1], b[0], b[1]));
}
return chainCode;
}
// This function generates the list of points for
// a straight line using Bresenham's Algorithm
function Bresenham2D(x1, y1, x2, y2){
let ListOfPoints = [];
ListOfPoints.push([x1, y1]);
let xdif = x2 - x1;
let ydif = y2 - y1;
let dx = Math.abs(xdif);
let dy = Math.abs(ydif);
if(xdif > 0){
xs = 1;
}
else{
xs = -1;
}
if (ydif > 0){
ys = 1;
}
else{
ys = -1;
}
if (dx > dy){
// Driving axis is the X-axis
let p = 2 * dy - dx;
while (x1 != x2){
x1 += xs
if (p >= 0){
y1 += ys;
p -= 2 * dx;
}
p += 2 * dy;
ListOfPoints.push([x1, y1]);
}
}
else{
// Driving axis is the Y-axis
let p = 2 * dx-dy;
while(y1 != y2){
y1 += ys;
if (p >= 0){
x1 += xs;
p -= 2 * dy;
}
p += 2 * dx;
ListOfPoints.push([x1, y1]);
}
}
return ListOfPoints
}
function DriverFunction(){
let x1 = -9;
let y1 = -3;
let x2 = 10;
let y2 = 1;
let ListOfPoints = Bresenham2D(x1, y1, x2, y2);
let chainCode = generateChainCode(ListOfPoints);
let chainCodeString = "";
for(let i = 0; i < chainCode.length; i++){
chainCodeString += chainCode[i].toString();
}
console.log("Chain code for the straight line from (", x1,",", y1,")","to","(", x2,",", y2,")", "is", chainCodeString);
}
DriverFunction();
// The code is contributed by Nidhi goel
Output: Chain code for the straight line from (-9, -3) to (10, 1) is 0010000100010000100
Similar Reads
Line chart in Pygal A line chart or line graph is a type of chart which helps to displays the information as a series of all data points called âmarkersâ and those markers are connected straight through line segments. It is a basic type of chart common in many fields which shows ascending or descending in a graph. A li
2 min read
Program to find slope of a line Given two coordinates, find the slope of a straight line. Examples: Input : x1 = 4, y1 = 2, x2 = 2, y2 = 5 Output : Slope is -1.5 Approach: To calculate the slope of a line you need only two points from that line, (x1, y1) and (x2, y2). The equation used to calculate the slope from two points is: Be
3 min read
PYGLET â Drawing Line In this article, we will see how we can draw line on window in PYGLET module in python. Pyglet is easy to use but powerful library for developing visually rich GUI applications like games, multimedia etc. A window is a "heavyweight" object occupying operating system resources. Windows may appear as
3 min read
Python OpenCV | cv2.line() method OpenCV-Python is a library of Python bindings designed to solve computer vision problems. cv2.line() method is used to draw a line on any image.Syntax:cv2.line(image, start_point, end_point, color, thickness) Parameters: image: It is the image on which line is to be drawn. start_point: It is the sta
3 min read
Python OpenCV - cv2.polylines() method OpenCV is the huge open-source library for computer vision, machine learning, and image processing and it now plays a major role in real-time operations which are very important in todayâs systems. By using OpenCV one can process images and videos to identify objects, faces, or even the handwriting
3 min read