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

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

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 13, средняя оценка - 4.69
iTD
 Аватар для iTD
0 / 0 / 0
Регистрация: 14.03.2012
Сообщений: 29
06.09.2012, 22:41     Не могу найти ошибку в коде. BMP файл, поворот на 90 #1
Здрасти !
Друзья, помогите найти ошибку: Задача /* Написать программу, формирующую по исходному 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.

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

Не могу найти ошибку в коде C++
Не могу найти ошибку в коде C++
C++ Не могу найти ошибку в коде :(
C++ Не могу найти ошибку в коде
C++ Не могу найти ошибку в коде
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Герц
523 / 340 / 4
Регистрация: 05.11.2010
Сообщений: 1,077
Записей в блоге: 1
06.09.2012, 22:55     Не могу найти ошибку в коде. BMP файл, поворот на 90 #2
1. Не уверен, что можно ставить указатель позиции в файле за пределы eof, а у тебя получается именно так.
2. Ты никак не учитываешь наличие выравнивания по границе 4 байт, правда при таких размерах картинки оно не имеет значения, но если ширина результирующего файла не делится без остатка на 4, то каждая строка в изображении дополняется до числа, кратного 4 байтам. При этом в заголовоке bmp файла меняется поле bitmapSize (или как-то так, оно определяется как ( width + width % 4) * height * bitsPerPixel / 8 ).
iTD
 Аватар для iTD
0 / 0 / 0
Регистрация: 14.03.2012
Сообщений: 29
06.09.2012, 23:07  [ТС]     Не могу найти ошибку в коде. BMP файл, поворот на 90 #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 байт
Герц
523 / 340 / 4
Регистрация: 05.11.2010
Сообщений: 1,077
Записей в блоге: 1
06.09.2012, 23:10     Не могу найти ошибку в коде. BMP файл, поворот на 90 #4
Ты двигаешься по исходному файлу вполне прямолинейно, по строкам слева направо снизу вверх.
При повороте левый нижний пиксель картинки оказывается верхним левым, а это уже где-то ближе к концу файла.
На этот момент в файл записано только сколько-то там байт (меньше 100) заголовка BMP, а ты пытаешься сделать seek на позицию "размер заголовка + 462240", когда файл у тебя имеет "размер заголовка", так что да, ты выходишь за пределы конца файла.

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

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

Хмм... а разве левый нижний пиксель из исходного файла не становится правым нижним в 2.bmp ? т.е. нижня строка в 1.bmp считывается в правый столбик 2.bmp (с низу в верх) .
Герц
523 / 340 / 4
Регистрация: 05.11.2010
Сообщений: 1,077
Записей в блоге: 1
07.09.2012, 00:18     Не могу найти ошибку в коде. BMP файл, поворот на 90 #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;
}
ValeryS
Модератор
6375 / 4841 / 443
Регистрация: 14.02.2011
Сообщений: 16,043
07.09.2012, 00:22     Не могу найти ошибку в коде. BMP файл, поворот на 90 #7
iTD, а не проще тебе будет
считать первый файл
создать структуру заголовков, создать массив
и потом из памяти записать второй ????
а в памяти крути как хочешь
iTD
 Аватар для iTD
0 / 0 / 0
Регистрация: 14.03.2012
Сообщений: 29
07.09.2012, 16:29  [ТС]     Не могу найти ошибку в коде. BMP файл, поворот на 90 #8
Цитата Сообщение от ValeryS Посмотреть сообщение
iTD, а не проще тебе будет
считать первый файл
создать структуру заголовков, создать массив
и потом из памяти записать второй ????
а в памяти крути как хочешь
Попробую сегодня считать пиксели в массив структур (RGB) и оттуда вытаскивать те, который требуются (т.е. что бы заполнение шло во 2 файле стандартно снизу в верх построчно )
Если я Вас правильно понял
Герц
523 / 340 / 4
Регистрация: 05.11.2010
Сообщений: 1,077
Записей в блоге: 1
07.09.2012, 16:40     Не могу найти ошибку в коде. BMP файл, поворот на 90 #9
Я же тебе рабочий код написал
iTD
 Аватар для iTD
0 / 0 / 0
Регистрация: 14.03.2012
Сообщений: 29
07.09.2012, 18:12  [ТС]     Не могу найти ошибку в коде. BMP файл, поворот на 90 #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();
}
Вот, получилось перевернуть Но пробывал только на одной бмпшке. Осталось доработать код и готово !
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.09.2013, 19:58     Не могу найти ошибку в коде. BMP файл, поворот на 90
Еще ссылки по теме:

C++ Не могу найти ошибку в коде
Не могу найти ошибку в коде C++
C++ Не могу найти ошибку в коде

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

Или воспользуйтесь поиском по форуму:
Ольга27
1 / 1 / 0
Регистрация: 18.10.2012
Сообщений: 36
08.09.2013, 19:58     Не могу найти ошибку в коде. BMP файл, поворот на 90 #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();
}
Вот, получилось перевернуть Но пробывал только на одной бмпшке. Осталось доработать код и готово !
я сейчас тоже с бмпшками пытаюсь разобраться,не могли бы вы мне пояснить вашу программу,много не понятного,а задание интересно)
Yandex
Объявления
08.09.2013, 19:58     Не могу найти ошибку в коде. BMP файл, поворот на 90
Ответ Создать тему
Опции темы

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