📜 ⬆️ ⬇️

Viewing images from the L15 format of the Electro-L satellite

Hello, dear Habarusery.
As you know, photos from the Electro-L satellite are laid out on FTP in two formats.
One is the well-known jpg, which is not interesting to us.
The second, as Zelenyikot wrote
The “secret” format is available only to meteorologists. There is no software in the network that allows you to open and view it. True, I was assured that from the point of view of the picture, there is the same thing as on JPEG, and the additional information is just text — everyone there, altitude, temperature, speed ...

Here we try to read it.
I could not read the additional information, but the picture is quite readable, and it differs somewhat from the one in JPG, in the number of bits per single channel. If there are 8 of them in JPG (256 shades of gray), then in L15 there are 10 of them (1024 shades of gray).


If the image in the file is not encrypted, then it should contain the image size. Let's hope that it is not encrypted.
Image sizes from satellite photos in jpg format 2784x2784. Transferring 2784 to HEX, we get 0A E0. This sequence must be inverted and look for E0 0A
Found e0 0a 00 00 e0 0a 00 00 10 00
By grouping this data into 4 bytes and displaying as a decimal, we get 2784 2784 16

From the end of the block inserted slightly to the end of the file 0xEC8800 (15501312) bytes.
15501312 / (2784 * 2784) = 2. From these results, assume that one pixel is described by two bytes.
')
But before you try to read the image you need to understand how to find the place from which it begins.
Two days of searching in the L15 files or the direct address of the region with the image or a plot close to it, or the displacement to this address did not lead to success.
Therefore, we will look for this area "in the forehead", reading the file bit by bit until the number 2784 or 11136 is encountered (this is the resolution of the images from the RGB channels).
After that, we check whether this number is repeated again, and, if it repeats, we check whether the next number is 16.
If everything is correct, congratulations, we found the beginning of the picture.
 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; } 

The method is a crutch, but so far no errors were given

Now you need to read this image and somehow display it or save it to a file. Since I didn’t work with images, I decided to use the Portable anymap format to speed up the process and facilitate the code.
     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; } 

In the P5 format, pixels whose brightness is greater than 255 (that is, greater than the 1st byte) turn black.

Result:
P2:

P5


And lastly, the code that connects the above functions
 #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; } 


Images with a color depth of 10 bits per channel can be used to create HDRi images. However, this is a topic for a separate topic.

UPD: There is a suspicion that text data is stored in wchar format. I'll have to check ...

Source: https://habr.com/ru/post/186560/


All Articles