diff --git a/src/__tests__/rgb.test.ts b/src/__tests__/rgb.test.ts
new file mode 100644
index 0000000..9b9a2fa
--- /dev/null
+++ b/src/__tests__/rgb.test.ts
@@ -0,0 +1,102 @@
+import assert from 'assert';
+import fs from 'fs';
+import path from 'path';
+
+import { rgb, IndexedColors, decode, encode, IndexedColorBitDepth } from '..';
+
+describe('rgb', () => {
+  it('1 bit', () => {
+    const data = new Uint8Array([27]);
+    const palette: IndexedColors = [
+      [0, 0, 1],
+      [0, 0, 2],
+    ];
+
+    const view = rgb(data, 1, palette);
+    assert.strictEqual(
+      Buffer.from(view).toString('hex'),
+      '000001000001000001000002000002000001000002000002',
+    );
+  });
+
+  it('2 bit', () => {
+    const data = new Uint8Array([27]);
+    const palette: IndexedColors = [
+      [0, 0, 1],
+      [0, 0, 2],
+      [0, 0, 3],
+      [0, 0, 4],
+    ];
+
+    const view = rgb(data, 2, palette);
+    assert.strictEqual(
+      Buffer.from(view).toString('hex'),
+      '000001000002000003000004',
+    );
+  });
+
+  it('4 bit', () => {
+    const data = new Uint8Array([18, 52, 86, 120]);
+    const palette: IndexedColors = [
+      [0, 0, 0],
+      [0, 0, 1],
+      [0, 0, 2],
+      [0, 0, 3],
+      [0, 0, 4],
+      [0, 0, 5],
+      [0, 0, 6],
+      [0, 0, 7],
+      [0, 0, 8],
+    ];
+
+    const view = rgb(data, 4, palette);
+    assert.strictEqual(
+      Buffer.from(view).toString('hex'),
+      '000001000002000003000004000005000006000007000008',
+    );
+  });
+
+  it('8 bit', () => {
+    const data = new Uint8Array([1, 2, 3, 4]);
+    const palette: IndexedColors = [
+      [0, 0, 0],
+      [0, 0, 1],
+      [0, 0, 2],
+      [0, 0, 3],
+      [0, 0, 4],
+    ];
+
+    const view = rgb(data, 8, palette);
+    assert.strictEqual(
+      Buffer.from(view).toString('hex'),
+      '000001000002000003000004',
+    );
+  });
+
+  it('convert palette.png tp simple file', () => {
+    const imgFile = fs.readFileSync(
+      path.join(__dirname, '../../img/palette.png'),
+    );
+    const img = decode(imgFile);
+    assert.ok(img.palette);
+    assert.notStrictEqual(img.depth, 16);
+
+    const data = rgb(
+      img.data as Uint8Array,
+      img.depth as IndexedColorBitDepth,
+      img.palette,
+    );
+    const newImg = encode({
+      width: img.width,
+      height: img.height,
+      channels: 3,
+      depth: 8,
+      data,
+    });
+    // Uncomment the next line for manual testing
+    // fs.writeFileSync(path.join(__dirname, "../../img/palette.new.png"), newImg, { flag: "w+" });
+
+    const newImageParsed = decode(newImg);
+    assert.strictEqual(newImageParsed.data.byteLength, 90000);
+  });
+});
diff --git a/src/index.ts b/src/index.ts
index 580c0f3..759ed19 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -6,6 +6,8 @@ import {
   DecodedPng,
   ImageData,
   PngEncoderOptions,
+  IndexedColorBitDepth,
+  IndexedColors,
 } from './types';
 
 export * from './types';
@@ -23,4 +25,57 @@ function encodePng(png: ImageData, options?: PngEncoderOptions): Uint8Array {
   return encoder.encode();
 }
 
-export { decodePng as decode, encodePng as encode };
+function rgb(
+  data: Uint8Array,
+  depth: IndexedColorBitDepth,
+  palette: IndexedColors,
+) {
+  const indexSize = data.length * (8 / depth);
+  const resSize = indexSize * 3;
+  const res = new Uint8Array(resSize);
+
+  let offset = 0;
+  let indexPos = 0;
+  const indexes = new Uint8Array(indexSize);
+  let bit = 0xff;
+  switch (depth) {
+    case 1:
+      bit = 0x80;
+      break;
+    case 2:
+      bit = 0xc0;
+      break;
+    case 4:
+      bit = 0xf0;
+      break;
+    case 8:
+      bit = 0xff;
+      break;
+    default:
+      throw new Error('Incorrect depth value');
+  }
+
+  for (const item of data) {
+    let bit2 = bit;
+    let shift = 8;
+    while (bit2) {
+      shift -= depth;
+      indexes[indexPos++] = (item & bit2) >> shift;
+
+      bit2 >>= depth;
+    }
+  }
+
+  for (const index of indexes) {
+    const color = palette[index];
+    if (!color) {
+      throw new Error('Incorrect index of palette color');
+    }
+    res.set(color, offset);
+    offset += 3;
+  }
+
+  return res;
+}
+
+export { decodePng as decode, encodePng as encode, rgb };
diff --git a/src/types.ts b/src/types.ts
index e17d375..70ac807 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -9,6 +9,8 @@ export type DecoderInputType = IOBuffer | ArrayBufferLike | ArrayBufferView;
 
 export type BitDepth = 1 | 2 | 4 | 8 | 16;
 
+export type IndexedColorBitDepth = 1 | 2 | 4 | 8;
+
 export interface PngResolution {
   /**
    * Pixels per unit, X axis