1 /*************************************************************
2 Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved.
3 PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research
4 Group. If you use this software, you agree to the following: This
5 program package is purely experimental, and is licensed "as is".
6 Permission is granted to use, modify, and distribute this program
7 without charge for any purpose, provided this license/ disclaimer
8 notice appears in the copies. No warranty or maintenance is given,
9 either expressed or implied. In no event shall the author(s) be
10 liable to you or a third party for any special, incidental,
11 consequential, or other damages, arising out of the use or inability
12 to use the program for any purpose (or the loss of data), even if we
13 have been advised of such possibilities. Any public reference or
14 advertisement of this source code should refer to it as the Portable
15 Video Research Group (PVRG) code, and not by any author(s) (or
16 Stanford University) name.
17 *************************************************************/
18 /*
19 ************************************************************
20 io.c
21
22 This package is used to manipulate the raw image files.
23
24 There are two standards: block based, assumed to be in sizes of the
25 DCT block, herein defined as BlockWidth and BlockHeight; and a special
26 case, two-line-based, assumed to be of two lines per.
27
28 ************************************************************
29 */
30
31 /*LABEL io.c */
32
33 /* Include definitions. */
34 #include "globals.h"
35 #ifdef SYSV
36 #include <sys/fcntl.h>
37 #include <sys/unistd.h>
38 #endif
39 #include <stdlib.h> /* malloc */
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <fcntl.h>
43 #include <string.h> /* memcpy */
44 #include <assert.h> /* memcpy */
45 #ifdef WIN32
46 #include <io.h> /* lseek on win32 */
47 #endif
48
49
50 /* Functions which are local and which are exported. */
51
52 /*PUBLIC*/
53
54 static BUFFER *MakeXBuffer();
55 static void WriteXBuffer();
56 static void ReadXBuffer();
57 static void ReadResizeBuffer();
58 static void FlushBuffer();
59 static void BlockMoveTo();
60 static void ReadXBound();
61 static void WriteXBound();
62
63 static void LineMoveTo();
64
65 extern void ReadBlock();
66 extern void WriteBlock();
67 extern void ResizeIob();
68 extern void RewindIob();
69 extern void FlushIob();
70 extern void SeekEndIob();
71 extern void CloseIob();
72 extern void MakeIob();
73 extern void PrintIob();
74 extern void InstallIob();
75 extern void TerminateFile();
76
77 extern void ReadLine();
78 extern void ReadPreambleLine();
79 extern void WriteLine();
80 extern void LineResetBuffers();
81
82
83 /*PRIVATE*/
84
85 /* External variables */
86 extern int Loud;
87 extern int PointTransform; /* Used for shifting the pels from the I/O */
88 extern IMAGE *CImage;
89 extern FRAME *CFrame;
90 extern SCAN *CScan;
91
92 /* Internal variables. */
93 static IOBUF *Iob=NULL; /* Internal I/O buffer. */
94 static int BlockWidth = BLOCKWIDTH; /* Block width. */
95 static int BlockHeight = BLOCKHEIGHT; /* Block height. */
96
97 /* Buffer calculation information */
98
99 #define BufferIndex(i,iobuf) (iobuf)->blist[(i)]
100 #define TrueBufferPos(buffer) (((buffer)->currentoffs - \
101 ((buffer)->tptr - (buffer)->bptr))/buffer->wsize)
102
103
104 /*START*/
105 /*BFUNC
106
107 MakeXBuffer() constructs a holding buffer for the stream input. It
108 takes up a size passed into it and returns the appropriate buffer
109 structure.
110
111 EFUNC*/
112
MakeXBuffer(nelem,wsize)113 static BUFFER *MakeXBuffer(nelem,wsize)
114 int nelem;
115 int wsize;
116 {
117 BEGIN("MakeXBuffer")
118 BUFFER *temp;
119
120 if (!(temp = MakeStructure(BUFFER))) /* Make structure */
121 {
122 WHEREAMI();
123 printf("Cannot allocate buffer structure.\n");
124 exit(ERROR_MEMORY);
125 }
126 temp->disable=0; /* Not disabled */
127 temp->wsize = wsize; /* Set up word size */
128 temp->size=nelem*wsize; /* Set up size, offset */
129 temp->currentoffs = 0;
130 temp->streamoffs = 0;
131 if (!(temp->space =(unsigned char *) /* Allocate buffer space */
132 calloc(temp->size+1,sizeof(unsigned char))))
133 {
134 WHEREAMI();
135 printf("Cannot allocate buffer memory.\n");
136 exit(ERROR_MEMORY);
137 }
138 temp->tptr = temp->bptr = temp->space;
139 return(temp);
140 }
141
142 /*BFUNC
143
144 ResizeIob() is used to resize the Iob height and width to conform to
145 that of the CScan. This is used for the dynamic Number-of-lines
146 rescaling.
147
148 EFUNC*/
149
ResizeIob()150 void ResizeIob()
151 {
152 BEGIN("ResizeIob")
153 int index;
154
155 for(index=0;index<CScan->NumberComponents;index++)
156 {
157 CScan->Iob[index]->width = CFrame->Width[CScan->ci[index]];
158 CScan->Iob[index]->height = CFrame->Height[CScan->ci[index]];
159 }
160 }
161
162 /*BFUNC
163
164 MakeIob() is used to create an Iob structure for use in the CScan
165 structure. An Iob consists of several Buffer structures with some
166 additional sizing information. The input flags set up the parameters
167 of the stream.
168
169 EFUNC*/
170
MakeIob(type,flags,wsize)171 void MakeIob(type,flags,wsize)
172 int type;
173 int flags;
174 int wsize;
175 {
176 BEGIN("MakeIob")
177 int index,sofs;
178 BUFFER **current;
179 IOBUF *temp;
180
181 for(index=0;index<CScan->NumberComponents;index++) /* Make IOBUF */
182 { /* For each component */
183 if (!(temp = MakeStructure(IOBUF)))
184 {
185 WHEREAMI();
186 printf("Cannot allocate IOBUF structure.\n");
187 exit(ERROR_MEMORY);
188 }
189 temp->linelastdefault=(1<<(CFrame->DataPrecision-PointTransform-1));
190 temp->type = type;
191 temp->wsize = wsize;
192 temp->hpos=0;
193 temp->vpos=0;
194 temp->width = CFrame->Width[CScan->ci[index]]; /* Set up widthxheight */
195 temp->height = CFrame->Height[CScan->ci[index]];
196 if (CScan->NumberComponents==1)
197 {
198 temp->hor = 1; /* For non-interleaved mode the freq */
199 temp->ver = 1; /* is always 1x1 */
200 }
201 else
202 {
203 temp->hor = CFrame->hf[CScan->ci[index]]; /* and hf x vf */
204 temp->ver = CFrame->vf[CScan->ci[index]];
205 }
206 switch(temp->type)
207 {
208 case IOB_BLOCK: /* BLOCK TYPE */
209 temp->num = temp->ver*BlockHeight;
210 break;
211 case IOB_LINE: /* LINE TYPE */
212 temp->num = temp->ver + 1;
213 break;
214 default:
215 WHEREAMI();
216 printf("Illegal type specified: %d.\n",type);
217 exit(ERROR_BOUNDS);
218 }
219 temp->flags = flags; /* and also flags */
220 if (!(temp->blist = /*Set up buffer list */
221 (BUFFER **) calloc(temp->num,sizeof(BUFFER *))))
222 {
223 WHEREAMI();
224 printf("Cannot allocate Iob bufferlist.\n");
225 exit(ERROR_MEMORY);
226 }
227 if( CFrame->tmpfile )
228 {
229 temp->file = CFrame->tmpfile;
230 }
231 else
232 {
233 if ((temp->file = /* Open file */
234 open(CFrame->ComponentFileName[CScan->ci[index]],
235 flags,UMASK)) < 0)
236 {
237 WHEREAMI();
238 printf("Cannot open file %s.\n",
239 CFrame->ComponentFileName[CScan->ci[index]]);
240 exit(ERROR_INIT_FILE);
241 } /* Make buffer for every line of component in MDU */
242 }
243
244 for(sofs=0,current=temp->blist;current<temp->blist+temp->num;current++)
245 {
246 *current = MakeXBuffer(CFrame->BufferSize, wsize);
247 (*current)->streamoffs = sofs;
248 (*current)->iob = temp;
249 (*current)->data_linelast = temp->linelastdefault;
250 if (!temp->height || (current - temp->blist) < temp->height-1)
251 {
252 sofs += CFrame->Width[CScan->ci[index]]*wsize;
253 }
254 }
255 CScan->Iob[index] = temp;
256 }
257 }
258
259 /*BFUNC
260
261 PrintIob() is used to print the current input buffer to the stdio
262 stream.
263
264 EFUNC*/
265
PrintIob()266 void PrintIob()
267 {
268 BEGIN("PrintIob")
269
270 if (Iob)
271 {
272 printf("*** Iob ID: %p ***\n",(void*)Iob);
273 printf("Number of Buffers: %d Width: %d Height: %d\n",
274 Iob->num,Iob->width,Iob->height);
275 printf("hpos: %d vpos: %d hor-freq: %d ver-freq: %d\n",
276 Iob->hpos,Iob->vpos,Iob->hor,Iob->ver);
277 printf("filed: %d flags: %d BufferListId: %p\n",
278 Iob->file,Iob->flags,(void*)Iob->blist);
279 }
280 else
281 {
282 printf("*** Iob ID: NULL ***\n");
283 }
284 }
285
286 /*BFUNC
287
288 WriteXBuffer() writes out len elements from storage out to the buffer
289 structure specified. This is can result in a multiple of len bytes
290 being written out depending on the element structure.
291
292 EFUNC*/
293
WriteXBuffer(len,storage,buffer)294 static void WriteXBuffer(len,storage,buffer)
295 int len;
296 int *storage;
297 BUFFER *buffer;
298 {
299 BEGIN("WriteXBuffer")
300 int diff,wout;
301
302 if (buffer->disable)
303 {
304 WHEREAMI();
305 printf("Attempting to write to disabled buffer!\n");
306 }
307 /* printf("Writing:%d bytes\n",len);*/
308 diff = buffer->size - (buffer->bptr - buffer->space); /* Find room left */
309 diff = diff/buffer->wsize; /* Scale by element # */
310 if(len > diff)
311 { /* Put as many elems in */
312 WriteXBuffer(diff,storage,buffer); /* If no room, then flush current */
313 FlushBuffer(buffer); /* buffer out to disk */
314 len -= diff;
315 storage += diff;
316 }
317 switch(buffer->wsize) /* Because of compatibility differences between */
318 { /* UNIX implementations, we are forced to do this */
319 case 1: /* explicit ordering of bytes... */
320 while(len--) /* Write the rest of the buffer out to the disk */
321 {
322 wout = *(storage++)<<PointTransform;
323 *(buffer->bptr++) = (unsigned char) wout;
324 }
325 break;
326 case 2:
327 while(len--) /* Write the rest of the buffer out to the disk */
328 {
329 wout = *(storage++)<<PointTransform;
330 *(buffer->bptr++) = (unsigned char) (wout>>8)&0xff;
331 *(buffer->bptr++) = (unsigned char) wout&0xff;
332 }
333 break;
334 case 3:
335 while(len--) /* Write the rest of the buffer out to the disk */
336 {
337 wout = *(storage++)<<PointTransform;
338 *(buffer->bptr++) = (unsigned char) (wout>>16)&0xff;
339 *(buffer->bptr++) = (unsigned char) (wout>>8)&0xff;
340 *(buffer->bptr++) = (unsigned char) wout&0xff;
341 }
342 break;
343 case 4:
344 while(len--) /* Write the rest of the buffer out to the disk */
345 {
346 wout = *(storage++)<<PointTransform;
347 *(buffer->bptr++) = (unsigned char) (wout>>24)&0xff;
348 *(buffer->bptr++) = (unsigned char) (wout>>16)&0xff;
349 *(buffer->bptr++) = (unsigned char) (wout>>8)&0xff;
350 *(buffer->bptr++) = (unsigned char) wout&0xff;
351 }
352 break;
353 default:
354 WHEREAMI();
355 printf("Illegal word size in characters %d.\n",buffer->wsize);
356 exit(ERROR_BOUNDS);
357 break;
358 }
359 }
360
361 /*BFUNC
362
363 ReadXBuffer() is fetches len amount of elements into storage from the
364 buffer structure. This may actually amount to an arbitrary number of
365 characters depending on the word size.
366
367 EFUNC*/
368
ReadXBuffer(len,storage,buffer)369 static void ReadXBuffer(len,storage,buffer)
370 int len;
371 int *storage;
372 BUFFER *buffer;
373 {
374 BEGIN("ReadXBuffer")
375 int i,numchars,maxelem,rin;
376
377 if (buffer->disable)
378 {
379 for(i=0;i<len;i++) *(storage++)=buffer->data_linelast;
380 return;
381 }
382
383 numchars = len*buffer->wsize;
384 /* The following command recurses because */
385 /* it's slightly more efficient that way */
386 /* when the probability of recursion is */
387 /* negligible. */
388 while (numchars > buffer->size) /* We ask more than the buffer can handle */
389 { /* Inefficient for small buffer sizes */
390 maxelem = buffer->size/buffer->wsize;
391 ReadXBuffer(maxelem, storage, buffer); /* Split up into several reads */
392 storage += maxelem;
393 len -= maxelem;
394 numchars -= maxelem*buffer->wsize;
395 }
396 if(numchars > (buffer->tptr - buffer->bptr)) /* If we request > bytes */
397 ReadResizeBuffer(numchars,buffer); /* Read those bytes in */
398 switch(buffer->wsize) /* Again, explicit input of bytes */
399 {
400 case 1:
401 while(len--) /* Now copy over to storage */
402 {
403 rin = (int) *(buffer->bptr++);
404 *(storage++) = rin >> PointTransform;
405 }
406 break;
407 case 2:
408 while(len--) /* Now copy over to storage */
409 {
410 rin = (((int)*(buffer->bptr++))<<8);
411 rin |= *(buffer->bptr++);
412 *(storage++) = rin >> PointTransform;
413 }
414 break;
415 case 3:
416 while(len--) /* Now copy over to storage */
417 {
418 rin = (((int)*(buffer->bptr++))<<16);
419 rin |= (((int)*(buffer->bptr++))<<8);
420 rin |= (*(buffer->bptr++));
421 *(storage++) = rin >> PointTransform;
422 }
423 break;
424 case 4:
425 while(len--) /* Now copy over to storage */
426 {
427 rin = (((int)*(buffer->bptr++))<<24);
428 rin |= (((int)*(buffer->bptr++))<<16);
429 rin |= (((int)*(buffer->bptr++))<<8);
430 rin |= (*(buffer->bptr++));
431 *(storage++) = rin >> PointTransform;
432 }
433 break;
434 default:
435 WHEREAMI();
436 printf("Illegal word size in characters %d.\n",buffer->wsize);
437 exit(ERROR_BOUNDS);
438 break;
439 }
440 #ifdef IO_DEBUG
441 WHEREAMI();
442 printf("last read: %d",*(storage-1));
443 printf("\n");
444 #endif
445 }
446
447 /*BFUNC
448
449 ReadResizeBuffer() reads len bytes from the stream and puts it
450 into the buffer.
451
452 EFUNC*/
453
ReadResizeBuffer(len,buffer)454 static void ReadResizeBuffer(len,buffer)
455 int len;
456 BUFFER *buffer;
457 {
458 BEGIN("ReadResizeBuffer")
459 int retval,diff,location,amount;
460
461 diff = buffer->tptr - buffer->bptr; /* Find out the current usage */
462 if (len > buffer->size-1) /* calculate if we can hold it */
463 {
464 WHEREAMI();
465 printf("Length Request Too Large.\n");
466 exit(ERROR_PARAMETER);
467 }
468 #ifdef IO_DEBUG
469 printf("SPACE: %x BPTR: %x DIFF: %d\n",buffer->space,buffer->bptr,diff);
470 printf("ReadLseek %d\n",buffer->streamoffs+buffer->currentoffs);
471 #endif
472 assert( diff >= 0 );
473 memcpy(buffer->space,buffer->bptr,diff); /* Move buffer down. */
474 buffer->bptr = buffer->space; /* Reset pointers. */
475 buffer->tptr = buffer->space + diff;
476
477 location = buffer->streamoffs+buffer->currentoffs;
478 amount = buffer->size-(buffer->tptr - buffer->space);
479 lseek(buffer->iob->file,location,SEEK_SET);
480 #ifdef IO_DEBUG
481 printf("Read: Filed %d Buf: %x NBytes: %d\n",
482 buffer->iob->file,buffer->tptr,amount);
483 #endif
484 if ((retval = read(buffer->iob->file, /* Do the read */
485 buffer->tptr,
486 amount)) < 0)
487 {
488 WHEREAMI();
489 printf("Cannot Resize.\n");
490 exit(ERROR_READ);
491 }
492 #ifdef IO_DEBUG
493 printf("ReadReturn numbytes %d\n",retval);
494 #endif
495 buffer->tptr += retval; /* Alter pointers */
496 buffer->currentoffs += retval;
497 }
498
499 /*BFUNC
500
501 FlushBuffer() saves the rest of the bytes in the buffer out to the
502 disk.
503
504 EFUNC*/
505
FlushBuffer(buffer)506 static void FlushBuffer(buffer)
507 BUFFER *buffer;
508 {
509 BEGIN("FlushBuffer")
510 int retval;
511
512 #ifdef IO_DEBUG
513 printf("WriteLseek %d\n",buffer->streamoffs+buffer->currentoffs);
514 #endif
515 lseek(buffer->iob->file,buffer->streamoffs+buffer->currentoffs,SEEK_SET);
516 if ((retval = write(buffer->iob->file,
517 buffer->space,
518 (buffer->bptr - buffer->space))) < 0)
519 {
520 WHEREAMI();
521 printf("Cannot flush buffer.\n");
522 exit(ERROR_WRITE);
523 }
524 buffer->currentoffs += (buffer->bptr - buffer->space);
525 buffer->bptr = buffer->space;
526 }
527
528 /*BFUNC
529
530 ReadBlock() is used to get a block from the current Iob. This function
531 returns (for the JPEG case) 64 bytes in the store integer array. It
532 is stored in row-major form; that is, the row index changes least
533 rapidly.
534
535 EFUNC*/
536
ReadBlock(store)537 void ReadBlock(store)
538 int *store;
539 {
540 BEGIN("ReadBlock")
541 int i,voffs;
542
543 voffs = (Iob->vpos % Iob->ver)*BlockHeight; /* Find current v offset*/
544 #ifdef IO_DEBUG
545 for(i=0;i<BlockHeight;i++)
546 {
547 printf("%d Iob %x\n",i,Iob->blist[i]->Iob);
548 }
549 #endif
550 for(i=voffs;i<voffs+BlockHeight;i++) /* Use voffs to index into */
551 { /* Buffer list of IOB */
552 #ifdef IO_DEBUG
553 printf("%d Iob %x\n",i,Iob->blist[i]->Iob);
554 #endif
555 ReadXBound(BlockWidth,store,Iob->blist[i]); /* get blockwidth elms */
556 store+=BlockWidth; /* Storage array & increment */
557 } /* by blockwidth */
558 if ((++Iob->hpos % Iob->hor)==0) /* Increment MDU block pos */
559 {
560 if ((++Iob->vpos % Iob->ver) == 0)
561 {
562 if (Iob->hpos < CScan->MDUWide*Iob->hor)
563 {
564 Iob->vpos -= Iob->ver;
565 }
566 else
567 {
568 Iob->hpos = 0; /* If at end of raster width*/
569 BlockMoveTo(); /* Reload buffers from start */
570 } /* of next line. */
571 }
572 else
573 {
574 Iob->hpos -= Iob->hor;
575 }
576 }
577 }
578
579 /*BFUNC
580
581 WriteBlock() writes an array of data in the integer array pointed to
582 by store out to the driver specified by the IOB. The integer array is
583 stored in row-major form, that is, the first row of (8) elements, the
584 second row of (8) elements....
585
586 EFUNC*/
587
WriteBlock(store)588 void WriteBlock(store)
589 int *store;
590 {
591 BEGIN("WriteBlock")
592 int i,voffs;
593
594 voffs = (Iob->vpos % Iob->ver)*BlockHeight; /* Find vertical buffer offs. */
595 for(i=voffs;i<voffs+BlockHeight;i++)
596 {
597 if (!Iob->height || (((Iob->vpos/Iob->ver)*BlockHeight + i) <
598 Iob->height))
599 {
600 WriteXBound(BlockWidth,store,Iob->blist[i]); /* write Block elms */
601 store+=BlockWidth; /* Iob indexed by offset */
602 }
603 }
604 if ((++Iob->hpos % Iob->hor)==0) /* Increment block position */
605 { /* in MDU. */
606 if ((++Iob->vpos % Iob->ver) == 0)
607 {
608 if (Iob->hpos < CScan->MDUWide*Iob->hor)
609 {
610 Iob->vpos -= Iob->ver;
611 }
612 else
613 {
614 Iob->hpos = 0; /* If at end of image (width) */
615 FlushIob(); /* Flush current IOB and */
616 BlockMoveTo(); /* Move to next lower MDU line */
617 }
618 }
619 else
620 {
621 Iob->hpos -= Iob->hor;
622 }
623 }
624 }
625
626
627 /*BFUNC
628
629 BlockMoveTo() is used to move to a specific vertical and horizontal
630 location (block wise) specified by the current Iob. That means you set
631 the current Iob parameters and then call BlockMoveTo().
632
633 EFUNC*/
634
BlockMoveTo()635 static void BlockMoveTo()
636 {
637 BEGIN("BlockMoveTo")
638 int i,vertical,horizontal;
639
640 if (Loud > MUTE)
641 {
642 WHEREAMI();
643 printf("%p Moving To [Horizontal:Vertical] [%d:%d] \n",
644 (void*)Iob,Iob->hpos,Iob->vpos);
645 }
646 horizontal = Iob->hpos * BlockWidth; /* Calculate actual */
647 vertical = Iob->vpos * BlockHeight; /* Pixel position */
648 for(i=0;i<Iob->ver*BlockHeight;i++)
649 {
650 if (Iob->height)
651 {
652 vertical =
653 ((vertical < Iob->height) ?
654 vertical : Iob->height-1);
655 }
656 Iob->blist[i]->tptr = /* Reset pointer space */
657 Iob->blist[i]->bptr = /* To show no contents */
658 Iob->blist[i]->space;
659 Iob->blist[i]->currentoffs = horizontal* Iob->wsize;/* reset h offset */
660 Iob->blist[i]->streamoffs = vertical * Iob->width *
661 Iob->wsize; /* Reset v offset */
662 vertical++;
663 }
664 }
665
666 /*BFUNC
667
668 RewindIob() brings all the pointers to the start of the file. The reset
669 does not flush the buffers if writing.
670
671 EFUNC*/
672
RewindIob()673 void RewindIob()
674 {
675 BEGIN("RewindIob")
676 int i;
677
678 switch(Iob->type)
679 {
680 case IOB_BLOCK:
681 BlockWidth = BLOCKWIDTH; /* Block width. */
682 BlockHeight = BLOCKHEIGHT; /* Block height. */
683 for(i=0;i<Iob->ver*BlockHeight;i++)
684 {
685 Iob->blist[i]->tptr =
686 Iob->blist[i]->bptr =
687 Iob->blist[i]->space;
688 Iob->blist[i]->currentoffs = 0;
689 Iob->blist[i]->streamoffs = i * Iob->width * Iob->wsize;
690 }
691 Iob->hpos = Iob->vpos = 0;
692 break;
693 case IOB_LINE:
694 Iob->linelastdefault=(1<<(CFrame->DataPrecision-PointTransform-1));
695 for(i= 0;i<Iob->ver+1;i++)
696 {
697 Iob->blist[i]->tptr =
698 Iob->blist[i]->bptr =
699 Iob->blist[i]->space;
700 Iob->blist[i]->currentoffs = 0;
701 if (!i)
702 {
703 Iob->blist[i]->streamoffs = 0;
704 Iob->blist[i]->disable=1;
705 }
706 else
707 {
708 Iob->blist[i]->streamoffs = (i-1) * Iob->width * Iob->wsize;
709 Iob->blist[i]->disable=0;
710 }
711 Iob->blist[i]->data_linelast = Iob->linelastdefault;
712 }
713 Iob->hpos = 0;
714 Iob->vpos = -1;
715 break;
716 default:
717 WHEREAMI();
718 printf("Bad IOB type: %d\n",Iob->type);
719 break;
720 }
721 }
722
723 /*BFUNC
724
725 FlushIob() is used to flush all the buffers in the current Iob. This
726 is done at the conclusion of a write on the current buffers.
727
728 EFUNC*/
729
FlushIob()730 void FlushIob()
731 {
732 BEGIN("FlushIob")
733 int i;
734
735 if (Loud > MUTE)
736 printf("IOB: %p Flushing buffers\n",(void*)Iob);
737 switch(Iob->type)
738 {
739 case IOB_BLOCK:
740 for(i=0;i<Iob->ver*BlockHeight;i++)
741 FlushBuffer(Iob->blist[i]);
742 break;
743 case IOB_LINE:
744 Iob->blist[0]->data_linelast=Iob->linelastdefault;
745 for(i=1;i<Iob->ver+1;i++)
746 {
747 Iob->blist[i]->data_linelast=Iob->linelastdefault;
748 FlushBuffer(Iob->blist[i]);
749 }
750 break;
751 default:
752 WHEREAMI();
753 printf("Illegal IOB type: %d.\n",Iob->type);
754 break;
755 }
756 }
757
758 /*BFUNC
759
760 SeekEndIob() is used to seek the end of all the buffers in the current
761 Iob. This is done at the conclusion of a write, to avoid DNL problems.
762
763 EFUNC*/
764
SeekEndIob()765 void SeekEndIob()
766 {
767 BEGIN("SeekEndIob")
768 int size,tsize;
769 static unsigned char Terminator[] = {0x80,0x00};
770
771 size = lseek(Iob->file,0,SEEK_END);
772 tsize = Iob->width*Iob->height*Iob->wsize;
773 if (size != tsize)
774 {
775 WHEREAMI();
776 printf("End not flush, making flush (actual: %d != target:%d)\n",
777 size,tsize);
778
779 if (size<tsize)
780 {
781 lseek(Iob->file,tsize-1,SEEK_SET); /* Seek and terminate */
782 write(Iob->file,Terminator,1);
783 }
784 else if (size > tsize)
785 {
786 #ifdef NOTRUNCATE
787 WHEREAMI();
788 printf("file is too large, only first %d bytes valid\n",
789 tsize);
790 #else
791 #ifdef WIN32
792 chsize(Iob->file,tsize); /* no ftruncate on WIN32... */
793 #else
794 ftruncate(Iob->file,tsize); /* simply truncate*/
795 #endif
796 #endif
797 }
798 }
799 }
800
801
802 /*BFUNC
803
804 CloseIob() is used to close the current Iob.
805
806 EFUNC*/
807
CloseIob()808 void CloseIob()
809 {
810 BEGIN("CloseIob")
811
812 if( !CFrame->tmpfile ) /* if file is closed we loose it for good */
813 {
814 close(Iob->file);
815 }
816 }
817
818 /*BFUNC
819
820 ReadXBound() reads nelem elements of information from the specified
821 buffer. It detects to see whether a load is necessary or not, or
822 whether the current buffer is out of the image width bounds.
823
824 EFUNC*/
825
ReadXBound(nelem,cstore,buffer)826 static void ReadXBound(nelem,cstore,buffer)
827 int nelem;
828 int *cstore;
829 BUFFER *buffer;
830 {
831 BEGIN("ReadXBound")
832 int i,diff;
833
834 if ((diff = buffer->iob->width - TrueBufferPos(buffer)) <= nelem)
835 {
836 #ifdef IO_DEBUG
837 printf("ReadBound: Trailing Edge Detected. Diff: %d\n",diff);
838 #endif
839 if (diff <= 0)
840 {
841 for(i=0;i<nelem;i++) /* Pure outside bounds */
842 *(cstore++) = buffer->overflow;
843 }
844 else
845 {
846 ReadXBuffer(diff,cstore,buffer);
847 buffer->overflow = (unsigned int) cstore[diff-1];
848 for(i=diff;i<nelem;i++) /* Replicate to bounds */
849 cstore[i] = cstore[i-1];
850 }
851 }
852 else
853 ReadXBuffer(nelem,cstore,buffer);
854 }
855
856 /*BFUNC
857
858 WriteXBound() writes the integer array input to the buffer. It checks
859 to see whether the bounds of the image width are exceeded, if so, the
860 excess information is ignored.
861
862 EFUNC*/
863
WriteXBound(nelem,cstore,buffer)864 static void WriteXBound(nelem,cstore,buffer)
865 int nelem;
866 int *cstore;
867 BUFFER *buffer;
868 {
869 BEGIN("WriteXBound")
870 int diff;
871
872 if ((diff = buffer->iob->width - TrueBufferPos(buffer)) <= nelem)
873 { /* Diff is balance to write to disk */
874 if (diff > 0) /* Write balance out to disk */
875 WriteXBuffer(diff,cstore,buffer);
876 }
877 else /* If more than numberelem, then can put all */
878 WriteXBuffer(nelem,cstore,buffer); /* to the buffer. */
879 }
880
881 /*BFUNC
882
883 InstallIob() is used to install the Iob in the current scan as the
884 real Iob.
885
886 EFUNC*/
887
InstallIob(index)888 void InstallIob(index)
889 int index;
890 {
891 BEGIN("InstallIob")
892
893 if (!(Iob = CScan->Iob[index]))
894 {
895 WHEREAMI();
896 printf("Warning, NULL Iob installed.\n");
897 }
898 }
899
900
901 /*BFUNC
902
903 TerminateFile() is a function that ensures that the entire file
904 defined by the Iob is properly flush with the filesize specifications.
905 This function is used when some fatal error occurs.
906
907 EFUNC*/
908
909
TerminateFile()910 void TerminateFile()
911 {
912 BEGIN("TerminateFile")
913 int i,size;
914 static unsigned char Terminator[] = {0x80,0x00};
915
916 if (CFrame->GlobalHeight)
917 {
918 printf("> GH:%d GW:%d R:%d\n",
919 CFrame->GlobalHeight,
920 CFrame->GlobalWidth,
921 CFrame->ResyncInterval);
922 for(i=0;i<CScan->NumberComponents;i++)
923 {
924 if (CScan->Iob[i])
925 {
926 printf(">> C:%d N:%s H:%d W:%d hf:%d vf:%d\n",
927 CScan->ci[i],
928 CFrame->ComponentFileName[CScan->ci[i]],
929 CFrame->Height[CScan->ci[i]],
930 CFrame->Width[CScan->ci[i]],
931 CFrame->hf[CScan->ci[i]],
932 CFrame->vf[CScan->ci[i]]);
933 InstallIob(i);
934 FlushIob();
935 size = lseek(CScan->Iob[i]->file,0,SEEK_END);
936 if (size !=
937 CFrame->Width[CScan->ci[i]]*CFrame->Height[CScan->ci[i]]*
938 CScan->Iob[i]->wsize)
939 { /* Terminate file */
940 lseek(CScan->Iob[i]->file, /* by seeking to end */
941 (CFrame->Width[CScan->ci[i]]* /* And writing byte */
942 CFrame->Height[CScan->ci[i]]*
943 CScan->Iob[i]->wsize)-1, /* Making flush with */
944 SEEK_SET); /* Original size */
945 write(CScan->Iob[i]->file,Terminator,1);
946 }
947 }
948 }
949 }
950 else
951 {
952 WHEREAMI();
953 printf("Unknown number of lines. Cannot flush file.\n");
954 }
955 }
956
957
958 /*BFUNC
959
960 ReadLine() reads in the lines required by the lossless function. The
961 array *store should be large enough to handle the line information
962 read.
963
964 In total, there should be (HORIZONTALFREQUENCY+1) * nelem
965 (VERTICALFREQUENCY+1) elements in the *store array. This forms a
966 matrix with each line consisting of:
967
968 [PastPredictor 1 element] nelem* [HORIZONTALFREQUENCY elements]
969
970 And there are (VERTICALFREQUENCY+1) of such lines in the matrix:
971
972 Previous line (2**Precision-1) if beyond specifications of window
973 Active line 1...
974 ...
975 Active line VERTICALFREQUENCY...
976
977
978 EFUNC*/
979
ReadLine(nelem,store)980 void ReadLine(nelem,store)
981 int nelem;
982 int *store;
983 {
984 BEGIN("ReadLine")
985 int i;
986
987 for(i=0;i<Iob->ver+1;i++) /* Use voffs to index into */
988 { /* Buffer list of IOB */
989 #ifdef IO_DEBUG
990 printf("%d Iob %x\n",i,Iob->blist[i]->Iob);
991 #endif
992 *(store++)=Iob->blist[i]->data_linelast;
993 ReadXBound(Iob->hor*nelem,store,Iob->blist[i]);
994 store+=Iob->hor*nelem;
995 Iob->blist[i]->data_linelast = *(store-1);
996 }
997 Iob->hpos += Iob->hor*nelem;
998 if (Iob->hpos >= CScan->MDUWide*Iob->hor)
999 {
1000 Iob->vpos += Iob->ver;
1001 Iob->hpos = 0; /* If at end of raster width*/
1002 LineMoveTo(); /* Reload buffers from start */
1003 } /* of next line. */
1004 }
1005
1006 /*BFUNC
1007
1008 ReadPreambleLine() reads the first line of the *store array for the
1009 WriteLine() companion command. It reads it so that prediction can be
1010 accomplished with minimum effort and storage.
1011
1012 This command is executed before decoding a particular line for the
1013 prediction values; WriteLine() is called after the decoding is done.
1014
1015 EFUNC*/
1016
ReadPreambleLine(nelem,store)1017 void ReadPreambleLine(nelem,store)
1018 int nelem;
1019 int *store;
1020 {
1021 BEGIN("ReadPreambleLine")
1022 int i;
1023 int preamblelength=1;
1024
1025 for(i=0;i<Iob->ver+1;i++) /* Use voffs to index into */
1026 { /* Buffer list of IOB */
1027 #ifdef IO_DEBUG
1028 printf("%d Iob %x\n",i,Iob->blist[i]->Iob);
1029 #endif
1030 if (i<preamblelength)
1031 {
1032 *(store++)=Iob->blist[i]->data_linelast;
1033 ReadXBound(Iob->hor*nelem,store,Iob->blist[i]);
1034 store+=Iob->hor*nelem;
1035 Iob->blist[i]->data_linelast = *(store-1);
1036 }
1037 else
1038 {
1039 *(store) = Iob->blist[i]->data_linelast;
1040 store += Iob->hor*nelem+1;
1041 }
1042 }
1043 }
1044
1045
1046 /*BFUNC
1047
1048 WriteLine() is used to write a particular line out to the IOB. The
1049 line must be of the proper form in the array for this function to
1050 work.
1051
1052 In total, there should be (HORIZONTALFREQUENCY+1) * nelem
1053 (VERTICALFREQUENCY+1) elements in the *store array. This forms a
1054 matrix with each line consisting of:
1055
1056 [PastPredictor 1 element] nelem* [HORIZONTALFREQUENCY elements]
1057
1058 And there are (VERTICALFREQUENCY+1) of such lines in the matrix:
1059
1060 Previous line (2**Precision-1) if beyond specifications of window
1061 Active line 1...
1062 ...
1063 Active line VERTICALFREQUENCY...
1064
1065
1066 EFUNC*/
1067
WriteLine(nelem,store)1068 void WriteLine(nelem,store)
1069 int nelem;
1070 int *store;
1071 {
1072 BEGIN("WriteLine")
1073 int i;
1074
1075 store += Iob->hor*nelem+1; /* Get rid of first line */
1076 for(i=1;i<Iob->ver+1;i++) /* Use voffs to index into */
1077 { /* Buffer list of IOB */
1078 #ifdef IO_DEBUG
1079 printf("WriteLine: %d Store: %d Iobblist: %x\n",
1080 i,*(store+1),Iob->blist[i]);
1081 #endif
1082
1083 WriteXBound(Iob->hor*nelem,store+1,Iob->blist[i]);
1084 store+=(Iob->hor*nelem)+1;
1085 Iob->blist[i]->data_linelast = *(store-1);
1086 }
1087 Iob->hpos += Iob->hor*nelem;
1088 if (Iob->hpos >= CScan->MDUWide*Iob->hor)
1089 {
1090 Iob->vpos += Iob->ver;
1091 Iob->hpos = 0; /* If at end of raster width*/
1092 FlushIob(); /* Flush current IOB and */
1093 LineMoveTo(); /* Reload buffers from start */
1094 } /* of next line. */
1095 }
1096
1097 /*BFUNC
1098
1099 LineResetBuffers() resets all of the line buffers to the
1100 (2\^DataPrecision-1) state. The previous state is the default
1101 prediction. This commmand is used for resynchronization. The
1102 implementation here does a trivial resetting.
1103
1104 EFUNC */
1105
LineResetBuffers()1106 extern void LineResetBuffers()
1107 {
1108 BEGIN("LineResetBuffers")
1109 int i;
1110
1111 if (Iob->type!=IOB_LINE)
1112 {
1113 WHEREAMI();
1114 printf("Attempting to line reset a non-line buffer!\n");
1115 exit(ERROR_PARAMETER);
1116 }
1117 for(i=0;i<Iob->ver+1;i++)
1118 Iob->blist[i]->data_linelast = Iob->linelastdefault;
1119 }
1120
1121 /*BFUNC
1122
1123 LineMoveTo() is used to move to a specific vertical and horizontal
1124 location (line wise) specified by the current Iob. That means you set
1125 the current Iob parameters and then call LineMoveTo().
1126
1127 EFUNC*/
1128
LineMoveTo()1129 static void LineMoveTo()
1130 {
1131 BEGIN("LineMoveTo")
1132 int i,vertical,horizontal;
1133
1134 if (Loud > MUTE)
1135 {
1136 WHEREAMI();
1137 printf("%p Moving To [Horizontal:Vertical] [%d:%d] \n",
1138 (void*)Iob,Iob->hpos,Iob->vpos);
1139 }
1140 horizontal = Iob->hpos;
1141 vertical = Iob->vpos;
1142 for(i=0;i<Iob->ver+1;i++)
1143 { /* Reset last element read */
1144 if (vertical<0)
1145 {
1146 Iob->blist[i]->disable=1;
1147 continue;
1148 }
1149 Iob->blist[i]->disable=0;
1150 Iob->blist[i]->data_linelast=Iob->linelastdefault;
1151 if (Iob->height)
1152 {
1153 vertical =
1154 ((vertical < Iob->height) ?
1155 vertical : Iob->height-1);
1156 }
1157 Iob->blist[i]->tptr = /* Reset pointer space */
1158 Iob->blist[i]->bptr = /* To show no contents */
1159 Iob->blist[i]->space;
1160 Iob->blist[i]->currentoffs = horizontal* Iob->wsize; /* Reset h offset */
1161 Iob->blist[i]->streamoffs = vertical * Iob->width *
1162 Iob->wsize; /* Reset v offset */
1163 vertical++;
1164 }
1165 }
1166
1167
1168
1169 /*END*/
1170