NOTES: Porting IIPImage Server to VS2010
by Bubba
If you aren’t interesting in porting C\C++ code to VS2010, nor are you interested in Image Processing Servers; you probably want to stop reading right about ….. here.
For the rest of you, this is a rough documentation of what I have done to get IIP to compile under Windows 7 Ultimate (x64) using Visual Studio 2010 (version 10.0.30319.1). There are my notes for getting it to compile, there are still a few issues, but it compiles and it runs under Apache on Windows. Even though this is a x64 OS, we are relentlessly targeting an x32 architecture in the build.
Created an IIP_Port directory structure
Using Visual Studio 10
LIBFCGI
- Acquired from: http://www.fastcgi.com/dist/fcgi.tar.gz
- Open C:\iip_port\fcgi-2.4.0\Win32\libfcgi.dsp in Visual Studio.
- Copy fcgi_config_x86.h to fcgi_config.h
- Convert and Open Projects (Yes)
- Build Debug version (Save Solution Name)
- Verify C:\iip_port\fcgi-2.4.0\libfcgi\Debug\libfcgi.dll exists
- Build Release version
- Verify C:\iip_port\fcgi-2.4.0\libfcgi\Release\libfcgi.dll exists
- Verify C:\iip_port\fcgi-2.4.0\libfcgi\Release\libfcgi.lib exists
LIBJPEG
- Acquired from: http://www.ijg.org/files/jpegsr8c.zip
- Run C:\iip_port\jpeg-8c>NMAKE /f makefile.vc setup-v10
This will move jconfig.vc to jconfig.h and makefiles to project files.
(Note that the renaming is critical!) - Open the solution file C:\iip_port\jpeg-8c\jpeg.sln
- Build the Release Version of the library project.
- Verify C:\iip_port\jpeg-8c\Release\jpeg.lib exists
- Open the solution file C:\iip_port\jpeg-8c\apps.sln
- Build the Release Version application projects.
- Run C:\iip_port\jpeg-8c>NMAKE /f makefile.vc test-build
- Verify ‘no differences encountered’
- Return to the jpeg.sln
- Right click on the project, and go to properties
- Modify Configuration Type and change to Dynamic Library (.dll), Click OK
- Re-Build the Release Version of the library project.
- Verify C:\iip_port\jpeg-8c\Release\jpeg.dll exists
- Verify C:\iip_port\jpeg-8c\Release\jpeg.lib exists
- I had some issues with this, don’t remember precisely what, but had to recompile a couple of different ways to get both the lib and the dll.
LIBTIFF
- Acquired from: ftp://ftp.remotesensing.org/pub/libtiff/tiff-3.9.4.zip
- C:\iip_port\tiff-3.9.4\libtiff>NMAKE /f makefile.vc
- Verify C:\iip_port\tiff-3.9.4\libtiff\libtiff.dll exists
- Verify C:\iip_port\tiff-3.9.4\libtiff\libtiff.lib exists
- I had some issues with this, don’t remember precisely what, but had to recompile a couple of different ways to get both the lib and the dll.
ZLIB
- Acquired from: http://zlib.net/zlib125.zip
- Also get http://www.winimage.com/zLibDll/zlib125dll.zip
- unzipped both to C:\iip_port\zlib-1.2.5\
- Verify C:\iip_port\zlib-1.2.5\dll32\zlibwapi.dll exists
- Verify C:\iip_port\zlib-1.2.5\dll32\zlibwapi.lib exists
- Verify C:\iip_port\zlib-1.2.5\zlib.h exists
IIPSRV
- Open Visual Studio 10
- File -> New –> Project
- Select Visual C++ -> Win32 Console Application
- Name it IIPSRV
- Modify Location to: C:\iip_port\iipsrv
- OK, then Next
- Select Empty Project
- Finish
- Right click the project, ADD Existing, and select all files in C:\iip_port\iipsrv to add
- Right click the project, ADD Existing, and select all files in C:\iip_port\iipsrv\src to add
- Right click the project, Open Properties
- Under C/C++ -> General We need to add additional Include Directories
- C:\iip_port\fcgi-2.4.0\include
- C:\iip_port\jpeg-8c
- C:\iip_port\tiff-3.9.4\libtiff
- C:\iip_port\zlib-1.2.5
- After you click apply, wait a second for it to find/recompile the new headers from the path
- Under Linker -> General We need to add additional Library Directories
- C:\iip_port\fcgi-2.4.0\libfcgi\Release
- C:\iip_port\jpeg-8c\Release
- C:\iip_port\tiff-3.9.4\libtiff
- C:\iip_port\zlib-1.2.5\dll32
- After you click apply, wait a second for it to find/recompile the new headers from the path
- Under Linker –> Input We need to add additional Dependencies
- libfcgi.lib
- libtiff.lib
- zlibwapi.lib
- jpeg.lib
- Build Solution (Debug Version)
- Should Have 50 Build errors (right click the error list and turn off Show Intellisense Errors)
- Right Click KakaduImage.cc and remove from project
The MS Compiler doesn’t support snprintf, we need to alias that to _snprintf so it will work.
We will make the following modifications to source files:
IIPResponse.h
1: #if _MSC_VER
2: #define snprintf _snprintf
3: #endif
Cache.h
1: #if _MSC_VER
2: #define snprintf _snprintf
3: #endif
Cache.h
1: #if _MSC_VER
2: #define snprintf _snprintf3: #endifIIPImage.h
1: #if _MSC_VER
2: #define snprintf _snprintf3: #include <time.h>
4: #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)5: #endiffif.cc
1: #include <algorithm>2: #include <locale>3: #if _MSC_VER
4: // Implement strptime under windows
5: static const char* kWeekFull[] = {6: "Sunday", "Monday", "Tuesday", "Wednesday",7: "Thursday", "Friday", "Saturday"8: };9:10: static const char* kWeekAbbr[] = {11: "Sun", "Mon", "Tue", "Wed",12: "Thu", "Fri", "Sat"13: };14:15: static const char* kMonthFull[] = {16: "January", "February", "March", "April", "May", "June",17: "July", "August", "September", "October", "November", "December"18: };19:20: static const char* kMonthAbbr[] = {21: "Jan", "Feb", "Mar", "Apr", "May", "Jun",22: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"23: };24:25: static const char* _parse_num(const char* s, int low, int high, int* value) {26: const char* p = s;27: for (*value = 0; *p != NULL && isdigit(*p); ++p) {
28: *value = (*value) * 10 + static_cast<int>(*p) - static_cast<int>('0');29: }30:31: if (p == s || *value < low || *value > high) return NULL;32: return p;
33: }34:35: static char* _strptime(const char *s, const char *format, struct tm *tm) {36: while (*format != NULL && *s != NULL) {
37: if (*format != '%') {
38: if (*s != *format) return NULL;39:40: ++format;41: ++s;42: continue;
43: }44:45: ++format;46: int len = 0;
47: switch (*format) {
48: // weekday name.
49: case 'a':
50: case 'A':
51: tm->tm_wday = -1;52: for (int i = 0; i < 7; ++i) {53: len = static_cast<int>(strlen(kWeekAbbr[i]));
54: if (strnicmp(kWeekAbbr[i], s, len) == 0) {
55: tm->tm_wday = i;56: break;
57: }58:59: len = static_cast<int>(strlen(kWeekFull[i]));
60: if (strnicmp(kWeekFull[i], s, len) == 0) {
61: tm->tm_wday = i;62: break;
63: }64: }65: if (tm->tm_wday == -1) return NULL;66: s += len;67: break;
68:69: // month name.
70: case 'b':
71: case 'B':
72: case 'h':
73: tm->tm_mon = -1;74: for (int i = 0; i < 12; ++i) {75: len = static_cast<int>(strlen(kMonthAbbr[i]));
76: if (strnicmp(kMonthAbbr[i], s, len) == 0) {
77: tm->tm_mon = i;78: break;
79: }80:81: len = static_cast<int>(strlen(kMonthFull[i]));
82: if (strnicmp(kMonthFull[i], s, len) == 0) {
83: tm->tm_mon = i;84: break;
85: }86: }87: if (tm->tm_mon == -1) return NULL;88: s += len;89: break;
90:91: // month [1, 12].
92: case 'm':
93: s = _parse_num(s, 1, 12, &tm->tm_mon);94: if (s == NULL) return NULL;95: --tm->tm_mon;96: break;
97:98: // day [1, 31].
99: case 'd':
100: case 'e':
101: s = _parse_num(s, 1, 31, &tm->tm_mday);102: if (s == NULL) return NULL;103: break;
104:105: // hour [0, 23].
106: case 'H':
107: s = _parse_num(s, 0, 23, &tm->tm_hour);108: if (s == NULL) return NULL;109: break;
110:111: // minute [0, 59]
112: case 'M':
113: s = _parse_num(s, 0, 59, &tm->tm_min);114: if (s == NULL) return NULL;115: break;
116:117: // seconds [0, 60]. 60 is for leap year.
118: case 'S':
119: s = _parse_num(s, 0, 60, &tm->tm_sec);120: if (s == NULL) return NULL;121: break;
122:123: // year [1900, 9999].
124: case 'Y':
125: s = _parse_num(s, 1900, 9999, &tm->tm_year);126: if (s == NULL) return NULL;127: tm->tm_year -= 1900;128: break;
129:130: // year [0, 99].
131: case 'y':
132: s = _parse_num(s, 0, 99, &tm->tm_year);133: if (s == NULL) return NULL;134: if (tm->tm_year <= 68) {
135: tm->tm_year += 100;136: }137: break;
138:139: // arbitray whitespace.
140: case 't':
141: case 'n':
142: while (isspace(*s)) ++s;
143: break;
144:145: // '%'.
146: case '%':
147: if (*s != '%') return NULL;148: ++s;149: break;
150:151: // All the other format are not supported.
152: default:
153: return NULL;
154: }155: ++format;156: }157:158: if (*format != NULL) {
159: return NULL;
160: } else {
161: return const_cast<char*>(s);162: }163: }164:165: char* strptime(const char *buf, const char *fmt, struct tm *tm) {166: return _strptime(buf, fmt, tm);
167: }168:169:170:171: static time_t timegm(struct tm *tm){172: time_t answer;173: char *zone;
174:175: zone=getenv("TZ");176: putenv("TZ=UTC");
177: tzset();178: answer=mktime(tm);179: if(zone)
180: {181: char *old_zone;
182:183: old_zone=(char *)malloc(3+strlen(zone)+1);184: if(old_zone)
185: {186: strcpy(old_zone,"TZ=");187: strcat(old_zone,zone);188: putenv(old_zone);189: }190: }191: else
192: #ifdef HAVE_UNSETENV193: unsetenv("TZ");
194: #else
195: putenv("TZ");
196: #endif197:198: tzset();199: return answer;
200: }201: #endif202:203:near line 75 replace
std::isxdigit(*(iter + 1)) && std::isxdigit(*(iter + 2)) ){
with1: #if _MSC_VER
2: isxdigit(*(iter + 1)) && isxdigit(*(iter + 2)) ){3: #else
4: std::isxdigit(*(iter + 1)) && std::isxdigit(*(iter + 2)) ){5: #endifCVT.cc
1: #if _MSC_VER
2: #include <algorithm>3: #include <locale>4: #endifDeepZoom.cc
Near the top add (because microsoft doesn’t provide the log2 function for us)
1: #if _MSC_VER
2: double log2(double max){3: return log((double)max)/log((double)2);4: }5: #endifIIPImage.cc
1: #if _MSC_VER
2: #define snprintf _snprintf3: #include <time.h>
4: #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)5: #endifFIF.cc
1: #include <time.h>
JPEGCompressor.cc
around line 388 Replace:
unsigned char t[width*height*channels+1024]; // Add an extra 1k for extra buffering
with1: unsigned char * t;2: t = new unsigned char[width*height*channels+1024]; // Add an extra 1k for extra bufferingWatermark.cc
around line 47 Replace:
uint32 buffer[_width*_height];
with1: uint32 * buffer;2: buffer = new uint32[_width*_height];
- Build the solution.
- Stop Apache
- Copy
- jpeg.dll
- libfcgi.dll
- libtiff.dll
- zlibwapi.dll
- IIPSRV.exe
- Into your fcgi-bin directory
- Restart Apache
- Test
Recommended Posts
Why I Love My Job
December 14, 2017
Liberty & Oppression
September 25, 2017
What is a Father?
June 19, 2016