Здравствуйте, уважаемые Хабарюзеры.
Как известно, фотографии со спутника «Электро-Л» выкладываются на FTP в двух форматах.
Один — общеизвестный jpg, который нам не интересен.
Второй, как писал Zelenyikot
Вот его мы и попытается прочитать.
Дополнительную информацию у меня прочитать не получилось, зато картинка вполне читаема, и она несколько отличается от той, что в JPG, по количеству бит на единственный канал. Если в JPG их 8 (256 оттенков серого), то в L15 их 10 (1024 оттенка серого).
Если изображение в файле не зашифровано, то в нём должны встречаться размеры изображения. Будем надеяться, что оно не зашифровано.
Размеры изображения у фотографий со спутника в формате jpg 2784x2784. Переведя 2784 в HEX получим 0A E0. Эту последовательность надо перевернуть и искать E0 0A
Нашлось
Сгруппировав эти данные по 4 байта и отобразив как десятичное число получим
От конца блока, вставленного чуть выше до конца файла 0xEC8800 (15501312) байт.
15501312/(2784*2784)=2. Из этих результатов предположим, что один пиксель описывается двумя байтами.
Но прежде чем пытаться прочитать изображение надо понять, как искать место, с которого оно начинается.
Два дня поисков в файлах L15 либо прямого адреса области с изображением или близкого к нему участка, либо смещения на этот адрес к успеху не привели.
Поэтому, будем искать этот участок «в лоб», читатя файл бит за битом до тех пор, пока не встретится число 2784 или 11136(это разрешение изображений от каналов R G B).
После чего проверяем, повторяется ли это число ещё раз, и, если оно повторяется, проверяем, равняется ли следующее число 16.
Если всё верно, поздравляю, мы нашли начало картинки.
Метод костыльный, но пока ошибок не давал.
Теперь нужно прочитать это изображение и как-то его отобразить или сохранить в файл. Так как с изображениями мне работать не приходилось, то для ускорения процесса и облегчения кода я решил использовать формат Portable anymap.
В формате P5, пиксели, яркость которых больше 255 (то есть больше 1-го байта) становятся чёрными.
Результат:
P2:
P5
И на последок код, который соеденяет вышенаписанные функции
Изображения с глубиной цвета 10 бит на канал можно использовать для создания HDRi изображений. Впрочем, это уже тема отдельного топика.
UPD: Есть подозрение, что текстовые данные хранятся в формате wchar. Надо будет проверить…
Как известно, фотографии со спутника «Электро-Л» выкладываются на FTP в двух форматах.
Один — общеизвестный jpg, который нам не интересен.
Второй, как писал Zelenyikot
«секретный» формат доступный только метеорологам. В сети нет ПО, которое позволяет его открыть и посмотреть. Правда меня заверили, что с точки зрения картинки, там то же самое, что и на JPEG, а дополнительная информация только текстом – всякие там, высоты, температуры, скорости…
Вот его мы и попытается прочитать.
Дополнительную информацию у меня прочитать не получилось, зато картинка вполне читаема, и она несколько отличается от той, что в JPG, по количеству бит на единственный канал. Если в JPG их 8 (256 оттенков серого), то в L15 их 10 (1024 оттенка серого).
Если изображение в файле не зашифровано, то в нём должны встречаться размеры изображения. Будем надеяться, что оно не зашифровано.
Размеры изображения у фотографий со спутника в формате jpg 2784x2784. Переведя 2784 в HEX получим 0A E0. Эту последовательность надо перевернуть и искать E0 0A
Нашлось
e0 0a 00 00 e0 0a 00 00 10 00
Сгруппировав эти данные по 4 байта и отобразив как десятичное число получим
2784 2784 16
От конца блока, вставленного чуть выше до конца файла 0xEC8800 (15501312) байт.
15501312/(2784*2784)=2. Из этих результатов предположим, что один пиксель описывается двумя байтами.
Но прежде чем пытаться прочитать изображение надо понять, как искать место, с которого оно начинается.
Два дня поисков в файлах L15 либо прямого адреса области с изображением или близкого к нему участка, либо смещения на этот адрес к успеху не привели.
Поэтому, будем искать этот участок «в лоб», читатя файл бит за битом до тех пор, пока не встретится число 2784 или 11136(это разрешение изображений от каналов R G B).
После чего проверяем, повторяется ли это число ещё раз, и, если оно повторяется, проверяем, равняется ли следующее число 16.
Если всё верно, поздравляю, мы нашли начало картинки.
long Find_Image_Pos(FILE *EL_Data,int *res_out)
{
unsigned int int_data;
int resolution;
unsigned long filepos;
filepos=0;
while(!feof(EL_Data))
{
fseek(EL_Data,filepos,SEEK_SET);
fread((void*)&int_data,sizeof(unsigned int),1,EL_Data);
if(int_data==2784||int_data==11136)
{
resolution=int_data;
fread((void*)&int_data,sizeof(unsigned int),1,EL_Data);
if(int_data==resolution)
{
fread((void*)&int_data,sizeof(unsigned int),1,EL_Data);
if(int_data==16)
{
*res_out=resolution;
return ftell(EL_Data);
}
}
}
filepos++;
}
return 0;
}
Метод костыльный, но пока ошибок не давал.
Теперь нужно прочитать это изображение и как-то его отобразить или сохранить в файл. Так как с изображениями мне работать не приходилось, то для ускорения процесса и облегчения кода я решил использовать формат Portable anymap.
Будем читать файл по 2 байта и записывать считанное значение в файл.
void Save_Image(FILE *EL_Data,FILE *EL_Image,long pos,int resolution)
{
#ifdef P5
char header[50];
sprintf(header,"P5\n%i %i\n1024\n",resolution,resolution);
fwrite(&header,strlen(header),1,EL_Image);
#else
fprintf(EL_Image,"P2\n%i %i\n1024\n",resolution,resolution);
#endif
int progress=-1;
int max=0;
int x=0,y=0;
int pixel=0;
fseek(EL_Data,pos,SEEK_SET);
for(y=0;y<resolution;y++)
{
if(progress<(y*100/resolution))
{
progress=(y*100/resolution);
cout<<progress<<"%"<<endl;
}
for(x=0;x<resolution;x++)
{
fread(&pixel,2,1,EL_Data);
#ifdef P5
fwrite(&pixel,1,1,EL_Image);
#else
fprintf(EL_Image,"%i\n",pixel);
#endif
if(pixel>max)
max=pixel;
}
}
cout<<"100 %"<<endl;
cout<<"max="<<max<<endl;
}
В формате P5, пиксели, яркость которых больше 255 (то есть больше 1-го байта) становятся чёрными.
Результат:
P2:
P5
И на последок код, который соеденяет вышенаписанные функции
#include <iostream>;
#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>
#include <windows.h>
//#define P5
using namespace std;
long Find_Image_Pos(FILE *EL_Data,int *res_out);
void Save_Image(FILE *EL_Data,FILE *EL_Image,long pos,int resolution);
int _tmain(int argc, _TCHAR* argv[])
{
FILE *EL_Data,*EL_Image;
if(argc==1)
return 0;
EL_Data=_wfopen(argv[1],L"rb");
if(!EL_Data)
return 0;
wchar_t out_file[300];
#ifdef P5
wsprintf(out_file,L"%s.P5.pgm",argv[1]);
EL_Image=_wfopen(out_file,L"wb");
#else
wsprintf(out_file,L"%s.P2.pgm",argv[1]);
EL_Image=_wfopen(out_file,L"wt");
#endif
if(!EL_Image)
return 0;
int resolution=0;
long pos=Find_Image_Pos(EL_Data,&resolution);
if(!pos)
return 0;
Save_Image(EL_Data,EL_Image,pos,resolution);
fclose(EL_Image);
fclose(EL_Data);
return 0;
}
Изображения с глубиной цвета 10 бит на канал можно использовать для создания HDRi изображений. Впрочем, это уже тема отдельного топика.
UPD: Есть подозрение, что текстовые данные хранятся в формате wchar. Надо будет проверить…