00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include "autoconfig.h"
00034 #endif
00035
00036 #include "common.h"
00037
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <errno.h>
00042
00043 #include "tools.h"
00044 typedef unsigned char uchar;
00045
00046 #ifndef TRUE
00047 #define TRUE 1
00048 #define FALSE 0
00049 #endif
00050
00051 #define M_SOF0 0xC0 // Start Of Frame N
00052 #define M_SOF1 0xC1 // N indicates which compression process
00053 #define M_SOF2 0xC2 // Only SOF0-SOF2 are now in common use
00054 #define M_SOF3 0xC3
00055 #define M_SOF5 0xC5 // NB: codes C4 and CC are NOT SOF markers
00056 #define M_SOF6 0xC6
00057 #define M_SOF7 0xC7
00058 #define M_SOF9 0xC9
00059 #define M_SOF10 0xCA
00060 #define M_SOF11 0xCB
00061 #define M_SOF13 0xCD
00062 #define M_SOF14 0xCE
00063 #define M_SOF15 0xCF
00064 #define M_SOI 0xD8 // Start Of Image (beginning of datastream)
00065 #define M_EOI 0xD9 // End Of Image (end of datastream)
00066 #define M_SOS 0xDA // Start Of Scan (begins compressed data)
00067 #define M_JFIF 0xE0 // Jfif marker
00068 #define M_EXIF 0xE1 // Exif marker
00069 #define M_COM 0xFE // COMment
00070 #define M_DQT 0xDB
00071 #define M_DHT 0xC4
00072 #define M_DRI 0xDD
00073
00074
00075 using namespace zmm;
00076
00077 #define ITEM_BUF_SIZE 16
00078 static int Get16m(const void * Short)
00079 {
00080 return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1];
00081 }
00082
00083 static int ioh_fgetc(Ref<IOHandler> ioh)
00084 {
00085 uchar c[1] = {0};
00086 int ret = ioh->read((char *)c, sizeof(char));
00087 if (ret < 0)
00088 return ret;
00089 return (int)c[0];
00090 }
00091
00092 static void get_jpeg_resolution(Ref<IOHandler> ioh, int *w, int *h)
00093 {
00094 int a;
00095
00096 a = ioh_fgetc(ioh);
00097
00098 if (a != 0xff || ioh_fgetc(ioh) != M_SOI)
00099 throw _Exception(_("get_jpeg_resolution: could not read jpeg specs"));
00100
00101 for(;;)
00102 {
00103 int itemlen;
00104 off_t skip;
00105 int marker = 0;
00106 int ll, lh, got;
00107 uchar Data[ITEM_BUF_SIZE];
00108
00109 for (a = 0; a < 7; a++)
00110 {
00111 marker = ioh_fgetc(ioh);
00112 if (marker != 0xff) break;
00113
00114 if (a >= 6)
00115 throw _Exception(_("get_jpeg_resolution: too many padding bytes"));
00116 }
00117
00118
00119 if (marker == 0xff)
00120 throw _Exception(_("get_jpeg_resolution: too many padding bytes!"));
00121
00122
00123 lh = ioh_fgetc(ioh);
00124 ll = ioh_fgetc(ioh);
00125
00126 itemlen = (lh << 8) | ll;
00127
00128 if (itemlen < 2)
00129 throw _Exception(_("get_jpeg_resolution: invalid marker"));
00130
00131 skip = 0;
00132 if (itemlen > ITEM_BUF_SIZE)
00133 {
00134 skip = itemlen - ITEM_BUF_SIZE;
00135 itemlen = ITEM_BUF_SIZE;
00136 }
00137
00138
00139 Data[0] = (uchar)lh;
00140 Data[1] = (uchar)ll;
00141
00142 got = ioh->read((char *)(Data + 2), itemlen - 2);
00143 if (got != itemlen-2)
00144 throw _Exception(_("get_jpeg_resolution: Premature end of file?"));
00145
00146 ioh->seek(skip, SEEK_CUR);
00147
00148 switch(marker)
00149 {
00150 case M_EOI:
00151 throw _Exception(_("get_jpeg_resolution: No image in jpeg!"));
00152 case M_SOF0:
00153 case M_SOF1:
00154 case M_SOF2:
00155 case M_SOF3:
00156 case M_SOF5:
00157 case M_SOF6:
00158 case M_SOF7:
00159 case M_SOF9:
00160 case M_SOF10:
00161 case M_SOF11:
00162 case M_SOF13:
00163 case M_SOF14:
00164 case M_SOF15:
00165 *w = Get16m(Data+5);
00166 *h = Get16m(Data+3);
00167 return;
00168 }
00169 }
00170 throw _Exception(_("get_jpeg_resolution: resolution not found"));
00171 }
00172
00173
00174 String get_jpeg_resolution(Ref<IOHandler> ioh)
00175 {
00176 int w, h;
00177 try
00178 {
00179 get_jpeg_resolution(ioh, &w, &h);
00180 }
00181 catch (Exception e)
00182 {
00183 ioh->close();
00184 throw e;
00185 }
00186 ioh->close();
00187
00188 return String::from(w) + "x" + h;
00189 }