Форум программистов, компьютерный форум CyberForum.ru

Изменение размера bmp стандартными средствами c++ - C++

Восстановить пароль Регистрация
 
Vespertilio
0 / 0 / 0
Регистрация: 27.02.2011
Сообщений: 14
13.10.2013, 01:31     Изменение размера bmp стандартными средствами c++ #1
Доброго времени суток, форумчане. Интересует такой вопрос: есть изображение bmp с глубиной 24 бита. Требуется провести децимацию: вырезать чётные строки и столбцы и сохранить в новом файле.

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

Выдержки из кода:

C++
1
2
3
4
[RGBTRIPLE* dstRgb = (RGBTRIPLE*)calloc(1, area * sizeof(RGBTRIPLE) / (step * step)); 
// Здесь area - площадь исходной картинки, step - шаг "вырезания"
//(в данном примере пусть step = 2, то есть высота и ширина урезаются в два раза, соответственно
//площадь картинки таким образом уменьшается вчетверо)
Этим шагом выделяю массив под новую картинку. НО при использовании такого кода:
C++
1
2
3
4
5
6
7
8
9
10
 
for(int i = 0; i < bih.biHeight; i += step){ //bih - структура типа bitmapinfoheader
    for(int j = 0; j < bih.biWidth; j += step){
                //Здесь rgb - массив триплетов из исходной картинки
        dstRgb[(i * bih.biWidth + j)/2].rgbtBlue = rgb[i * bih.biWidth + j].rgbtBlue;//Нижеописанное исключение бросается на этой строчке
        dstRgb[(i * bih.biWidth + j)/2].rgbtRed = rgb[i * bih.biWidth + j].rgbtRed;
        dstRgb[(i * bih.biWidth + j)/2].rgbtGreen = rgb[i * bih.biWidth + j].rgbtGreen;     
    }
}
free(rgb);
при исполнении программы выдаёт вот такое исключение:
C++
1
Необработанное исключение в "0x013a1dec" в "MMTL1.exe": 0xC0000005: Нарушение прав доступа при записи "0x038dab40".
Если вместо вышеуказанного выделения памяти под новую картинку использовать вот такое:
C++
1
RGBTRIPLE* dstRgb = (RGBTRIPLE*)calloc(1, area * sizeof(RGBTRIPLE));
, то есть, без уменьшения площади, то, в принципе, программа работает - на выходе получается картинка, у которой в левой нижней четверти уменьшенное в четыре раза исходное изображение, остальные три четверти черны. При изменении свойств bih.biWidth и bih.biHeight напрямую картинка ведёт себя тоже не так, как задумывалось. Вопрос: почему может появляться такое исключение и как вести себя при решении подобных задач с изменением размера (как в большую, так и в меньшую стороны с использованием только стандартных средств C++)?

Вот весь код функции, если он будет необходим:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//src, dst - названия исходного и конечного файлов, step - шаг децимации,
//way - несущественная для данного вопроса переменная
void decimation(char* src, char* dst, int step, int way){
    FILE* imgFile = fopen(src, "rb");
    BITMAPFILEHEADER bfh;
    fread(&bfh, sizeof(bfh), 1, imgFile);
    
    BITMAPINFOHEADER bih;
    fread(&bih, sizeof(bih), 1, imgFile);
 
    int imgSize = bih.biSizeImage;
 
    int area = bih.biWidth * bih.biHeight;
 
    RGBTRIPLE* rgb = (RGBTRIPLE*)calloc(1, imgSize);
    fread(rgb, imgSize, 1, imgFile);
 
    fclose(imgFile);
    
    RGBTRIPLE* dstRgb = (RGBTRIPLE*)calloc(1, area * sizeof(RGBTRIPLE));//Проблемное место номер один
 
    if(way){
        for(int i = 0; i < bih.biHeight; i += step){
            for(int j = 0; j < bih.biWidth; j += step){
                dstRgb[(i * bih.biWidth + j)/2].rgbtBlue = rgb[i * bih.biWidth + j].rgbtBlue;//Исключение бросается на этой строчке
                dstRgb[(i * bih.biWidth + j)/2].rgbtRed = rgb[i * bih.biWidth + j].rgbtRed;
                dstRgb[(i * bih.biWidth + j)/2].rgbtGreen = rgb[i * bih.biWidth + j].rgbtGreen;     
            }
        }
        free(rgb);
    }
    writeBmp(dst, bfh, bih, dstRgb);//Функция записи в файл
    free(dstRgb);
}
Заранее спасибо
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.10.2013, 01:31     Изменение размера bmp стандартными средствами c++
Посмотрите здесь:

Изменение размера массива C++
C++ изменение размера изображения
C++ Как создать XML файл стандартными средствами
C++ Простейший текстовый редактор стандартными средствами c++
Считать посимвольно файл стандартными средствами и итераторами C++
C++ Изменение размера массива
Изменение размера массива C++
C++ Ввод без ожидания стандартными средствами

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
MrGluck
Ворчун
Эксперт С++
 Аватар для MrGluck
4920 / 2663 / 243
Регистрация: 29.11.2010
Сообщений: 7,405
13.10.2013, 01:39     Изменение размера bmp стандартными средствами c++ #2
Не знаю, с какой библиотекой вы работаете, но в OpenCV эта задача решилась бы на раз.

Добавлено через 43 секунды
P.S. в С++ нет стандартных средств для работы с изображениями
Vespertilio
0 / 0 / 0
Регистрация: 27.02.2011
Сообщений: 14
14.10.2013, 03:08  [ТС]     Изменение размера bmp стандартными средствами c++ #3
MrGluck, по OpenCV, чувствую, тоже появятся вопросы в скорейшем будущем

А пока MS VisualStudio 2010 без OpenCV.

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

Добавлено через 6 минут
Вот все включаемые файлы:
C++
1
2
3
4
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <Windows.h>
Добавлено через 1 час 16 минут
В одной ошибке разобрался сам. Ошибся при работе с памятью. Вместо
C++
1
dstRgb[(i * bih.biWidth + j) / 2]
надо было
C++
1
dstRgb[(i * bih.biWidth + j) / (step * step)]
для того, чтобы правильно урезать изображение (учесть изменения И по ширине, И по высоте, отсюда step * step).


Проблема теперь в другом: на выходе получается 4-хкилобайтный файл, при открытии говорится, что он повреждён. Посему новый вопрос: чтобы правильно записать новый RGB-массив, какие записи нужно ОБЯЗАТЕЛЬНО поменять в BITMAPINFOHEADER и BITMAPFILEHEADER, кроме biWidth и biHeight, и нужно ли что-нибудь менять вообще, или мыслю не в том направлении?

Добавлено через 23 часа 46 минут
Разобрался сам. Проблема опять была в неправильном обращении к памяти. При обращении к элементу массива в цикле вместо
C++
1
dstRgb[(i * bih.biWidth + j) / (step * step)]
правильней было использовать
C++
1
dstRgb[i * bih.biWidth / (step * step) + j / step]
, так как в первом случае он в левую половину картинки в каждый пиксель два раза записывал новое значение пикселя. Теперь строки и столбцы обрабатываются немного по-разному.

Мораль: весомая часть ошибок в решении многих задач с помощью C++ устраняется очень внимательной и скрупулёзной работой с динамической памятью.

P.S.: ещё надо было поменять в заголовках изображения атрибуты ширин, высот и размеров на новые. Вот так:
C++
1
2
3
4
bih.biHeight = bih.biHeight / step;
bih.biWidth = bih.biWidth / step;
bih.biSizeImage = bih.biSizeImage / (step * step);
bfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + area * sizeof(RGBTRIPLE) / (step * step);
Может, кому пригодится
Yandex
Объявления
14.10.2013, 03:08     Изменение размера bmp стандартными средствами c++
Ответ Создать тему
Опции темы

Текущее время: 08:15. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru