LINUX.ORG.RU

[PureC] Работа с bmp


0

1

Появилось желание поработать с графической информацией, а именно попробовать себя в распознавании изображений, но я пока в начале пути, для начала надо научиться работать с битовыми массивами на нижнем уровне и был написан следующий код http://paste.org.ru/?k63kz2 , который пишет заголовок бмп файла, однако в конечном файле появляются лишнии 2 байта

$ xxd set.bmp 
0000000: 424d 0000 2616 0000 0100 0100 0004 0000  BM..&...........
ЧЯДНТ?



Последнее исправление: ice2heart (всего исправлений: 1)

Структура выравнивается. И вообще - никогда не пиши в файл данные _так_.

Deleted
()

приписываю двухнедельный курс лечения чтением стандарта си, три раза в день по 15 страниц.

arsi ★★★★★
()
Ответ на: комментарий от arsi

на него и операюсь, просто нет опыта по работе с бинарными файлами. если укажите более конкретно буду признателен

ice2heart
() автор топика
Ответ на: комментарий от ice2heart

а как правильно?

Либо отдельные поля структуры записывать по отдельности, либо отключить для конкретной структуры выравнивание (в разных компиляторах это делается по разному). И ещё нужно не забывать, что на разных архитектурах процессоров порядок байт в слове/двойном_слове/итп может быть разным.

Deleted
()
Ответ на: комментарий от ice2heart

как можно, опираясь на стандарт, полностью игнорировать выравнивание полей структур, размеров типов данных и порядок байт?

arsi ★★★★★
()
Ответ на: комментарий от Boy_from_Jungle

к сожалению, все описания бмп файлов основываются на M$, пришлось ввести для удобства работы.

ice2heart
() автор топика
Ответ на: комментарий от ice2heart

т.е. в структуре происходит выравнивание которое и добовляет лишнии байты?

Да.

Вообще, погугли перевод небольшой статьи «Fighting the lemmings». Там вроде и про выравнивание было.

Deleted
()
Ответ на: комментарий от arsi

знание стандарта ещё далеко от удовлетварительного, поэтому и спрашиваю совета у более оптынх программистов. где ошибки и как исправить

ice2heart
() автор топика
Ответ на: комментарий от true_admin

> для начала надо научиться работать с битовыми массивами на нижнем уровне


используй готовые библиотеки.


Лор такой лор. )))

LamerOk ★★★★★
()
Ответ на: комментарий от ice2heart

> где ошибки и как исправить

ошибка в самом подходе.

сериализацию данной структуры можно записать примерно так (учитывая то, что порядок байт в bmp-файле — little-endian):

#define SERIALIZE_WORD(val)     (uint8_t)(val), (uint8_t)((val) >> 8)
#define SERIALIZE_DWORD(val)    SERIALIZE_WORD(val), SERIALIZE_WORD((val) >> 16)

uint8_t buf[] = {
	SERIALIZE_WORD(bfh.bfType),
	SERIALIZE_DWORD(bfh.bfSize),
	SERIALIZE_WORD(bfh.bfReserved1),
	SERIALIZE_WORD(bfh.bfReserved2),
	SERIALIZE_DWORD(bfh.bfOffBits)
};
fwrite(buf, sizeof buf, 1, stream);
arsi ★★★★★
()
Ответ на: комментарий от arsi

uint8_t переменная которая иммет строго 8 бит размерность, но я не понял как работает дефайн... и что по этой теме можно почитать ?

ice2heart
() автор топика

а зачем писать свой велосипед, если можно взять готовую библиотеку для работы с изображениями и сконцентироваться на основной задаче?

lazyklimm ★★★★★
()
Ответ на: комментарий от lazyklimm

ну если у меня нехватает заний на начальные задачи, то скорей всего неполучится что то более сложное. велосипед в данном случае нужен ради обучения.

ice2heart
() автор топика
Ответ на: комментарий от ice2heart

тогда начни с ассемблера и своей операционки

lazyklimm ★★★★★
()
Ответ на: комментарий от LamerOk

а как ты думаешь, что будет на выходе у C-библитеки по работе с изображениями? Картинка на мониторе? :). Они в память декодируют в виде массива, дальше делай что хочешь.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

Спасибо, кэп.

1. Только ты не уточнил, что библиотеки именно для чтения ;)

2. Опу как раз для начала работы лучше научиться читать битовые массивы из файла - как раз самые простейшие преобразования, т.к. бмп и есть массив с заголовком. ;)

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

> Только ты не уточнил, что библиотеки именно для чтения ;)

тыщи их :) Первая ссылка в гугле: http://code.google.com/p/libbmp/
Там даже пример работы на главной.

Опу как раз для начала работы лучше научиться читать битовые массивы из файла


да лан, залезет в сырцы либы и посмотрит что к чему :)

true_admin ★★★★★
()

Выкинь старый, тухлый и ненужный Си.

Умные люди(не будем показывать пальцем) уже все продумали за тебя: http://github.com/Lovesan/virgil

C этой теплой ламповой библиотекой для CL ты сможешь писать так:

(define-struct (bmp-header
                 (:constructor make-bmp-header
                               (&key file-size offset))
                 (:packed t))
    "BMP file header"
  (magic     (string :encoding :ascii
                     :byte-length 2)
         :initform "BM")
  (file-size uint32)
  (reserved1 uint16)
  (reserved2 uint16)  
  (offset    uint32))

(define-external-function "fopen"
    (:cdecl :default)
  (pointer rv (if (&? rv)
                rv
                (error "fopen(3) error")))
  "fopen(3)"
  (path (& string))
  (mode (& string)))

(define-external-function "fclose"
    (:cdecl :default)  
  (int rv (or (zerop rv)
              (error "fclose(3) error")))
  "fclose(3)"
  (fd pointer))

(define-external-function "fwrite"
    (:cdecl :default)
  (size-t)
  "fwrite(3)"
  (data   pointer)
  (size   size-t :optional 1)
  (n      size-t)
  (stream pointer))

(defun write-header (header filename)
  (let ((fd (fopen (namestring filename) "w")))
    (unwind-protect
        (with-pointer ((p size) header 'bmp-header)
          (fwrite p size fd))
      (fclose fd))))

;;(defvar *header* (make-bmp-header :offset 123 :file-size 456))
;;
;;(write-header *header* "/xynta.bmp")
;;==> 14

Love5an
()
Ответ на: комментарий от Love5an

хм, действительно, просто и понятно, не то что на всяких перлах:

open my $fh, '>:raw' $filename   or die "open($filename): $!";
syswrite $fh, pack 'a2VvvV', 'BM', $filesize, $reserved1, $reserved2, $offset  or die "write($filename): $!";
close $fh  or die "close($filename): $!";

эх, за лисп взяться, что ли…

arsi ★★★★★
()
Ответ на: комментарий от true_admin

Ааа, так это он померяться пиписьками решил?

Смищно. Ну, для особо умных:

(defun write-int (int stream n)
  (dotimes (i n)
    (write-byte (ldb (byte 8 (* 8 i)) int)
                stream)))

(with-open-file (out filename :element-type '(unsigned-byte 8))
  (write-int #x4D42 out 2)
  (write-int *file-size* out 4)
  (write-int *reserved1* out 2)
  (write-int *reserved2* out 2)
  (write-int *offset* out 4))

Следующий подобный «умник», не способный даже прочитать декларативное описание сишных структур и функций и врубиться в суть, пусть лучше проходит мимо.

Love5an
()
Ответ на: комментарий от Love5an

Вообще, мой пример нацелен на то, чтобы показать, что с сишными данными(ну и функциями) в лиспе, с моей библиотекой, работать удобнее, чем в сях.

Внимание вопрос: насколько надо быть уебанным по голове, чтобы в ответ вот на это выкладывать какой-то левый и кривой ad-hoc(я что-то не вижу конкретной структуры там, и конкретных сишных функций) говнокод на получитаемом говне? Видимо, мне такую степень уебанности понять не дано, потому что на перле я писал довольно мало.

Love5an
()
Ответ на: комментарий от Love5an

Согласен, выглядит просто ужасно. То ли дело:

import struct

with open(file_path, 'wb') as fd:
    fd.write(struct.pack('<2sLHHL', 'BM', file_size, reserved_1, reserved_2, offset))
shylent
()
Ответ на: комментарий от Love5an

> Уже лучше, но все-равно не дотягивает до:

(write-packed-bmp-header file-size reserved1 reserved2 offset)

Да епт, вот смотри:

write_packed_bmp_header(hdr)

и всё :D

tailgunner ★★★★★
()
Ответ на: комментарий от arsi

ждём реализацию на brainfuck, asm или ещё чём-нить ещё более экзотическом :)

true_admin ★★★★★
()
Ответ на: комментарий от enep

да нормально всё, пока кто-нить не начинает возбухать «вы все козлы, лисп говно, ххх рулез»... Я уже привык.

true_admin ★★★★★
()
Ответ на: комментарий от enep

Не очень гоже посылать в стандарт, когда поставлен конкретный вопрос. Возьмут на улице тебя, посадят на 15 суток с объяснением «кури административный кодекс», будет так же весело.

kiverattes ★☆
()
Ответ на: комментарий от kiverattes

Так ведь нагуглить нужную библиотеку или просто кусок кода можно очень быстро. Я так минут за 15 получил все нужные процедуры для работы с bmp :)

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от kiverattes

> Не очень гоже посылать в стандарт, когда поставлен конкретный вопрос. Возьмут на улице тебя, посадят на 15 суток с объяснением «кури административный кодекс»

что за бредовое сравнение? если сравнивать программирование с юриспруденцией, то программист — как юрист (а не случайный прохожий). послать его курить стандарт кодекс — святое дело.

arsi ★★★★★
()
Ответ на: комментарий от arsi

что за бредовое сравнение?

А почему вы думаете, что ТС обязательно программист? Может, у него возникла необходимость обработать результаты какого-нибудь эксперимента? Он вполне и медиком может быть :)

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

> А почему вы думаете, что ТС обязательно программист?

желание ТСа работать со [служебными] данными на низком уровне наводит на такую мысль :)

arsi ★★★★★
()
Ответ на: комментарий от Eddy_Em

Даже если ТС и программист, то он сюда приходит не для того, наверное, чтобы мы его в стандарт или в гугл посылали. Он про эти два места и без нас знает.

kiverattes ★☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.