1 // ------------------------------------------------------------------------------------------------
2 //
3 // IMAGE OUTPUT PAGE MANAGEMENT
4 //
5 // This source code is the property of FITS Imaging inc.
6 //
7 // MODULE : PageIVUE
8 // LANGUAGE : C++
9 // AUTHOR : Philippe BOSSUT
10 // DATE : Thursday, December 16th 1993
11 // DESCRIPTION :
12 // COMMENT : This package is a part of the IVUE Toolkit I/O and the FlashPix Baseline I/O Toolkit
13 // SCCSID : @(#)ri_page.cpp 1.4 12:41:25 08 Jul 1997
14 // ------------------------------------------------------------------------------------------------
15 // Copyright (c) 1999 Digital Imaging Group, Inc.
16 // For conditions of distribution and use, see copyright notice
17 // in Flashpix.h
18 // ------------------------------------------------------------------------------------------------
19 #include "ri_page.h"
20 // ------------------------------------------------------------------------------------------------
21
22 // Includes
23 // --------
24
25 #include <stdlib.h>
26
27 #ifndef Memoire_h
28 #include "b_memory.h"
29 #endif
30 #ifndef Numbers_h
31 #include "numbers.h"
32 #endif
33 #ifndef IVUEToolkit_h
34 #include "ri_lib.h"
35 #endif
36 #ifndef AdvancedIVUE_h
37 #include "viewimg.h"
38 #endif
39 #ifndef PHierarchicalImage_h
40 #include "ph_image.h"
41 #endif
42
43 // Constants
44 // ---------
45
46 // Variables
47 // ---------
48
49 // ------------------------------------------------------------------------------------------------
50
51 // ------------------------------------------------------------------------------------------------
52
53 // ------------------------------------------------------------------------------------------------
54 // Internal Functions
55 // ------------------------------------------------------------------------------------------------
56
57 // ------------------------------------------------------------------------------------------------
58 // Methods of the PageImage class
59 // ------------------------------------------------------------------------------------------------
60
PageImage(PRIImage * rawImage,long width,long height,float rotation)61 PageImage::PageImage (PRIImage* rawImage, long width, long height, float rotation)
62
63 {
64 // Set the image pointers first
65 image = new ViewImage (rawImage);
66 if (image==NULL) {
67 return;
68 }
69 this->rawImage = rawImage;
70
71 // Set values
72 pixHeight = height; // height of the page in pixels
73 pixWidth = width; // width of the page in pixels
74 numLine = -1; // first line number set to an invalid value
75 lineSize = 0; // length of each line
76 buffer = NULL; // no buffer allocated...
77 line[0] = NULL; // ...
78 line[1] = NULL; // ...
79 line[2] = NULL; // ...
80 line[3] = NULL; // ...
81 // By default the image covers the page which means that the height of the page is equal to 1.0mm
82 // in the image coordinate system. Thus, the resolution of the page is equal to (height)(pixels)/(1.0)(mm)
83 resolution = (float)(height);
84 xOrigin = (float) 0.0; // the position of the page in the world is on (0,0) by default
85 yOrigin = (float) 0.0;
86
87 // Compute position transformation matrix : Rotate image in page
88 TransfoPerspective position;
89 ComputeRotationMatrix (&position, rotation);
90
91 // Set the view image position
92 image->ApplyTransform(position);
93 }
94
PageImage(PRIImage * rawImage,long width,long height,float r,float x,float y,TransfoPerspective trans)95 PageImage::PageImage (PRIImage* rawImage, long width, long height, float r, float x, float y, TransfoPerspective trans)
96
97 {
98 // Set the image pointers first
99 image = new ViewImage (rawImage);
100 if (image==NULL) {
101 return;
102 }
103 this->rawImage = rawImage;
104
105 // Set values
106 pixHeight = height; // height of the page in pixels
107 pixWidth = width; // width of the page in pixels
108 numLine = -1; // first line number set to an invalid value
109 lineSize = 0; // length of each line
110 buffer = NULL; // no buffer allocated...
111 line[0] = NULL; // ...
112 line[1] = NULL; // ...
113 line[2] = NULL; // ...
114 line[3] = NULL; // ...
115 resolution = r; // Set the resolution of the page in pixels per mm
116 xOrigin = x; // Set the position of the page in the world
117 yOrigin = y;
118
119 // Set the view image position
120 image->ApplyTransform(trans);
121 }
122
PageImage(ViewImage * viewImage,long width,long height,float rotation)123 PageImage::PageImage (ViewImage* viewImage, long width, long height, float rotation)
124
125 {
126 // Set the image pointers first
127 image = new ViewImage (viewImage->GetImage());
128 if (image==NULL) {
129 return;
130 }
131
132 rawImage = viewImage->GetImage();
133
134 // Set values
135 pixHeight = height; // height of the page in pixels
136 pixWidth = width; // width of the page in pixels
137 numLine = -1; // first line number set to an invalid value
138 lineSize = 0; // length of each line
139 buffer = NULL; // no buffer allocated...
140 line[0] = NULL; // ...
141 line[1] = NULL; // ...
142 line[2] = NULL; // ...
143 line[3] = NULL; // ...
144 // By default the image covers the page which means that the height of the page is equal to 1.0mm
145 // in the image coordinate system. Thus, the resolution of the page is equal to (height)(pixels)/(1.0)(mm)
146 resolution = (float)(height);
147 xOrigin = (float) 0.0; // the position of the page in the world is on (0,0) by default
148 yOrigin = (float) 0.0;
149
150 // Compute position transformation matrix : Rotate image in page
151 TransfoPerspective position;
152 ComputeRotationMatrix (&position, rotation);
153
154 // Set the view image position
155 image->ApplyTransform(position);
156 }
157
PageImage(ViewImage * viewImage,long width,long height,float r,float x,float y,TransfoPerspective trans)158 PageImage::PageImage (ViewImage* viewImage, long width, long height, float r, float x, float y, TransfoPerspective trans)
159
160 {
161 // Set the image pointers first
162 image = new ViewImage (viewImage->GetImage());
163 if (image==NULL) {
164 return;
165 }
166
167 rawImage = viewImage->GetImage();
168
169 // Set values
170 pixHeight = height; // height of the page in pixels
171 pixWidth = width; // width of the page in pixels
172 numLine = -1; // first line number set to an invalid value
173 lineSize = 0; // length of each line
174 buffer = NULL; // no buffer allocated...
175 line[0] = NULL; // ...
176 line[1] = NULL; // ...
177 line[2] = NULL; // ...
178 line[3] = NULL; // ...
179 resolution = r; // Set the resolution of the page in pixels per mm
180 xOrigin = x; // Set the position of the page in the world
181 yOrigin = y;
182
183 // Set the view image position
184 image->ApplyTransform(trans);
185 }
186
~PageImage()187 PageImage::~PageImage ()
188
189 {
190 delete image;
191 image = NULL;
192
193 // Free memory buffer
194 if (buffer) {
195 FastDeleteArray(buffer,Pixel);
196 }
197 return;
198 }
199
ComputeRotationMatrix(TransfoPerspective * position,float rotation)200 void PageImage::ComputeRotationMatrix (TransfoPerspective* position, float rotation)
201 {
202 PositionMv pointUV;
203 PositionMv p[4];
204
205 if (rotation) {
206 position->Rotate ((float) 0.0,(float) 0.0, rotation);
207
208 // Inverse position matrix (position is the xy to uv transformation)
209 TransfoPerspective uvToxy (*position);
210 uvToxy.Inverse();
211
212 // Set first corner of image and transform
213 pointUV.h = (float) 0.0;
214 pointUV.v = (float) 0.0;
215 p[0] = uvToxy * pointUV;
216
217 // Set second corner of image and transform
218 pointUV.h = (float)(rawImage->width)/rawImage->resolution;
219 pointUV.v = (float) 0.0;
220 p[1] = uvToxy * pointUV;
221
222 // Set third corner of image and transform
223 pointUV.h = (float)(rawImage->width) /rawImage->resolution;
224 pointUV.v = (float)(rawImage->height)/rawImage->resolution;
225 p[2] = uvToxy * pointUV;
226
227 // Set fourth corner of image and transform
228 pointUV.h = (float) 0.0;
229 pointUV.v = (float)(rawImage->height)/rawImage->resolution;
230 p[3] = uvToxy * pointUV;
231
232 // Compute bounding box :
233 // init min and max values with the first point
234 PositionMv p0 = p[0];
235 PositionMv p1 = p[0];
236
237 // loop to find min and max values in both direction
238 for (short i = 1; i < 4; i++) {
239 if (p[i].h < p0.h) p0.h = p[i].h;
240 if (p[i].v < p0.v) p0.v = p[i].v;
241 if (p[i].h > p1.h) p1.h = p[i].h;
242 if (p[i].v > p1.v) p1.v = p[i].v;
243 }
244
245 // Translate the minimum point of the bounding box to the origin of the page
246 position->Translate (-p0.h, -p0.v);
247
248 // Scale to fit the page size
249 float sh = ((float)(pixWidth)/resolution)/(p1.h - p0.h);
250 float sv = ((float)(pixHeight)/resolution)/(p1.v - p0.v);
251 float sx = MIN (sh,sv);
252 position->Scale ((float) 0.0,(float) 0.0, sx, sx);
253 }
254
255 // Note that virtually, the page is 1 mm high, but it still makes
256 // sense because we dont't care about the real page size in mm...
257
258 }
259
260
261 // Read the entire image page
ReadPage(Pixel * image)262 FPXStatus PageImage::ReadPage (Pixel* image)
263 {
264 Pixel *pt;
265 unsigned char *dest = NULL;
266 FPXStatus status = FPX_OK;
267
268 for (long i = 0; i < pixHeight; i++) {
269 // get line pointer from page (read it in file if necessary)
270 // PTCH_105 - added following code to implement progress callbacks....
271 if ( GtheSystemToolkit->fnctProgFunc)
272 if (GtheSystemToolkit->fnctProgFunc( pixHeight, i))
273 return FPX_USER_ABORT;
274 // PTCH_105 ....end of addition
275
276 if (((pt = ReadLine (i, &status)) == NULL) || (status != FPX_OK)) {
277 break;
278 } else {
279 short plan = GtheSystemToolkit->activeChannel;
280 if ((plan != ActiveChannel_All) && (GtheSystemToolkit->interleaving == Interleaving_Channel)) {
281 // allocate an intermediate buffer
282 if (!dest)
283 FastAllocArray(dest,unsigned char,(unsigned int)(pixWidth));
284 if (dest == NULL) {
285 status = FPX_MEMORY_ALLOCATION_FAILED;
286 break;
287 }
288 // Pixel by pixel if planes specified, the destination contains only the choosed channel
289 register long j;
290 register unsigned char *src, *dst;
291 src = (unsigned char *)(pt) + plan;
292 dst = dest;
293 for (j=0; j<pixWidth;j++,src+=sizeof(Pixel),dst++)
294 *dst = *src;
295 pt = (Pixel*)(dest);
296 } else {
297 // convert according to the interleaving option
298 if (Toolkit_Interleave (pt, pixWidth, 1)) {
299 status = FPX_MEMORY_ALLOCATION_FAILED;
300 break;
301 }
302 }
303 if (Toolkit_CopyInterleaved (image, pixWidth, pixHeight, pt, pixWidth, 1, 0, i)) {
304 status = FPX_MEMORY_ALLOCATION_FAILED;
305 break;
306 }
307 }
308 }
309 FastDeleteArray(dest,unsigned char);
310 return(status);
311 }
312
313
314 // Read a line of the page taking into account all global options
ReadPageLine(long lineNumber,Pixel * pixLine)315 FPXStatus PageImage::ReadPageLine (long lineNumber, Pixel* pixLine)
316 {
317 Pixel *pt;
318 FPXStatus status;
319
320 // get line pointer from page (read it in file if necessary)
321 pt = ReadLine (lineNumber, &status);
322
323 if (pt && (status == FPX_OK)) {
324
325 short plan = GtheSystemToolkit->activeChannel;
326 if ((plan != ActiveChannel_All) && (GtheSystemToolkit->interleaving == Interleaving_Channel)) {
327 // Pixel by pixel if planes specified, the destination contains only the choosen channel
328 register long j;
329 register unsigned char *src, *dst;
330 src = (unsigned char *)(pt) + plan;
331 dst = (unsigned char *)pixLine;
332 for (j=0; j<pixWidth;j++,src+=sizeof(Pixel),dst++)
333 *dst = *src;
334 } else {
335 // copy pixels in pixLine
336 if (plan == ActiveChannel_All) {
337 // Copy pixels to the buffer
338 BlockMove(pt,pixLine,pixWidth*sizeof(Pixel));
339 } else {
340 // Pixel by pixel if planes specified
341 register long j;
342 register unsigned char *src, *dst;
343 src = (unsigned char *)(pt) + plan;
344 dst = (unsigned char *)(pixLine) + plan;
345 for (j=0; j<pixWidth;j++,src+=sizeof(Pixel),dst+=sizeof(Pixel))
346 *dst = *src;
347 }
348 // convert according to the interleaving option
349 if (Toolkit_Interleave (pixLine, pixWidth, 1))
350 status = FPX_MEMORY_ALLOCATION_FAILED;
351 }
352 }
353
354 return(status);
355 }
356
357
358 // Give a pointer on the pixel line
359 // Caution : this function doesn't take interleaving option into account
ReadLine(long lineNumber,FPXStatus * status)360 Pixel* PageImage::ReadLine (long lineNumber, FPXStatus* status)
361 {
362 // test if line has been already read :
363 if ((lineNumber & ~0x3) == numLine) { // previous multiple by 4 of x is : x & ~0x3
364 *status = FPX_OK;
365 return (line[lineNumber & 0x3]); // rest by 4 of x is : x & 0x3
366 }
367
368 long lineLength = (pixWidth + 3) & ~3;
369 // Read 4 lines including the searched one
370 // PTCH_105 - removed non-FlashPix call and disabled progress reporting thru this routine
371 *status = ReadRectangle(0, lineNumber, lineLength, lineNumber+1, NULL, lineLength,
372 PRIImage::readInterpolated, 0);
373
374 // return the buffer pointer to the calling routine
375 return (line[lineNumber & 0x3]); // rest by 4 of x is : x & 0x3
376 }
377
378
379
380 // read a rectangle by samples
381 // bufPix must be allowed before the call
382 // PTCH_105 - added 'reportProgress' argument
ReadRectangle(long left,long top,long right,long bottom,Pixel * bufPix,long bufWidth,Boolean withAntialias,Boolean reportProgress)383 FPXStatus PageImage::ReadRectangle(long left, long top, long right, long bottom, Pixel* bufPix,
384 long bufWidth, Boolean withAntialias, Boolean reportProgress)
385 {
386 Pixel pix[16];
387 Pixel pixEmpty[16];
388 Pixel *dest;
389 long i;
390 long j;
391 FPXStatus status = FPX_OK;
392 const long left4 = left & ~3; // 'left' aligned to a multiple of 4
393
394 // Allocate buffer if necessary
395 long lineLength = ((right+3) & ~3) - left4;
396 if (!buffer || (lineSize != lineLength)) {
397 if (buffer)
398 FastDeleteArray(buffer, Pixel);
399 FastAllocArray(buffer,Pixel,4*lineLength); // size of the buffer : 4 full lines
400 if ( buffer == NULL)
401 return FPX_MEMORY_ALLOCATION_FAILED;
402 line[0] = buffer;
403 line[1] = line[0] + lineLength;
404 line[2] = line[1] + lineLength;
405 line[3] = line[2] + lineLength;
406 lineSize = lineLength;
407 numLine = -1;
408 }
409 long line3 = lineSize*2;
410 long line4 = lineSize*3;
411
412 // Set the antialiasing
413 Boolean oldMode = PRIImage::readInterpolated;
414 if (withAntialias)
415 PRIImage::readInterpolated = true;
416
417 // Initialize pixEmpty with the backGround
418 for (i = 0 ; i < 16 ; i++)
419 pixEmpty[i] = GtheSystemToolkit->backgroundColor;
420
421 float xOrigin05 = (float) (xOrigin + 0.5/resolution);
422 float yOrigin05 = (float) (yOrigin + 0.5/resolution);
423
424 for (j = top; j < bottom; j ++) {
425 // PTCH_105 added following to implement progress callbacks....
426 if ( reportProgress && GtheSystemToolkit->fnctProgFunc)
427 if (GtheSystemToolkit->fnctProgFunc( bottom - top, j - top))
428 return FPX_USER_ABORT;
429 // PTCH_105 ....end of addition
430
431 if (((j & ~0x3) != numLine) || (j == top)) {
432 FPXStatus readStatus; // CHG_FILE_ERR - used to save intermediate error
433 numLine = j & ~0x3;
434
435 dest = buffer;
436 for (i = left4 ; i < right; i += 4) {
437 // Erase the pix buffer with the background
438 memcpy (pix, pixEmpty, (unsigned int)(16*sizeof(Pixel)));
439
440 // Read a sample
441 float x0 = (float)(i) /resolution + xOrigin05;
442 float x1 = (float)(i+4)/resolution + xOrigin05;
443 float y0 = (float)(numLine) /resolution + yOrigin05;
444 float y1 = (float)(numLine+4)/resolution + yOrigin05;
445 if((readStatus = image->Read4x4Points (x0, y0, x1, y1, pix))) // CHG_FILE_ERR - if error
446 status = readStatus; // then copy it to 'status'
447 BlockMove(pix,dest,4*sizeof(Pixel));
448 BlockMove(pix+4,dest+lineSize,4*sizeof(Pixel));
449 BlockMove(pix+8,dest+line3,4*sizeof(Pixel));
450 BlockMove(pix+12,dest+line4,4*sizeof(Pixel));
451 dest+=4;
452 }
453 }
454 if (bufPix) {
455 dest = bufPix + ((j-top)*bufWidth);
456 BlockMove(line[j & 0x3]+(left & 0x3),dest,(right-left)*sizeof(Pixel));
457 }
458 }
459
460 // reset antialiasing
461 PRIImage::readInterpolated = oldMode;
462
463 return status;
464 }
465
466