Esta es una tarea trivial. He escrito un programa c ++ que puede mostrar en la terminal. Podría publicar si estás interesado. También sería trivial escribir un Service
para mostrar el resultado.
//
// Display Comment, size of JPEG image
//
#include <iostream>
#include "../jpeg.h"
int main (int argc, const char * argv[])
{
Cjpeg Jpeg1;
switch(Jpeg1.OpenJpeg(argv[1]))
{
case INVALID_JPEG:
std::cerr << "Invalid JPEG" << std::endl;
return INVALID_JPEG;
case NOTFOUND_JPEG:
std::cerr << "File Not Found" << std::endl;
return NOTFOUND_JPEG;
case NOT_JPEG:
std::cerr << "Not JPEG" << std::endl;
return NOT_JPEG;
default:
std::cout << Jpeg1.Comments << " " << Jpeg1.Width << " * " << Jpeg1.Height << std::endl;
}
return 0;
}
// jpeg.cpp: implementation of the Cjpeg class.
// ANSI version
//////////////////////////////////////////////////////////////////////
#include "jpeg.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Cjpeg::Cjpeg()
{
Height = Width = 0;
Comments[0] = '//
// Display Comment, size of JPEG image
//
#include <iostream>
#include "../jpeg.h"
int main (int argc, const char * argv[])
{
Cjpeg Jpeg1;
switch(Jpeg1.OpenJpeg(argv[1]))
{
case INVALID_JPEG:
std::cerr << "Invalid JPEG" << std::endl;
return INVALID_JPEG;
case NOTFOUND_JPEG:
std::cerr << "File Not Found" << std::endl;
return NOTFOUND_JPEG;
case NOT_JPEG:
std::cerr << "Not JPEG" << std::endl;
return NOT_JPEG;
default:
std::cout << Jpeg1.Comments << " " << Jpeg1.Width << " * " << Jpeg1.Height << std::endl;
}
return 0;
}
// jpeg.cpp: implementation of the Cjpeg class.
// ANSI version
//////////////////////////////////////////////////////////////////////
#include "jpeg.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Cjpeg::Cjpeg()
{
Height = Width = 0;
Comments[0] = '%pre%';
}
Cjpeg::~Cjpeg()
{
}
//--------------------------------------------------------------------------
// JPEG markers consist of one or more 0xFF bytes, followed by a marker
// code byte (which is not an FF).
//--------------------------------------------------------------------------
#define M_SOF0 0xC0 // Start Of Frame N
#define M_SOF1 0xC1 // N indicates which compression process
#define M_SOF2 0xC2 // Only SOF0-SOF2 are now in common use
#define M_SOF3 0xC3
#define M_SOF5 0xC5 // NB: codes C4 and CC are NOT SOF markers
#define M_SOF6 0xC6
#define M_SOF7 0xC7
#define M_SOF9 0xC9
#define M_SOF10 0xCA
#define M_SOF11 0xCB
#define M_SOF13 0xCD
#define M_SOF14 0xCE
#define M_SOF15 0xCF
#define M_SOI 0xD8 // Start Of Image (beginning of datastream)
#define M_EOI 0xD9 // End Of Image (end of datastream)
#define M_SOS 0xDA // Start Of Scan (begins compressed data)
#define M_JFIF 0xE0 // Jfif marker
#define M_APP1 0xE1 // Exif marker
#define M_COM 0xFE // COMment
#define M_DQT 0xDB
#define M_DHT 0xC4
#define M_DRI 0xDD
// Process a SOFn marker
void Cjpeg::process_SOF (unsigned length)
{
int data_precision, num_components;
unsigned char Data[128];
unsigned long cb; // count of bytes read
cb = fread(&Data, 1, length, fp); // read JPEG
data_precision = Data[0];
Height = Get16(Data+1);
Width = Get16(Data+3);
num_components = Data[5];
}
// Process a COM marker.
void Cjpeg::process_COM (unsigned length)
{
unsigned nch;
unsigned long cb; // count of bytes read
nch = 0;
nch = (length > MAX_COMMENT) ? MAX_COMMENT : length; // Truncate if it won't fit in our structure.
cb = fread(&Comments, 1, nch, fp); // read JPEG
Comments[nch] = '%pre%'; // Null terminate
if(cb<length)
{
fseek(fp, length - cb, SEEK_CUR); // point to next JPEG marker
}
}
void Cjpeg::process_APP1(unsigned int length)
{
fseek(fp, length, SEEK_CUR); // point to next JPEG marker
}
int Cjpeg::OpenJpeg(const char *JpegFile)
{
int count;
unsigned long cb; // count of bytes read
fp = fopen(JpegFile, "rb");
if(fp == NULL)
{
return NOTFOUND_JPEG;
}
cb = fread(&JpegMarker, 2, 1, fp); // read JPEG
if(JpegMarker[0] != 0xFF || JpegMarker[1] != M_SOI)
{
fclose(fp);
return NOT_JPEG; // Not JPEG File
}
while(cb != 0) // Stop if EOF reached
{
cb = fread(&JpegMarker, 2, 1, fp); // read JPEG marker
if(JpegMarker[0] != 0xFF)
{
fclose(fp);
return INVALID_JPEG; // Invalid File
}
switch(JpegMarker[1])
{
case M_SOS: // stop before hitting compressed data
case M_EOI: // in case it's a table only JPEG stream
fclose(fp);
return 0; // Normal exit
}
cb = fread(&JpegSecCount, 2, 1, fp); // read length of field
count = Get16(JpegSecCount);
count -= 2; // value includes length bytes
switch(JpegMarker[1])
{
case M_COM: // Comment section
process_COM (count);
break;
case M_SOF0:
case M_SOF1:
case M_SOF2:
process_SOF (count);
break;
case M_APP1:
process_APP1 (count);
break;
case M_JFIF:
default:
// Skip any other sections.
fseek(fp, count, SEEK_CUR); // point to next JPEG marker
break;
}
}
fclose(fp);
return INVALID_JPEG; // Possible Invalid File
}
';
}
Cjpeg::~Cjpeg()
{
}
//--------------------------------------------------------------------------
// JPEG markers consist of one or more 0xFF bytes, followed by a marker
// code byte (which is not an FF).
//--------------------------------------------------------------------------
#define M_SOF0 0xC0 // Start Of Frame N
#define M_SOF1 0xC1 // N indicates which compression process
#define M_SOF2 0xC2 // Only SOF0-SOF2 are now in common use
#define M_SOF3 0xC3
#define M_SOF5 0xC5 // NB: codes C4 and CC are NOT SOF markers
#define M_SOF6 0xC6
#define M_SOF7 0xC7
#define M_SOF9 0xC9
#define M_SOF10 0xCA
#define M_SOF11 0xCB
#define M_SOF13 0xCD
#define M_SOF14 0xCE
#define M_SOF15 0xCF
#define M_SOI 0xD8 // Start Of Image (beginning of datastream)
#define M_EOI 0xD9 // End Of Image (end of datastream)
#define M_SOS 0xDA // Start Of Scan (begins compressed data)
#define M_JFIF 0xE0 // Jfif marker
#define M_APP1 0xE1 // Exif marker
#define M_COM 0xFE // COMment
#define M_DQT 0xDB
#define M_DHT 0xC4
#define M_DRI 0xDD
// Process a SOFn marker
void Cjpeg::process_SOF (unsigned length)
{
int data_precision, num_components;
unsigned char Data[128];
unsigned long cb; // count of bytes read
cb = fread(&Data, 1, length, fp); // read JPEG
data_precision = Data[0];
Height = Get16(Data+1);
Width = Get16(Data+3);
num_components = Data[5];
}
// Process a COM marker.
void Cjpeg::process_COM (unsigned length)
{
unsigned nch;
unsigned long cb; // count of bytes read
nch = 0;
nch = (length > MAX_COMMENT) ? MAX_COMMENT : length; // Truncate if it won't fit in our structure.
cb = fread(&Comments, 1, nch, fp); // read JPEG
Comments[nch] = '%pre%'; // Null terminate
if(cb<length)
{
fseek(fp, length - cb, SEEK_CUR); // point to next JPEG marker
}
}
void Cjpeg::process_APP1(unsigned int length)
{
fseek(fp, length, SEEK_CUR); // point to next JPEG marker
}
int Cjpeg::OpenJpeg(const char *JpegFile)
{
int count;
unsigned long cb; // count of bytes read
fp = fopen(JpegFile, "rb");
if(fp == NULL)
{
return NOTFOUND_JPEG;
}
cb = fread(&JpegMarker, 2, 1, fp); // read JPEG
if(JpegMarker[0] != 0xFF || JpegMarker[1] != M_SOI)
{
fclose(fp);
return NOT_JPEG; // Not JPEG File
}
while(cb != 0) // Stop if EOF reached
{
cb = fread(&JpegMarker, 2, 1, fp); // read JPEG marker
if(JpegMarker[0] != 0xFF)
{
fclose(fp);
return INVALID_JPEG; // Invalid File
}
switch(JpegMarker[1])
{
case M_SOS: // stop before hitting compressed data
case M_EOI: // in case it's a table only JPEG stream
fclose(fp);
return 0; // Normal exit
}
cb = fread(&JpegSecCount, 2, 1, fp); // read length of field
count = Get16(JpegSecCount);
count -= 2; // value includes length bytes
switch(JpegMarker[1])
{
case M_COM: // Comment section
process_COM (count);
break;
case M_SOF0:
case M_SOF1:
case M_SOF2:
process_SOF (count);
break;
case M_APP1:
process_APP1 (count);
break;
case M_JFIF:
default:
// Skip any other sections.
fseek(fp, count, SEEK_CUR); // point to next JPEG marker
break;
}
}
fclose(fp);
return INVALID_JPEG; // Possible Invalid File
}