1 #include <stdio.h>
2 //#include <jpeglib.h>
3 //#define __NO_SYSTEM__
4 #include "filter.h"
5 #include "metadata.h"
6 #include "file.h"
7
8 #include "jpegicc.h"
9
10
writeJPEG(Image * im,fullPath * sfile,int quality,int progressive)11 int writeJPEG(Image * im, fullPath * sfile, int quality, int progressive)
12 {
13 struct jpeg_compress_struct cinfo;
14 struct jpeg_error_mgr jerr;
15 FILE *outfile;
16 char filename[512];
17 int scanlines_written;
18 unsigned char *data, *buf;
19
20 #ifdef __Mac__
21 unsigned char the_pcUnixFilePath[512]; // added by Kekus Digital
22 Str255 the_cString;
23 Boolean the_bReturnValue;
24 CFStringRef the_FilePath;
25 CFURLRef the_Url; //till here
26 #endif
27
28 cinfo.err = jpeg_std_error(&jerr);
29 jpeg_create_compress(&cinfo);
30
31 if (GetFullPath(sfile, filename))
32 return -1;
33
34 #ifdef __Mac__
35 CopyCStringToPascal(filename, the_cString); //Added by Kekus Digital
36 the_FilePath =
37 CFStringCreateWithPascalString(kCFAllocatorDefault, the_cString,
38 kCFStringEncodingUTF8);
39 the_Url =
40 CFURLCreateWithFileSystemPath(kCFAllocatorDefault, the_FilePath,
41 kCFURLHFSPathStyle, false);
42 the_bReturnValue =
43 CFURLGetFileSystemRepresentation(the_Url, true, the_pcUnixFilePath,
44 512);
45
46 strcpy(filename, the_pcUnixFilePath); //till here
47 #endif
48
49 if ((outfile = fopen(filename, "wb")) == NULL)
50 {
51 PrintError("can't open %s", filename);
52 return -1;
53 }
54 TwoToOneByte(im);
55
56 jpeg_stdio_dest(&cinfo, outfile);
57
58
59
60 cinfo.image_width = im->width; /* image width and height, in pixels */
61 cinfo.image_height = im->height;
62 cinfo.input_components = 3; /* # of color components per pixel */
63 cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
64
65 jpeg_set_defaults(&cinfo);
66
67 if (2 != (progressive & 2))
68 cinfo.optimize_coding = TRUE;
69
70 jpeg_set_quality(&cinfo, quality, TRUE);
71
72 if (1 == (progressive & 1))
73 jpeg_simple_progression(&cinfo);
74
75
76 jpeg_start_compress(&cinfo, TRUE);
77
78 // Write ICC Profile if it exists
79
80 if (im->metadata.iccProfile.size > 0) {
81 jpegICCWriteProfile(&cinfo,
82 (JOCTET *)im->metadata.iccProfile.data,
83 im->metadata.iccProfile.size);
84 }
85
86 scanlines_written = 0;
87 data = *(im->data);
88 buf = (unsigned char *) malloc((size_t) im->bytesPerLine);
89 if (buf == NULL)
90 {
91
92 PrintError("Not enough memory");
93 fclose(outfile);
94 return -1;
95 }
96
97
98 while (scanlines_written < im->height)
99 {
100 memcpy(buf, data, (size_t) im->bytesPerLine);
101 if (im->bitsPerPixel == 32) // Convert 4->3 samples
102 {
103 int x;
104 unsigned char *c1 = buf, *c2 = buf;
105 for (x = 0; x < im->width; x++)
106 {
107 c2++;
108 *c1++ = *c2++;
109 *c1++ = *c2++;
110 *c1++ = *c2++;
111 }
112
113 }
114
115 if (jpeg_write_scanlines(&cinfo, (JSAMPARRAY) & buf, 1))
116 {
117 scanlines_written++;
118 data += im->bytesPerLine;
119 }
120 }
121 jpeg_finish_compress(&cinfo);
122 jpeg_destroy_compress(&cinfo);
123 fclose(outfile);
124 free(buf);
125 return 0;
126
127
128 }
129
130
readJPEG(Image * im,fullPath * sfile)131 int readJPEG(Image * im, fullPath * sfile)
132 {
133 struct jpeg_decompress_struct cinfo;
134 struct jpeg_error_mgr jerr;
135 FILE *infile;
136 char filename[256];
137 int scan_lines_to_be_read, scan_lines_read;
138 unsigned int i, scanheight;
139 unsigned char *data;
140 JSAMPARRAY sarray;
141 JOCTET *ptr = NULL;
142 unsigned int size = 0;
143
144
145
146 #ifdef __Mac__
147 unsigned char the_pcUnixFilePath[256]; // added by Kekus Digital
148 Str255 the_cString;
149 Boolean the_bReturnValue;
150 CFStringRef the_FilePath;
151 CFURLRef the_Url; //till here
152 #endif
153
154 //PrintError("%s", sfile->name);
155
156 cinfo.err = jpeg_std_error(&jerr);
157 jpeg_create_decompress(&cinfo);
158
159 // Prepare the library for reading the ICC profile, see its source code
160 // for further information
161 jpegICCSetupReadICCProfile(&cinfo);
162
163 if (GetFullPath(sfile, filename))
164 return -1;
165
166 #ifdef __Mac__
167 CopyCStringToPascal(filename, the_cString); //Added by Kekus Digital
168 the_FilePath =
169 CFStringCreateWithPascalString(kCFAllocatorDefault, the_cString,
170 kCFStringEncodingUTF8);
171 the_Url =
172 CFURLCreateWithFileSystemPath(kCFAllocatorDefault, the_FilePath,
173 kCFURLHFSPathStyle, false);
174 the_bReturnValue =
175 CFURLGetFileSystemRepresentation(the_Url, true, the_pcUnixFilePath,
176 256);
177
178 strcpy(filename, the_pcUnixFilePath); //till here
179 #endif
180
181 if ((infile = fopen(filename, "rb")) == NULL) {
182 PrintError("can't open %s", filename);
183 return -1;
184 }
185
186 jpeg_stdio_src(&cinfo, infile);
187
188 jpeg_read_header(&cinfo, TRUE);
189
190 jpeg_start_decompress(&cinfo);
191
192 SetImageDefaults(im);
193 im->width = cinfo.output_width;
194 im->height = cinfo.output_height;
195 if (cinfo.output_components != 3)
196 {
197 PrintError("Image must be rgb");
198 fclose(infile);
199 return -1;
200 }
201
202
203 im->bitsPerPixel = 24;
204 im->bytesPerLine = im->width * 3;
205 im->dataSize = im->width * 4 * im->height;
206 im->data = (unsigned char **) mymalloc((size_t) im->dataSize);
207 if (im->data == NULL)
208 {
209 PrintError("Not enough memory");
210 fclose(infile);
211 return -1;
212 }
213
214 scanheight = cinfo.rec_outbuf_height;
215 sarray = (JSAMPARRAY) malloc(scanheight * sizeof(JSAMPROW));
216
217 scan_lines_to_be_read = im->height;
218 data = *(im->data);
219
220 while (scan_lines_to_be_read)
221 {
222 for (i = 0; i < scanheight; i++)
223 {
224 sarray[i] = (JSAMPROW) (data + i * im->bytesPerLine);
225 }
226
227 scan_lines_read = jpeg_read_scanlines(&cinfo, sarray, scanheight);
228
229 scan_lines_to_be_read -= scan_lines_read;
230 data += scan_lines_read * im->bytesPerLine;
231 }
232
233 // read ICC profile
234
235 if (jpegICCReadProfile(&cinfo, &ptr, &size)) {
236
237 im->metadata.iccProfile.size = size;
238 im->metadata.iccProfile.data = (char*) ptr;
239 }
240
241 jpeg_finish_decompress(&cinfo);
242 jpeg_destroy_decompress(&cinfo);
243
244 ThreeToFourBPP(im);
245 free(sarray);
246
247
248 fclose(infile);
249
250 return 0;
251
252
253 }
254
255 // this function is very likely to change
256 // so it should be considered a hack until
257 // we are able to read all the JPEG metadata
258
panoJPEGRead(Image * im,fullPath * sfile)259 int panoJPEGRead(Image * im, fullPath * sfile)
260 {
261 if ( readJPEG(im, sfile) == 0) {
262 return panoMetadataUpdateFromImage(im);
263 } else
264 return FALSE;
265
266
267 }
268