| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Для новичков > Bitmap и TFileStream |
| Автор: Proxin 26.12.2009, 20:25 |
| В общем, как? Известна высота изображения и ширина. Рылся в сети - ничего не нашёл. |
| Автор: artsb 26.12.2009, 20:35 | ||
? |
| Автор: Proxin 26.12.2009, 20:44 |
| Гениально, да. Но не то. У меня есть файлстрим, в который напихана ещё куча информации. С определённой позиции начианается рисунок. Конец рисунка - не конец файла. Я знаю размеры рисунка (высота и ширина). Куда мне его можно считать и как вывести потом на bitmap? |
| Автор: artsb 26.12.2009, 20:47 | ||
Как вы задали вопрос, так я и ответил Устанавливаете позицию курсора в потоке на нужную позицию и ...
Всё будет ОК ;) Добавлено @ 20:48 Ну и что? LoadFromStream знает когда остановиться. |
| Автор: Alexeis 26.12.2009, 20:56 |
Можно создать промежуточный TMemoryStream и в него сливать картинку. Добавлено через 1 минуту и 51 секунду К сожалению нет. TBitmap тупо читает до конца файла. В связи с этим иногда бывают проблемы, в частности с битмапами 64х64, 256х256 (текстуры) |
| Автор: artsb 26.12.2009, 21:00 |
Странно. Я много раз так делал. До сих пор никаких проблем не было... Добавлено через 2 минуты и 14 секунд Тогда можно при сохранении, сначала сохранить изображение в промежуточный поток, потом в основной поток записать размер потока с картинкой и саму картинку. А при чтении читаем размер картинки, а потом во временный поток саму картинку и уже из него в битмап. |
| Автор: Proxin 26.12.2009, 22:01 | ||
Вот так должно быть?
|
| Автор: artsb 26.12.2009, 22:12 | ||||
Напишу на С++
Добавлено @ 22:16 А. Ну да. Только установка ширины и высоты излишни. И читайте кусок потока через метод CopyFrom. А перед этой строкой:
Обязательно позицию курсора в ноль нужно поставить. Иначе ничего не выйдет |
| Автор: Alexeis 26.12.2009, 22:29 |
| Вот это вызывает сомнение filestr.read(memorystr,bytescount); Думаю тут должен быть CopyFrom |
| Автор: artsb 26.12.2009, 22:39 |
Упс. Вы правы. А я почему-то везде написал просто Copy. Добавлено через 2 минуты и 18 секунд мне кажется, что это вообще работать не должно. |
| Автор: Proxin 26.12.2009, 22:52 |
| сделал с помощью copyfrom. появляется ошибка "bitmap image is not valid" - это значит, что я его не оттуда копирую? |
| Автор: artsb 26.12.2009, 22:54 |
Возможно... А в поток вы как сохраняли? SaveToStream? |
| Автор: Proxin 26.12.2009, 23:12 |
| Это вообще не мой файл - пытаюсь делать парсилку по открытому формату. Описание дано так: screenshotdata=3*width*height. Width и height я получаю правильно, смотрел с помощью другой парсилки. А вот сам битмап получить по этой технологии уже как-то не получается. Ещё заметил, что начало файла как-то странно читается - если даже сиком позицию после открытия установить в ноль, то символы читаются начиная со второго только. |
| Автор: artsb 26.12.2009, 23:20 |
| Ещё бы знать, как они сохраняют картинку... А вы уверены, что там битмап? Может там JPEG? Не понял. Где разворачиваются события? Добавлено через 7 минут и 1 секунду Побольше бы информации... |
| Автор: Proxin 26.12.2009, 23:30 |
| rgb - три бита на пиксель без компрессии есть битмап самый натуральный. или я не прав? ещё, если это поможет - вот описание структуры файла. конкретно интересует поле screenshot. может, я что-то неправильно понял (ширину и высоту получаю нормально) ? |
| Автор: Proxin 26.12.2009, 23:57 | ||
| Да, до скриншота всё нормально. А так и читаю:
|
| Автор: Proxin 27.12.2009, 00:15 |
| А как эти биты считать именно в массив? Они считываются в int64 только. |
| Автор: Alexeis 27.12.2009, 00:22 |
| 3*w*h этого мало. Нужно еще sizeof(BITMAPINFOHEADER), sizeof(BITMAPFILEHEADER) и кроме того учесть 2 выравнивания. 1е выравнивание каждой строки на границу 4х байт + выравнивание всего растра на границу 4х байт. Подробнее можно тут почитать http://forum.vingrad.ru/topic-94227.html |
| Автор: artsb 27.12.2009, 00:53 |
| Proxin, пришли мне на мыло файлик или выложи и пришли ссылку в личку. Завтра в обед приду, покумекаю. |
| Автор: artsb 27.12.2009, 13:44 | ||
Получилось:![]()
|
| Автор: Proxin 27.12.2009, 14:41 |
| И ничего... не силён я в переводе с си на паскаль. Вот как делаю: Картинка получается абсолютно чёрной. |
| Автор: artsb 27.12.2009, 14:54 |
| Мне кажется, вы неправильно длину массива bta устанавливаете... Как в Делфи создать динамический массив? |
| Автор: Proxin 27.12.2009, 15:10 |
| объявляется переменная array of что-то. затем с помощью setlength ей задаётся длина. |
| Автор: artsb 27.12.2009, 15:12 | ||
Proxin, вы действительно неверно создаёте массив. Написал так:
и всё заработало. Только индексы в циклах начинаются с 1. Добавлено @ 15:12 setlength это для строк. Добавлено @ 15:14 ![]() |
| Автор: Proxin 27.12.2009, 15:25 |
| Спасибо Вам большое за помощь. Всё работает. |
| Автор: artsb 27.12.2009, 15:33 |
| Но, конечно же, нужно всё реализовать так, чтобы массив создавался динамически. |
| Автор: Proxin 27.12.2009, 15:51 |
| а как установить его длину тогда правильно? во всех мануалах пишут setlength. |
| Автор: artsb 27.12.2009, 16:03 |
Я знаю как на С++. По крайней мере, в хелпе эта функция относится к строкам. А может вы просто bta не правильно объявили? |
| Автор: artsb 27.12.2009, 16:20 | ||
Написал так:
i равно 0. |
| Автор: bems 27.12.2009, 17:44 | ||
| Эта функция работает и для динамических массивов. Это известно всем, кто прочитал хоть один учебник по языку. 1) проверить что w и h больше нуля 2) проверить значение i не встроенным отладчиком а например так
|
| Автор: artsb 27.12.2009, 17:57 | ||||
Я не читал 100% больше нуля Добавлено @ 18:01
Сейчас проверил. Всё ОК. Массив заполнен нулями. Поэтому картинка чёрная. Значит не происходит чтения из потока. Не верно передаём указатель? Добавлено @ 18:11 Ха. Вот так работает:
Странно у вас всё в Делфи |
| Автор: bems 27.12.2009, 18:20 |
| Да нормально всё у нас. Для динамического массива bta и bta[0] это разные вещи, потому что bta это ссылка на первый элемент |
| Автор: artsb 27.12.2009, 18:36 |
не сомневаюсь ;) в С++ это указатель на массив. |
| Автор: bems 27.12.2009, 18:48 | ||
| Ну я назвал ссылкой условно. Физически это указатель на первый элемент, но синтаксически к элементам обращаются без ^ Ну по ходу получается то же самое. А первый параметр read это var-параметр, он и так передается по ссылке. Таким образом когда ты вызываешь f.read(bta, 3*w*h) в метод передается адрес адреса первого элемента. А для статического массива работало, потому что у него переменная-массив лежит по тому же адресу что и первый элемент. Форма f.read(bta[0], 3*w*h) будет работать в обоих случаях (для статического массива еще есть условие что он должен начинаться с нуля) А вот так совсем универсально
|
| Автор: artsb 27.12.2009, 18:56 | ||
Спасибо за разъяснение. В принципе, в С++ то же самое. Только в функцию Read передаётся именно указатель на буфер. |
| Автор: Proxin 27.12.2009, 19:09 | ||||
| Переделал всё с динамическим массивом. Работает так, как описал artsb. И ещё вопрос. Почему a string perfixed with a byte length не читается полностью? Пишу так:
Строка читается, но без первой буквы. UPD: А вот так
Читаются все строки нормально, но без последенй буквы. В чём может быть дело? Вообще, есть ли хороший материал по потокам - где детально всё на примерах расписано? |
| Автор: artsb 27.12.2009, 21:25 |
| Proxin, проверил под BCB 6. Всё отлично работает без Seek (с ним наоборот мусор). Значит это уже нюансы языка (Object Pascal). Здесь я, к сожалению, помочь не могу. ЗЫ обожаю С++ |
| Автор: bems 27.12.2009, 21:37 | ||
Попробуй так
Добавлено через 12 минут и 31 секунду Это неверно, потому что есть еще ноль в конце |
| Автор: bems 27.12.2009, 21:53 | ||||
| Тебе нужно посмотреть на файл в хексредакторе и определить включается ли терминатор в байт длины. Если нет, то так
А если да, то
|
| Автор: Proxin 28.12.2009, 08:02 |
| Спасибо. Понял. |