SecurityYourFingers
@SecurityYourFingers
I make other things, but i know that without your

Как правильно записать буфер в файл? Какая должна быть кодировка?

Доброго времени суток!
Я выполняю курсовую работу по теме "кодирование bmp изображения по методу Хаффмана"
Описание этапов кодирования

1) Читаем изображение и записываем в буфер
2) Читаем заголовок изображения и записываем в отдельный буфер (заголовок bmp это первые 54 байта)
3) Читаем матрицу изображения и записываем в отдельный буфер
4) Использование алгоритма Хаффмана для кодирования матрицы изображения(описание алгоритма есть в интернете в общих подходах)
5) После кодирования матрицы получаем таблицу кодировки и закодированную матрицу(в виде нулей и единиц)
6) Записываем в новый буфер таблицу кодировки
7) Записываем в новый буфер закодированную матрицу
8) Соединяем три буфера(заголовок bmp, таблицу кодировки, матрицу) в один буфер
9) Записываем созданный буфер в новый файл
Описание этапов декодирования

1) Читаем изображение и записываем в буфер
2) Читаем заголовок изображения и записываем в отдельный буфер (заголовок bmp это первые 54 байта)
3) Читаем таблицу кодировки и записываем в отдельный буфер
4) Читаем закодированную матрицу и записываем в отдельный буфер
5) Соеднияем буферы(таблицы и матрицы) в один буфер
6) Используем алгоритм Хаффмана для декодирования
7) Получаем декодированную матрицу (в формате строки)
8) Записываем декодированную матрицу в буфер
9) Соединяем буфер заголовка bmp и буфер декодированной матрицы
10) Записываем в новый файл
Проблема: при декодировании получаю матрицу в виде строки. Если эту строку записать в буфер, то получится ошибка(дело в кодировке)
Если открыть исходное изображение блокнотом:
5cdc105533c84289251505.png
Если открыть декодированное изображение блокнотом:
5cdc106cf0df9328182178.png

Сразу видно, дело в кодировке.

Мой код на Node Js
var express = require('express');
var app = express();
const fs = require('fs');
//create server on 3330 port
// app.listen(3330, function () {
//     console.log('Example app listening on port 3330!');
// });
//********S**T**A**R**T***H*U*F*F*M*A*N***************//Код хаффмана работает правильно, принимает строку, возвращает строку
var Heap = function(fn) {
    this.fn = fn || function(e) {
        return e;
    };
    this.items = [];
};
Heap.prototype = {
    swap: function(i, j) {
        this.items[i] = [
            this.items[j],
            this.items[j] = this.items[i]
        ][0];
    },
    bubble: function(index) {
        var parent = ~~((index - 1) / 2);
        if (this.item(parent) < this.item(index)) {
            this.swap(index, parent);
            this.bubble(parent);
        }
    },
    item: function(index) {
        return this.fn(this.items[index]);
    },
    pop: function() {
        return this.items.pop();
    },
    sift: function(index, end) {
        var child = index * 2 + 1;
        if (child < end) {
            if (child + 1 < end && this.item(child + 1) > this.item(child)) {
                child++;
            }
            if (this.item(index) < this.item(child)) {
                this.swap(index, child);
                return this.sift(child, end);
            }
        }
    },
    push: function() {
        var lastIndex = this.items.length;
        for (var i = 0; i < arguments.length; i++) {
            this.items.push(arguments[i]);
            this.bubble(lastIndex++);
        }
    },
    get length() {
        return this.items.length;
    }
};
var Huffman = {
    encode: function(data) {
        var prob = {};
        var tree = new Heap(function(e) {
            return e[0];
        });
        for (var i = 0; i < data.length; i++) {
            if (prob.hasOwnProperty(data[i])) {
                prob[data[i]]++;
            } else {
                prob[data[i]] = 1;
            }
        }
        Object.keys(prob).sort(function(a, b) {
            return ~~(Math.random() * 2);
        }).forEach(function(e) {
            tree.push([prob[e], e]);
        });
        while (tree.length > 1) {
            var first = tree.pop(),
                second = tree.pop();
            tree.push([first[0] + second[0], [first[1], second[1]]]);
        }
        var dict = {};
        var recurse = function(root, string) {
            if (root.constructor === Array) {
                recurse(root[0], string + '0');
                recurse(root[1], string + '1');
            } else {
                dict[root] = string;
            }
        };
        tree.items = tree.pop()[1];
        recurse(tree.items, '');
        var result = '';
        for (var i = 0; i < data.length; i++) {
            result += dict[data.charAt(i)];
        }
        var header = Object.keys(dict).map(function(e) {
            return e.charCodeAt(0) + '|' + dict[e];
        }).join('-') + '/';
        huffmanTable = header;
        huffmanBitmap = result;
        return header + result;
    },
    decode: function(string) {
        string = string.split('/');
        var data = string[1].split(''),
            header = {};
        string[0].split('-').forEach(function(e) {
            var values = e.split('|');
            header[values[1]] = String.fromCharCode(values[0]);
        });
        var result = '';
        while (data.length) {
            var i = 0,
                cur = '';
            while (data.length) {
                cur += data.shift();
                if (header.hasOwnProperty(cur)) {
                    result += header[cur];
                    break;
                }
            }
        }
        // dataBitmap = result;
        return result;
    }
};
//***********E***N***D**H*U*F*F*M*A*N***************//
var huffmanTable = '',
    huffmanBitmap = '',
    dataBitmap = '',
    bmpBuffer,//read file
    bmpHead,//new empty
    arrByteTable = [],
    tableHuff,//new buffer for tableHuff
    currentOffsetByte,//current offset
    arrByteBitmap = [],
    bmpData,//add info into bmpData
    huffData,//add huff info
    offsetByte,//new offset
    totalLength,//size new buffer
    newArrByteBitmap = [],//for encode
    newBuffer;//create new buffer

function toReadFile(bmpName) {
    bmpBuffer = fs.readFileSync(bmpName);
    console.log('bmpBuffer length: '+bmpBuffer.length);
}
function getBmpHead() {
    bmpHead = Buffer.alloc(54);
    bmpBuffer.copy(bmpHead, 0, 0, 53);
    return bmpHead;
}
function getBmpData() {
    var leng = bmpBuffer.length - bmpHead.length;
    bmpData = Buffer.alloc(leng);
    bmpBuffer.copy(bmpData, 0, 54);//запись матрицы в буфер
    return bmpData;
}
function toWriteFileEncode() {
    totalLength = bmpHead.length + huffData.length + tableHuff.length;
    newBuffer = Buffer.concat([bmpHead, tableHuff, huffData], totalLength);
    fs.writeFileSync('img/picture-encode.bmp', newBuffer);
}
function toEncode() {
    Huffman.encode(bmpData.toString());//выполняется кодирование по хаффману
    tableHuff = Buffer.alloc(huffmanTable.length);
    tableHuff = Buffer.from(huffmanTable);//запись таблицы кодирования
    currentOffsetByte = bmpHead.readUInt8(10);//читаем текущий отступ
    offsetByte = currentOffsetByte + tableHuff.length;//создаем новый отступ
    bmpHead.writeUInt8(offsetByte, 10);//запись нового отступа
    huffData = Buffer.alloc(huffmanBitmap.length);
    huffData = Buffer.from(huffmanBitmap);//запись код-матрицы в буфер
    toWriteFileEncode();
}
function toDecode() {
    currentOffsetByte = bmpHead.readUInt8(10);
    tableHuff = Buffer.alloc(currentOffsetByte - 54);
    bmpBuffer.copy(tableHuff, 0, 54, currentOffsetByte);//запись таблицы в буфер
    huffData = Buffer.alloc(bmpBuffer.length - currentOffsetByte);
    bmpBuffer.copy(huffData, 0, currentOffsetByte);//запись код-матрицы в буфер
    newBuffer = tableHuff.toString() + huffData.toString();//соединение таблицы и код-матрицы
    dataBitmap = Huffman.decode(newBuffer);
    bmpData = Buffer.from(dataBitmap);//запись матрицы в буфер
    bmpHead.writeUInt8(54, 10);
    totalLength = bmpHead.length + bmpData.length;
    newBuffer = Buffer.concat([bmpHead, bmpData], totalLength);
    fs.writeFileSync('img/picture-decode.bmp', newBuffer);
}

//Запустить для кодирования
// toReadFile('img/picture2.bmp');//чтение файла и запись в буфер
// getBmpHead();//запись заголовока bmp в буфер bmpHead
// getBmpData();//запись тела bmp в буфер до кодирования
// toEncode();

//Запустить для декодирования
toReadFile('img/picture-encode.bmp');//чтение файла и запись в буфер
getBmpHead();//запись заголовока bmp в буфер bmpHead
toDecode();

  • Вопрос задан
  • 102 просмотра
Решения вопроса 1
@Sumor
По-умолчанию node.js работает с файлами как с текстовыми файлами в различных кодировках.
bmp это бинарный (нетекстовый) формат. Для его чтения/записи нужно явно указывать кодировку 'binary' при вызове readFileSync, writeFileSync и т.п.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы