Форум программистов, компьютерный форум, киберфорум
Программирование графики
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/3: Рейтинг темы: голосов - 3, средняя оценка - 5.00
8 / 8 / 4
Регистрация: 08.12.2022
Сообщений: 157

Формат .tiff

19.09.2024, 12:11. Показов 1035. Ответов 6
Метки c++ (Все метки)

Студворк — интернет-сервис помощи студентам
Пытаюсь сделать версию без сжатия для формата .tiff . При конвертации из .bmp получаю черно-белое изображение, а при обратной конвертации получаю исходное изображение. В чем может быть проблема?

сам класс для работы с .tiff
Кликните здесь для просмотра всего текста

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include "tiff_image.h"
 
namespace img_lib
{
    namespace tiff_image
    {
        Image TiffImage::LoadImageTiff(const Path& path_)
        {
            std::ifstream file(path_, std::ios::binary);
            if (!file)
            {
                throw std::runtime_error("Failed to open TIFF file: "s + path_.string());
            }
 
            TiffHeader header;
 
            file.read(reinterpret_cast<char*>(&header), sizeof(TiffHeader));
            if (!file || header.byteOrder != 0x4949 || header.magic != 42)
            {
                throw std::runtime_error("Invalid TIFF file: "s + path_.string());
            }
 
            std::vector<IFDEntry> ifdEntries;
            file.seekg(header.ifdOffset, std::ios::beg);
 
            uint16_t entryCount;
            file.read(reinterpret_cast<char*>(&entryCount), sizeof(entryCount));
            if (!file)
            {
                return {};
            }
 
            ifdEntries.resize(entryCount);
            file.read(reinterpret_cast<char*>(ifdEntries.data()), entryCount * sizeof(IFDEntry));
            if (!file)
            {
                return {};
            }
 
            uint32_t width = 0;
            uint32_t height = 0;
            uint32_t bitsPerSample = 0;
            uint32_t samplesPerPixel = 0;
            uint32_t rowsPerStrip = 0;
            uint32_t stripOffsets = 0;
            uint32_t stripByteCounts = 0;
 
            for (const auto& entry : ifdEntries)
            {
                switch (entry.tag)
                {
                case 0x0100:
                    width = entry.valueOffset;
                    break;
 
                case 0x0101:
                    height = entry.valueOffset;
                    break;
 
                case 0x0102:
                    bitsPerSample = entry.valueOffset;
                    break;
 
                case 0x0115:
                    samplesPerPixel = entry.valueOffset;
                    break;
 
                case 0x0116:
                    rowsPerStrip = entry.valueOffset;
                    break;
 
                case 0x0111:
                    stripOffsets = entry.valueOffset;
                    break;
 
                case 0x0117:
                    stripByteCounts = entry.valueOffset;
                    break;
                }
            }
 
            if (bitsPerSample != 8 || samplesPerPixel != 4)
            {
                throw std::runtime_error("Unsupported TIFF format"s);
            }
 
            Image image(width, height, Color::Black());
 
            file.seekg(stripOffsets, std::ios::beg);
            std::vector<std::byte> buffer(width * height * samplesPerPixel);
 
            file.read(reinterpret_cast<char*>(buffer.data()), buffer.size());
            if (!file)
            {
                return {};
            }
 
            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                {
                    int index = (y * width + x) * samplesPerPixel;
                    image.GetPixel(x, y) = { buffer[index], buffer[index + 1], buffer[index + 2], buffer[index + 3] };
                }
            }
            return image;
        }
 
        bool TiffImage::SaveImageTiff(const Path& path_, const Image& image_)
        {
            std::ofstream file(path_, std::ios::binary);
            if (!file)
            {
                throw std::runtime_error("Failed to create TIFF file: "s + path_.string());
            }
 
            uint32_t ifdOffset = sizeof(TiffHeader);
            TiffHeader header = { 0x4949, 42, ifdOffset };
 
            file.write(reinterpret_cast<char*>(&header), sizeof(header));
            if (!file)
            {
                return false;
            }
 
            uint16_t entryCount = 8;
 
            file.write(reinterpret_cast<char*>(&entryCount), sizeof(entryCount));
            if (!file)
            {
                return false;
            }
 
            uint32_t width = image_.GetWidth();
            uint32_t height = image_.GetHeight();
            uint32_t bitsPerSample = 8;
            uint32_t samplesPerPixel = 4;
            uint32_t rowsPerStrip = height;
            uint32_t stripOffsets = sizeof(TiffHeader) + sizeof(entryCount) + entryCount * sizeof(IFDEntry) + sizeof(uint32_t);
            uint32_t stripByteCounts = width * height * sizeof(Color);
 
            IFDEntry entries[] =
            {
                {0x0100, 3, 1, width},
                {0x0101, 3, 1, height},
                {0x0102, 3, 1, bitsPerSample},
                {0x0115, 3, 1, samplesPerPixel},
                {0x0116, 3, 1, rowsPerStrip},
                {0x0111, 4, 1, stripOffsets},
                {0x0117, 4, 1, stripByteCounts},
                {0x0118, 3, 1, 1}
            };
 
            file.write(reinterpret_cast<char*>(entries), sizeof(entries));
            if (!file)
            {
                return false;
            }
 
            uint32_t nextIFDOffset = 0;
 
            file.write(reinterpret_cast<char*>(&nextIFDOffset), sizeof(nextIFDOffset));
            if (!file)
            {
                return false;
            }
 
            for (int y = 0; y < image_.GetHeight(); ++y)
            {
                for (int x = 0; x < image_.GetWidth(); ++x)
                {
                    const Color& color = image_.GetPixel(x, y);
 
                    file.write(reinterpret_cast<const char*>(&color.r), sizeof(color.r));
                    file.write(reinterpret_cast<const char*>(&color.g), sizeof(color.g));
                    file.write(reinterpret_cast<const char*>(&color.b), sizeof(color.b));
                    file.write(reinterpret_cast<const char*>(&color.a), sizeof(color.a));
                }
            }
            return true;
        }
 
    } // end namespace tiff_image
 
} // end namespace img_lib


Основной класс для описания изображения
Кликните здесь для просмотра всего текста

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
#pragma once
 
#include <array>
#include <cassert>
#include <cstddef>
#include <vector>
#include <string>
#include <stdexcept>
#include <filesystem>
#include <fstream>
 
namespace img_lib
{
    using namespace std::string_literals;
    using Path = std::filesystem::path;
 
    struct Size
    {
        int width = 0;
        int height = 0;
    };
 
    struct Color
    {
        static Color Black()
        {
            return { std::byte{0}, std::byte{0}, std::byte{0}, std::byte{255} };
        }
 
        std::byte r;
        std::byte g;
        std::byte b;
        std::byte a;
    };
 
    class Image
    {
    public:
 
        Image() = default;
        Image(int w_, int h_, Color fill_);
 
        Image(const Image& other_);
        Image& operator=(const Image& other_);
 
        Image(Image&& other_) noexcept;
        Image& operator=(Image&& other_) noexcept;
 
        explicit operator bool() const
        {
            return GetWidth() > 0 && GetHeight() > 0;
        }
        bool operator!() const
        {
            return !operator bool();
        }
 
        const Color& GetPixel(int x_, int y_) const;
        Color& GetPixel(int x_, int y_);
 
        Color* GetLine(int y_);
        const Color* GetLine(int y_) const;
 
        int GetWidth() const;
        int GetHeight() const;
 
        int GetStep() const;
 
    private:
 
        int width = 0;
        int height = 0;
        int step = 0;
 
        std::vector<Color> pixels;
 
        void CheckBounds(int x_, int y_) const;
    };
 
}//end namespace img_lib


структуры, которые определял для работы с .tiff
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct TiffHeader
{
    uint16_t byteOrder;
    uint16_t magic;
    uint32_t ifdOffset;
};
 
struct IFDEntry
{
    uint16_t tag;
    uint16_t type;
    uint32_t count;
    uint32_t valueOffset;
};
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
19.09.2024, 12:11
Ответы с готовыми решениями:

Исходник, конвертирующий tiff to bmp?
Не найдётся у кого-нибудь исходника, конвертирующего tiff to bmp?

Чтение файла TIFF в память
Здравствуйте. Решил проверить простую консольную программу для чтения цветного графического файла TIFF. Код взят из руководства к...

Как прочитать заголовок бинарного файла в формате TIFF?
нужно считать заголовок *.tif - файла... открываю как поток для чтения бинарного файла вот так: ifstream...

6
Модератор
Эксперт Java
 Аватар для alecss131
2856 / 1363 / 406
Регистрация: 11.08.2017
Сообщений: 4,352
Записей в блоге: 2
19.09.2024, 12:53
Ifreqo, Если смотреть спецификации, то для rgb нужен такой набор полей

У Вас полей меньше чем даже для других форматов, которые могут быть: Bilevel, Grayscale, Palette Color и RGB
Правда я читая спеки 6 версии от адоба
0
8 / 8 / 4
Регистрация: 08.12.2022
Сообщений: 157
19.09.2024, 13:06  [ТС]
alecss131, .ppm тоже использует у меня формат rgb, но для него я не определял никаких дополнительных структур. Справилась структура Color из файла image.h(второе вложение)
0
Модератор
Эксперт Java
 Аватар для alecss131
2856 / 1363 / 406
Регистрация: 11.08.2017
Сообщений: 4,352
Записей в блоге: 2
19.09.2024, 13:08
Например 0х106 содержит тип изображения, 0 - WhiteIsZero, 1 - BlackIsZero, 2 - RGB, 3 - Palette color, 4 - Transparency Mask
0
8 / 8 / 4
Регистрация: 08.12.2022
Сообщений: 157
19.09.2024, 13:45  [ТС]
alecss131, я по умолчанию использую 8 бит на пиксель и тип rgba
C++
1
2
uint32_t bitsPerSample = 8;
uint32_t samplesPerPixel = 4;
но тип то нужен был rgb, а значит поле samplesPerPixel должно быть 3

ну и следовательно цикл записи пикселей
C++
1
2
3
4
5
6
7
8
9
10
11
for (int y = 0; y < image_.GetHeight(); ++y)
{
    for (int x = 0; x < image_.GetWidth(); ++x)
    {
        const Color& color = image_.GetPixel(x, y);
 
        file.write(reinterpret_cast<const char*>(&color.r), sizeof(color.r));
        file.write(reinterpret_cast<const char*>(&color.g), sizeof(color.g));
        file.write(reinterpret_cast<const char*>(&color.b), sizeof(color.b));
    }
}
0
Модератор
Эксперт Java
 Аватар для alecss131
2856 / 1363 / 406
Регистрация: 11.08.2017
Сообщений: 4,352
Записей в блоге: 2
19.09.2024, 14:10
Ifreqo, Повторяюсь еще раз, добавьте пакет 0х106 со значением 2
А bitsPerSample у всех имеет значение либо 4 либо 8, samplesPerPixel у rgb имеет 3, только вот bitsPerSample у rgb имеет значение не 8, а 8, 8, 8 для 3 (rgb) и 8, 8, 8, 8 для 4 (rgba)
То есть поле 0х102 должно содержать количество бит на сэмпл для каждого канала отдельно
То есть в 0х115 должно быть 3/4 а в 0х102 8,8,8/8,8,8,8 и должен быть заполнен 0х106 со значением 2
rgb от палитры отличается только 2 и 3 в 0х106 и у палитры есть ColorMap 0х140
Если не выполнить эти условия у Вас так и будет чб картинка
0
8 / 8 / 4
Регистрация: 08.12.2022
Сообщений: 157
19.09.2024, 14:19  [ТС]
alecss131, то что я написал выше исправило проблему, но добавлю некоторые изменения еще
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
19.09.2024, 14:19
Помогаю со студенческими работами здесь

Контрастирование, прореживание, построение гистограммы tiff изображения и переформатирование в bmp формат
Ребят , кто может , отзовитесь!!! Срочно нужна помощь знающих людей! В этой программе прореживание должно делаться по вот этой формуле...

Tiff в Bitmap
Мне нужно из графического файла *.tiff загрузить картинку в bitmap. Как это зделать? Заранее благодарен!

Конвертировать TIFF в BMP
Проблема такова. требуется создать метод конвертирования 10битного файла тифф в 8битный файл бмп. раскодировка исходного изображения...

Конвертировать tiff в bmp и обратно
Есть ли какие-нибудь простенькие библиотеки для конвертирования tiff в TBitmap и обратно? Или можно ли это сделать стандартными средствами...

Помогите прочитать TIFF-файл
Кто нибудь. подскажите подробный алгоритм и программный код для вывода на экран содержимого TIFF-файла. Просьба не использовать встроенных...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru