Ошибка CImg: не удалось распознать формат файла xxx.png

Я искал код на С++, который дает мне значения RGB всех пикселей файла png.

Поэтому я много искал в Интернете и нашел разные способы сделать это, например, с помощью libpng, OpenCV, Magick++, CImg и т. д., и я просто решил использовать CImg (в основном потому, что я не знаю, как это сделать). используйте OpenCV, хотя я много искал о том, как установить и использовать его в Code::Blocks, и это как-то связано с mingw64, который установщик, который я скачал из Sorceforge, продолжает выдавать мне ошибки в середине загрузки некоторых файлов, и о для остальных я просто не могу найти подходящий заголовочный файл (например, Magick++.h), совместимый с Code::Blocks... Так что, если вы думаете, что некоторые из них будут лучше и проще, чем CImg.h, то я Буду признателен, если вы предоставите мне ссылку для скачивания шапки или любую другую необходимую вещь)

Итак, вот код, который я нашел с Cimg:

#include <windows.h>
#include <iostream>
using namespace std;

#include <CImg.h>
using namespace cimg_library;

int main()
{
CImg<unsigned char>src("twittericon.png");
int width = src.width();
int height = src.height();
cout << width << "x" << height << endl;
for (int r = 0; r < height; r++)
for (int c = 0; c < width; c++)
   cout << "(" << r << "," << c << ") ="
        << " R" << (int)src(c,r,0,0)
        << " G" << (int)src(c,r,0,1)
        << " B" << (int)src(c,r,0,2) << endl;
return 0;
}

Но проблема в том, что после запуска программы она выдает ошибку: CImg::load(): не удалось распознать формат файла 'twittericon.png'

Что мне делать с ошибкой?

И, кстати, знаете ли вы какой-нибудь лучший способ прочитать эти значения RGB файла png? Если вы это сделаете, не могли бы вы также предоставить мне небольшую инструкцию для этого? Спасибо.


person mitrafrz    schedule 14.02.2018    source источник
comment
Поиск Google: MSDN SetDIBitsToDevice, нажмите на 1-ю ссылку, перейдите к таблице внизу страницы и включите библиотеку в настройках вашего компоновщика. Все функции Win32API перечислены на сайте MSDN вместе с необходимыми заголовками и библиотеками.   -  person Richard Critten    schedule 14.02.2018
comment
Я добавил строку: #include ‹windows.h› И скачал Gdi32.lib и добавил его в настройки компоновщика в настройках моего компилятора. Теперь при запуске программы нет ошибки, но потом выдает вот такую ​​ошибку: CImg‹unsigned char›::load(): Не удалось распознать формат файла 'twittericon.png' Теперь что мне делать? С файлом png не работает?   -  person mitrafrz    schedule 15.02.2018
comment
Вы должны установить libpng для чтения/записи файлов PNG. Я подозреваю, что вместо этого вам лучше установить ImageMagick, потому что CImg может использовать его для чтения файлов большинства форматов. Не забудьте установить флажок Установить устаревшие инструменты при установке ImageMagick.   -  person Mark Setchell    schedule 15.02.2018
comment
Помогите, пожалуйста, какую скачать? Я использую Windows 10, C++ и Code::Blocks, если вам нужно. imagemagick.org/script/install-source.php   -  person mitrafrz    schedule 15.02.2018
comment
Вам не нужно устанавливать источник. Можно использовать готовые бинарники, это проще.   -  person Mark Setchell    schedule 15.02.2018
comment
Итак, мне нужно скачать и установить это: ImageMagick-7.0.7-22-Q16-x64-dll.exe? Извините, что задаю много вопросов, я просто новичок в этом... Я был бы очень признателен, если бы вы просветили меня немного больше об этом.   -  person mitrafrz    schedule 15.02.2018
comment
Что вы на самом деле пытаетесь сделать в целом? Вы хотите просто прочитать значения RGB одного файла PNG один раз? Или вы пишете большую систему обработки изображений общего назначения, которую вы будете использовать в течение многих лет и которая должна иметь возможность читать файлы многих форматов? Какую обработку нужно сделать?   -  person Mark Setchell    schedule 15.02.2018
comment
Не могли бы вы попробовать ответить на вопрос выше, прежде чем спрашивать больше, иначе мне придется отвечать 3 раза, чтобы охватить все возможности :-)   -  person Mark Setchell    schedule 16.02.2018


Ответы (1)


Есть много способов получить значения пикселей RGB в файле PNG, и лучший из них зависит от вашего фактического сценария использования.


Вариант 1

Если у вас есть один или два файла PNG, и вы просто хотите легко получить пиксели RGB один раз, я бы посоветовал вам установить любой из готовых двоичных файлов ImageMagick, на которые вы уже дали ссылки. Затем мы можем создать тестовый PNG файл, подобный этому, в командной строке терминала или командной строки:

convert xc:red xc:lime xc:blue +append \( xc:cyan xc:magenta xc:yellow +append \) -append image.png

и это будет выглядеть так (только меньше):

введите здесь описание изображения

(Я думаю, вы опускаете обратную косую черту под Windows в приведенной выше команде)

Хорошо, теперь вы хотите увидеть значения RGB, поэтому вы можете вывести файл как текст:

convert image.png -depth 8 txt:

Пример вывода

# ImageMagick pixel enumeration: 3,2,65535,srgb
0,0: (65535,0,0)  #FF0000  red
1,0: (0,65535,0)  #00FF00  lime
2,0: (0,0,65535)  #0000FF  blue
0,1: (0,65535,65535)  #00FFFF  cyan
1,1: (65535,0,65535)  #FF00FF  magenta
2,1: (65535,65535,0)  #FFFF00  yellow

Или вы можете преобразовать файл в почтенный (но превосходный) формат NetPBM описание NetPBM в Википедии в режиме ASCII:

convert image.png -compress none image.pnm

Теперь вы получаете такой файл, который вы можете легко прочитать:

P3                              # PPM in ASCII mode
3 2                             # width=3 height=2
255                             # 8-bit
255 0 0 0 255 0 0 0 255 
0 255 255 255 0 255 255 255 0 

Если вы опустите -compress none, вы получите тот же файл, но данные RGB будут в 8-битном двоичном формате без знака, и тогда весь файл будет очень легко читаться на C/C++. Фактически, CImg все равно знает, как их читать/писать.

Таким образом, вы можете заранее преобразовать любые изображения (TIF, BMP, JPEG, GIF), к которым вы хотите получить доступ, в файлы NetBM PPM и просто читать и записывать файлы PPM, используя встроенные процедуры в CImg. . Работа выполнена!


Вариант 2

На следующем уровне вы можете установить ImageMagick из готовых двоичных файлов на веб-сайте ImageMagick, а затем использовать CImg. Затем CImg обнаружит, что программа ImageMagick convert/magick использует ее для преобразования всего, что она не может прочитать сама от своего имени. Таким образом, вы получите мгновенный бесплатный доступ к более чем 200 форматам, о которых знает ImageMagick.


Вариант 3

В качестве альтернативы вы можете собрать и установить libpng, а затем, когда вы пишете код с помощью CImg, вы определяете макрос до включения CImg.h, и он использует libpng для чтения и записи файлов PNG.

Это довольно много проблем, когда вы можете просто позволить ImageMagick сделать всю работу, и в конце вы получите только PNG поддержку, а не более 200 форматов для всей этой работы.

Этот сценарий выглядит так:

#define cimg_use_png 1
#include "CImg.h"
...
...

Вы бы скомпилировали с:

c++ -I CIMG_DIRECTORY -L LIBPNG_DIRECTORY -lpng -lz

Я сделал другой ответ, используя эту опцию для libjpeg и заставив CIMg читать и записывать файлы JPEG. Я могу только сказать, что это была полная боль - этот ответ здесь.

person Mark Setchell    schedule 15.02.2018
comment
Еще раз извините за бесконечные вопросы, как я уже сказал, я всего лишь новичок (кто так благодарен за ваше руководство, хотя:)) Итак, первый вопрос, о чем именно эта строка в разделе «Вариант 1»? : convert xc:red xc:lime xc:blue +append \( xc:cyan xc:magenta xc:yellow +append \) -append image.png и 2-й вопрос был бы таким же, как и первый вопрос, но про эту строчку: convert image.png -compress none image.pnm Вроде бы это не команды, так что же это? Лучше сказать, как должен выглядеть код (может показаться слишком глупым, но я просто не понимаю :( ) - person mitrafrz; 16.02.2018
comment
И есть ли что-то еще, что мне нужно сделать, кроме как установить ImageMagick и скопировать содержимое папки Include из его установочного каталога в папку Include в каталоге установки Code::Blocks, а затем добавить строку #include <Magick++.h> в начало моего кода? Потому что это все, что я сделал (все, что я знал, что должен был сделать). А что касается части Варианта 2, в которой CImg использует ImageMagick для преобразования, что вы подразумеваете под convert/magick? Будет ли это частью кода, о котором я упоминал вначале? (БОГ МНЕ ТАК ИЗВИНЯЕТСЯ, ЕСЛИ Я ПРИЧУЖУ ТЕБЕ ГОЛОВНУЮ БОЛЬ! :( ) - person mitrafrz; 16.02.2018
comment
Никаких проблем, мы все учимся. В1) Вы просто вводите эту команду в терминал, или в командную строку, или в окно DOS, или как там Windows называет это, когда вы вводите такие команды, как DIR. - person Mark Setchell; 16.02.2018
comment
Q3) Нет, не #include Magick++.h это экспериментально и не нужно. - person Mark Setchell; 16.02.2018
comment
Q4) В версии 7 ImageMagick команда, которую вы вводите для запуска в командной строке, изменилась с convert (v6) на magick (v7). Если при установке v7 вы установите флажок Install legacy tools, вы сможете использовать magick или convert в командной строке. Если вы не установите этот флажок, вы сможете использовать только magick. - person Mark Setchell; 16.02.2018
comment
И еще вопрос, как сохранить коды цветов в 2D-массиве? - person mitrafrz; 16.02.2018
comment
Не уверен, что вы подразумеваете под двумерным массивом. Ваше изображение имеет 3 измерения, высоту, ширину и цветовой канал? Он уже находится в массиве, если вы используете CImg - как вы думаете, что такое src(c,r,0,0) в вашей программе? - person Mark Setchell; 16.02.2018
comment
Во-первых, как я уже дважды говорил, я в этом деле совсем новичок, и я впервые работаю с «файлами» (в школе!) Итак, что касается кода, у меня есть несколько вопросов, и да, один из них будет: что такое src(int,int,int,int)? Все, что я могу предположить, это просто сокращение от «Источник» или что-то в этом роде? И даже если это так, какой в ​​этом прок? Поскольку мы недавно узнали о файлах и немного поработали с fstream , у меня возник вопрос: почему мы не можем просто использовать ifstream для получения файла png, и что именно делает src? - person mitrafrz; 16.02.2018
comment
А что касается 2D-массива, я имел в виду массив высоты × ширины с сохраненными шестнадцатеричными цветовыми кодами, например. Я хочу, чтобы FF0000 сохранялся для красного цвета, а не сохранял все 3 кода 255,0,0. Как я могу это сделать? - person mitrafrz; 16.02.2018
comment
src() фактически уже является массивом. Вы получаете доступ к красному пикселю с помощью src(c,r,0,0), а к зеленому с помощью src(c,r,0,1). Нет необходимости хранить все дважды. Если вы хотите увидеть шестнадцатеричный код, просто выполните std::cout << std::hex << src(c,r,0,0) << std::endl; - person Mark Setchell; 16.02.2018
comment
Спасибо и еще один вопрос... что это за третий 0 в src(c,r,0*,0)? - person mitrafrz; 16.02.2018
comment
Оставьте его на нуле. CImg может работать с трехмерными объемными формами, такими как КТ (компьютерная томография), и этот ноль является индексом для оси Z. - person Mark Setchell; 16.02.2018