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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 13, средняя оценка - 4.69
iTD
0 / 0 / 0
Регистрация: 14.03.2012
Сообщений: 29
#1

Не могу найти ошибку в коде. BMP файл, поворот на 90 - C++

06.09.2012, 22:41. Просмотров 1874. Ответов 10
Метки нет (Все метки)

Здрасти !
Друзья, помогите найти ошибку: Задача /* Написать программу, формирующую по исходному BMP файлу новый BMP файл, повернутый на 90 градусов влево. */ Как устроены бмпшки разобрался. У меня 24 битовая картинка 480х320.

Сам код:

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
35
36
37
38
39
40
41
42
43
44
/* Написать программу, формирующую по исходному BMP файлу новый BMP файл,
    повернутый на 90 градусов влево. */
 
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <Windows.h>
 
void main ()
{
    FILE *f1, *f2;
    BITMAPFILEHEADER bmfh;
    BITMAPINFOHEADER bmih;
    RGBTRIPLE RGBColor;
    
    f1=fopen("1.bmp", "r+b");
    fread(&bmfh, sizeof(bmfh), 1, f1);
    fread(&bmih, sizeof(bmih), 1, f1);
    int h, w;
    w=bmih.biWidth;
    h=bmih.biHeight;
    
    f2=fopen("2.bmp", "w+b");
    bmih.biWidth=h;
    bmih.biHeight=w;
    fwrite(&bmfh, sizeof(bmfh), 1, f2);
    fwrite(&bmih, sizeof(bmih), 1, f2);
    
    int k=1, j=0;
    for(int i=0; i<bmih.biHeight*bmih.biWidth; i++)
    {
        fread(&RGBColor, sizeof(RGBColor),1, f1);
        // указываем позицию пикселя !!!
        fseek(f2, (k*bmih.biWidth-j)*sizeof(RGBColor), SEEK_SET);
        fwrite(&RGBColor, sizeof(RGBColor), 1, f2);
        if(k==bmih.biHeight)
        {
            k=0;
            j++;
        }
        k++;
    }
    fcloseall();
}
Собственно 1.bmp и 2.bmp входной и выходной файлы соответственно. Меняю местами высоту и ширину картинки и записываю во 2 файл BMPINFOHEADER & BMPFILEHEADER. Далее считываю содержимое битового образа и записываю во 2 файл (fseek указываю куда ставить каждый пиксель(надеюсь правильно выразился)).

Проблема в том, что после завершения программы 2ой файл (2.bmp) не открывается Хотя весит он столько же сколько и исходный 1.bmp.

Пожалуйста, тыкните меня носом, где я накосячил !
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.09.2012, 22:41
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Не могу найти ошибку в коде. BMP файл, поворот на 90 (C++):

Не могу найти ошибку в коде - C++
Не могу найти ошибку в коде. Помогите плиз. Нужно вычислить приближённое значение суммы этого бесконечного ряда. #include &lt;iostream&gt;...

Не могу найти ошибку в коде - C++
Работаю со связанным списком. нужно удалить из него указанный элемент. Вот код функции удаления: void List::Delete(int Number){ ...

Не могу найти ошибку в коде :( - C++
#include &lt;stdio.h&gt; #include &lt;math.h&gt; #include &lt;conio.h&gt; void main () { clrscr(); float eps=0.0001; float x,S,ocr; scanf...

Не могу найти ошибку в коде - C++
class genetic { typedef bool* chr; typedef vector&lt;chr&gt; vals; vals population; bool...

Не могу найти ошибку в коде - C++
Игра &quot;БлэкДжек&quot; Ошибка - &quot;Прекращена работ программы&quot;. С чем это связано - не могу понять... // Д/З 25 Блэк-Джек #include...

Не могу найти ошибку в коде - C++
Задание такое: в текстовом файле находятся данные про радиусы основ и высот 15 конусов. Нужно записать в другой файл таблицу, которая...

10
Герц
524 / 341 / 4
Регистрация: 05.11.2010
Сообщений: 1,077
Записей в блоге: 1
06.09.2012, 22:55 #2
1. Не уверен, что можно ставить указатель позиции в файле за пределы eof, а у тебя получается именно так.
2. Ты никак не учитываешь наличие выравнивания по границе 4 байт, правда при таких размерах картинки оно не имеет значения, но если ширина результирующего файла не делится без остатка на 4, то каждая строка в изображении дополняется до числа, кратного 4 байтам. При этом в заголовоке bmp файла меняется поле bitmapSize (или как-то так, оно определяется как ( width + width % 4) * height * bitsPerPixel / 8 ).
1
iTD
0 / 0 / 0
Регистрация: 14.03.2012
Сообщений: 29
06.09.2012, 23:07  [ТС] #3
Цитата Сообщение от Герц Посмотреть сообщение
Не уверен, что можно ставить указатель позиции в файле за пределы eof, а у тебя получается именно так.
ммм.. разве я выхожу за пределы конца файла ?
C++
1
fseek(f2, (k*bmih.biWidth-j)*sizeof(RGBColor), SEEK_SET);
Поправьте если ошибаюсь. sizeof(RGBColor) - это размер информации, которую несет в себе пиксель (т.е. домнажаю на sizeof(RGBColor) что бы двигаться по пикселям). (k*bmih.biWidth-j) - а это, если можно так назвать, "формула", по которой и происходит заполнение(переворот на 90 градусов в лева) 2.bmp . k принимает значение от 1 до 480 (bmih.biHeight), j - от 0 до 320 (bmih.biWidth). Правильно же ?

Добавлено через 3 минуты
Еще размер 1.bmp 460*854 байт
2.bmp 460*803 байт
0
Герц
524 / 341 / 4
Регистрация: 05.11.2010
Сообщений: 1,077
Записей в блоге: 1
06.09.2012, 23:10 #4
Ты двигаешься по исходному файлу вполне прямолинейно, по строкам слева направо снизу вверх.
При повороте левый нижний пиксель картинки оказывается верхним левым, а это уже где-то ближе к концу файла.
На этот момент в файл записано только сколько-то там байт (меньше 100) заголовка BMP, а ты пытаешься сделать seek на позицию "размер заголовка + 462240", когда файл у тебя имеет "размер заголовка", так что да, ты выходишь за пределы конца файла.

Добавлено через 59 секунд
Могу написать поворачивалку своими средствами, если хочешь. Посмотришь.
1
iTD
0 / 0 / 0
Регистрация: 14.03.2012
Сообщений: 29
06.09.2012, 23:18  [ТС] #5
Цитата Сообщение от Герц Посмотреть сообщение
Ты двигаешься по исходному файлу вполне прямолинейно, по строкам слева направо снизу вверх.
При повороте левый нижний пиксель картинки оказывается верхним левым, а это уже где-то ближе к концу файла.
На этот момент в файл записано только сколько-то там байт (меньше 100) заголовка BMP, а ты пытаешься сделать seek на позицию "размер заголовка + 462240", когда файл у тебя имеет "размер заголовка", так что да, ты выходишь за пределы конца файла.

Добавлено через 59 секунд
Могу написать поворачивалку своими средствами, если хочешь. Посмотришь.
Было бы здорово, если не затруднит, напиши пожалуйста Можно только сам алгоритм переворота.

Хмм... а разве левый нижний пиксель из исходного файла не становится правым нижним в 2.bmp ? т.е. нижня строка в 1.bmp считывается в правый столбик 2.bmp (с низу в верх) .
0
Герц
524 / 341 / 4
Регистрация: 05.11.2010
Сообщений: 1,077
Записей в блоге: 1
07.09.2012, 00:18 #6
Я имел в виду вращение по часовой стрелке.

Добавлено через 29 минут
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <fstream>
#include <string.h> //  memcpy
 
namespace Bitmap
{
#   pragma pack( push, 1 )
    struct Header
    {
        unsigned short bitmap;
        unsigned int fileSizeLow;
        unsigned int fileSizeHigh;
        unsigned int headerSize;
        unsigned int unknown2;
        unsigned int width;
        unsigned int height;
        unsigned short unknown3;
        unsigned short depth;
        unsigned int unknown4;
        unsigned int bitmapSize;
        unsigned int unknown5;
        unsigned int unknown6;
        unsigned int unknown7;
        unsigned int unknown8;
    };
#   pragma pack( pop )
}
 
bool rotateImage90ClockWise( std::string inFileName, std::string outFileName );
 
bool rotateImage90ClockWise( std::string inFileName, std::string outFileName )
{
    std::ifstream in( inFileName.c_str(), std::ios::in | std::ios::binary );
    if ( not in.is_open() ) {
        return false;
    }
    Bitmap::Header hdrIn;
    //  Читаем заголовок из входного файла
    in.read( reinterpret_cast< char* >( &hdrIn ), sizeof( Bitmap::Header ) );
 
    //  Работаем только с RGB_888 файлами
    if ( hdrIn.depth != 24 ) {
        in.close();
        return false;
    }
 
    //  Копируем заголовок входного файла в заголовок выходного файла
    Bitmap::Header hdrOut;
    memcpy( &hdrOut, &hdrIn, sizeof( Bitmap::Header ) );
    //  Переворачиваем картинку
    hdrOut.width = hdrIn.height;
    hdrOut.height = hdrIn.width;
    //  Вычисляем новую длину строки с учетом выравнивания
    unsigned rowLength = hdrOut.width * hdrOut.depth / 8 + hdrOut.width % 4;
    //  Вычисляем новый размер изображения
    hdrOut.bitmapSize = rowLength * hdrOut.height;
    //  Устанавливаем новый размер файла
    hdrOut.fileSizeLow = hdrOut.bitmapSize + hdrOut.headerSize;
 
    //  Создаем массив для хранения преобразованного изображения
    char* dataOut = new char[ hdrOut.bitmapSize ];
    //  А сюда будем читать каждый пиксель из входного файла
    char color[3];
 
    for ( unsigned i = 0; i < hdrIn.height; ++i ) {
        for ( unsigned j = 0; j < hdrIn.width; ++j ) {
            //  Читаем пиксель
            in.read( color, sizeof( color ) );
            //  Копируем по нужному адресу в выходное изображение
            memcpy( &dataOut[ ( hdrOut.height - j - 1 ) * rowLength + i * 3 ],
                color, sizeof( color ) );
        }
        //  Пропускаем лишние байты
        if ( int overHead = hdrIn.width % 4 ) {
            in.seekg( overHead, std::ios::cur );
        }
    }
 
    std::ofstream out( outFileName.c_str(), std::ios::out | std::ios::binary );
    if ( not out.is_open() ) {
        in.close();
        return false;
    }
 
    out.write( reinterpret_cast< char* >( &hdrOut ), sizeof( Bitmap::Header ) );
    out.write( dataOut, hdrOut.bitmapSize );
    out.close();
    in.close();
 
    return true;
}
1
ValeryS
Модератор
6679 / 5088 / 475
Регистрация: 14.02.2011
Сообщений: 17,070
07.09.2012, 00:22 #7
iTD, а не проще тебе будет
считать первый файл
создать структуру заголовков, создать массив
и потом из памяти записать второй ????
а в памяти крути как хочешь
1
iTD
0 / 0 / 0
Регистрация: 14.03.2012
Сообщений: 29
07.09.2012, 16:29  [ТС] #8
Цитата Сообщение от ValeryS Посмотреть сообщение
iTD, а не проще тебе будет
считать первый файл
создать структуру заголовков, создать массив
и потом из памяти записать второй ????
а в памяти крути как хочешь
Попробую сегодня считать пиксели в массив структур (RGB) и оттуда вытаскивать те, который требуются (т.е. что бы заполнение шло во 2 файле стандартно снизу в верх построчно )
Если я Вас правильно понял
0
Герц
524 / 341 / 4
Регистрация: 05.11.2010
Сообщений: 1,077
Записей в блоге: 1
07.09.2012, 16:40 #9
Я же тебе рабочий код написал
1
iTD
0 / 0 / 0
Регистрация: 14.03.2012
Сообщений: 29
07.09.2012, 18:12  [ТС] #10
Я же тебе рабочий код написал
Спасибо большое Я им воспользуюсь, но должен и я же что то написать

Добавлено через 7 минут
C++
1
2
3
4
5
6
//  Вычисляем новую длину строки с учетом выравнивания
    unsigned rowLength = hdrOut.width * hdrOut.depth / 8 + hdrOut.width % 4;
    //  Вычисляем новый размер изображения
    hdrOut.bitmapSize = rowLength * hdrOut.height;
    //  Устанавливаем новый размер файла
    hdrOut.fileSizeLow = hdrOut.bitmapSize + hdrOut.headerSize;
Вот только немного понять не могу, разве в моем случае нужно считать новую длину строки ?
Или это на случай, если исходная картинка будет иметь разрешение не кратное 4 ?

Добавлено через 1 час 11 минут
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/* Написать программу, формирующую по исходному BMP файлу новый BMP файл,
    повернутый на 90 градусов влево. */
 
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <Windows.h>
 
struct RGB
{
    BYTE    rgbtBlue;
    BYTE    rgbtGreen;
    BYTE    rgbtRed;
} p[320*480];
 
void main ()
{
    FILE *f1, *f2;
    BITMAPFILEHEADER bmfh;
    BITMAPINFOHEADER bmih;
    RGBTRIPLE RGBColor;
    
    f1=fopen("1.bmp", "r+b");
    fread(&bmfh, sizeof(bmfh), 1, f1);
    fread(&bmih, sizeof(bmih), 1, f1);
    int h, w;
    w=bmih.biWidth;
    h=bmih.biHeight;
    
    f2=fopen("2.bmp", "w+b");
    bmih.biWidth=h;
    bmih.biHeight=w;
    fwrite(&bmfh, sizeof(bmfh), 1, f2);
    fwrite(&bmih, sizeof(bmih), 1, f2);
    
    int k=0, j=w;
    for(int i=0; i<bmih.biHeight*bmih.biWidth; i++)
    {
        fread(&RGBColor, sizeof(RGBColor),1, f1);
        p[i].rgbtBlue=RGBColor.rgbtBlue;
        p[i].rgbtGreen=RGBColor.rgbtGreen;
        p[i].rgbtRed=RGBColor.rgbtRed;
    }
 
    for(int i=0; i<bmih.biHeight*bmih.biWidth; i++)
    {
        if(i!=0 && i%h==0)
        {
            k=0;
            j--;
        }
 
        fwrite(&p[(h*w)-(k*w)-j], sizeof(RGB), 1, f2);
        k++;
    }
    fcloseall();
}
Вот, получилось перевернуть Но пробывал только на одной бмпшке. Осталось доработать код и готово !
0
Ольга27
1 / 1 / 0
Регистрация: 18.10.2012
Сообщений: 36
08.09.2013, 19:58 #11
Цитата Сообщение от iTD Посмотреть сообщение
Спасибо большое Я им воспользуюсь, но должен и я же что то написать

Добавлено через 7 минут
C++
1
2
3
4
5
6
//  Вычисляем новую длину строки с учетом выравнивания
    unsigned rowLength = hdrOut.width * hdrOut.depth / 8 + hdrOut.width % 4;
    //  Вычисляем новый размер изображения
    hdrOut.bitmapSize = rowLength * hdrOut.height;
    //  Устанавливаем новый размер файла
    hdrOut.fileSizeLow = hdrOut.bitmapSize + hdrOut.headerSize;
Вот только немного понять не могу, разве в моем случае нужно считать новую длину строки ?
Или это на случай, если исходная картинка будет иметь разрешение не кратное 4 ?

Добавлено через 1 час 11 минут
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/* Написать программу, формирующую по исходному BMP файлу новый BMP файл,
    повернутый на 90 градусов влево. */
 
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <Windows.h>
 
struct RGB
{
    BYTE    rgbtBlue;
    BYTE    rgbtGreen;
    BYTE    rgbtRed;
} p[320*480];
 
void main ()
{
    FILE *f1, *f2;
    BITMAPFILEHEADER bmfh;
    BITMAPINFOHEADER bmih;
    RGBTRIPLE RGBColor;
    
    f1=fopen("1.bmp", "r+b");
    fread(&bmfh, sizeof(bmfh), 1, f1);
    fread(&bmih, sizeof(bmih), 1, f1);
    int h, w;
    w=bmih.biWidth;
    h=bmih.biHeight;
    
    f2=fopen("2.bmp", "w+b");
    bmih.biWidth=h;
    bmih.biHeight=w;
    fwrite(&bmfh, sizeof(bmfh), 1, f2);
    fwrite(&bmih, sizeof(bmih), 1, f2);
    
    int k=0, j=w;
    for(int i=0; i<bmih.biHeight*bmih.biWidth; i++)
    {
        fread(&RGBColor, sizeof(RGBColor),1, f1);
        p[i].rgbtBlue=RGBColor.rgbtBlue;
        p[i].rgbtGreen=RGBColor.rgbtGreen;
        p[i].rgbtRed=RGBColor.rgbtRed;
    }
 
    for(int i=0; i<bmih.biHeight*bmih.biWidth; i++)
    {
        if(i!=0 && i%h==0)
        {
            k=0;
            j--;
        }
 
        fwrite(&p[(h*w)-(k*w)-j], sizeof(RGB), 1, f2);
        k++;
    }
    fcloseall();
}
Вот, получилось перевернуть Но пробывал только на одной бмпшке. Осталось доработать код и готово !
я сейчас тоже с бмпшками пытаюсь разобраться,не могли бы вы мне пояснить вашу программу,много не понятного,а задание интересно)
0
08.09.2013, 19:58
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.09.2013, 19:58
Привет! Вот еще темы с ответами:

Не могу найти ошибку в коде - C++
Здравствуйте еще раз! У меня возникла проблема: В написанном мною коде какая то ошибка, которую ни я, ни компилятор, не может выявить. ...

Не могу найти ошибку в коде - C++
Помогите пожалуйста найти ошибку в коде: #include &lt;fstream&gt; #include &lt;iostream&gt; using namespace std; const int n = 8; ...

Не могу найти ошибку в коде - C++
Привет всем. У меня не получается построить решение. Вот код. #include &lt;conio.h&gt; #include &lt;iostream&gt; #include &lt;clocale&gt; using...

Не могу найти ошибку в коде - C++
Доброго времени суток. Не могу найти ошибку в коде. Задача: Периодическая функция F(x) определена на всей числовой прямой и имеет период...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru