5 #include "epp_private.h"
6 #define row_buffer ((unsigned char **)epp->cache)
11 * Opens file in read-write mode and loads raster into memory
12 * Returns pointer to newly created structure or NULL on error
15 EPP *load_epp(char *filename)
18 f=fopen(filename,"rb+");
27 * Reads file from given stream into memory. Returns 0 if Ok, -1 if
31 int do_load_epp(EPP *epp)
34 unsigned short *width;
35 unsigned short *new_widthtable=NULL; /* if we have to create widthtable
36 on the fly, we would keep it here */
38 unsigned short int *pixel;
41 if(!epp->widthtable) {
42 new_widthtable=calloc(epp->lr-epp->fr,sizeof(short int));
46 If we want to have read-write access, we should have read access
47 first. Switching from write-only to read-write access requires
50 if(!(epp->mode&MAP_INPUT)) {
51 map_error=ME_INVALID_MODE;
55 We use pointer where cache is otherwise kept
57 if (epp->mode&MAP_CACHED) {
61 Create array of pointers to file rows
63 if ((epp->cache=calloc(epp->lr-epp->fr,sizeof(char *)))==NULL) {
64 map_error=ME_OUT_OF_MEMORY;return -1;
67 Allocate table of frequencies.
69 /* Note, count of pixels with value==offsite not stored here! */
70 epp->counttable=calloc(1<<epp->kind,sizeof(int));
71 counttab=epp->counttable;
72 if (epp->counttable==NULL) {
73 map_error=ME_OUT_OF_MEMORY;
79 /* We are assuming that file is fresh from fopen_epp or reset_epp */
80 nrows=epp->lr-epp->fr;
81 if (epp->widthtable) {
82 width=epp->widthtable;
86 for(row=epp->cache,i=epp->fr,k=1;i<epp->lr;width++,i++,row++,k++)
87 { if((*row=malloc(*width))==NULL)
88 { for(rr=epp->cache;rr<row;rr++) free(*rr);
90 free(epp->counttable);
91 map_error=ME_OUT_OF_MEMORY;
94 if (EndLineProc) (*EndLineProc)(i,k,nrows);
98 *width=epp->filepos-oldpos;
100 memcpy(*row,epp->packed_buffer,*width);
101 for (j=epp->fc,pixel=epp->row;j<epp->lc;j++,pixel++) {
105 /* find out what is actual maximum minimum of file */
106 for (i=(1<<epp->kind)-1;i>0&&(counttab[i]==0||i==epp->offsite);i--);
108 for (i=0;i<epp->max&&(counttab[i]==0||i==epp->offsite);i++);
110 fseek(epp->F,128L,SEEK_SET);
112 epp->currentline=epp->fr-1;
114 epp->mode=MAP_INPUT|MAP_OUTPUT|MAP_LOADED;
115 epp->position=position_loaded;
119 * Recieves stream and loads epp-file from it
122 EPP *fload_epp(FILE *f)
129 /* do_load return non-zero on error */
130 if (do_load_epp(epp)) {
137 int load_new_epp(EPP *epp)
139 if (epp->mode!=MAP_OUTPUT) {
140 map_error=ME_INVALID_MODE;
144 if (do_load_epp(epp)) {
151 void save_row(EPP *epp)
152 { int oldsize,newsize,l=epp->currentline-epp->fr;
154 if (!epp->modified) return;
156 epp->mode|=MAP_MODIFIED;
157 oldsize=epp->widthtable[l];
158 newsize=pack_buffer(epp);
159 if (oldsize != newsize) {
161 row_buffer[l]=malloc(newsize);
162 epp->widthtable[l]=newsize;
164 memcpy(row_buffer[l],epp->packed_buffer,newsize);
168 * Writes loaded file back. Uses stream stored in F field.
169 * Returns 0 on success, -1 on failure
170 * Calls EndLineProc after saving each row.
173 int save_epp(EPP *epp)
176 unsigned short *width;
178 if (!(epp->mode&MAP_LOADED)) {
179 map_error=ME_INVALID_MODE;
183 /* If file wasn't modified, don't save. See touch_epp macro in epp.h */
184 if (!(epp->mode&MAP_MODIFIED)) {
188 fseek(epp->F,128L,SEEK_SET);
190 nrows=epp->lr-epp->fr;
191 map_error=ME_WRITE_ERROR;
192 for(i=epp->fr,row=epp->cache,width=epp->widthtable,k=1;
193 i<epp->lr; row++,width++,i++,k++) {
194 if (EndLineProc) (*EndLineProc)(i,k,nrows);
195 if (fwrite(*row,1,*width,epp->F)!=*width)
197 epp->filepos+=*width;
199 epp->currentline=epp->lr;
201 epp->position(epp,epp->fr);
206 * Writes epp file to given stream and makes this stream default
207 * Copies header by hand and then calls save_epp
210 int fsave_epp_as(EPP *epp,FILE *f)
213 fread(&h,128,1,epp->F);
216 fseek(f,0L,SEEK_SET);
217 if (fwrite(&h,128,1,f)!=128) return 1;
219 return save_epp(epp);
222 * Wrapper around fsave_epp_as, which opens stream to pass there
226 int save_epp_as(EPP *epp,char *newname)
228 f=fopen(newname,"w+");
230 return fsave_epp_as(epp,f);
233 * position_loaded - sets current line of epp to given row.
234 * To be stored in position field of EPP structure.
235 * Takes care of saving row, if modified and unpacks neccesary row
236 * temporary substituting pointer to it into packed_buffer field.
238 void position_loaded(EPP *epp,int row)
240 unsigned char *tmp; /* to keep packed buffer */
242 if (row==epp->currentline) return;
243 save_row(epp); /* save row does nothing if row isn't modified */
244 tmp=epp->packed_buffer;
245 epp->packed_buffer=row_buffer[row-epp->fr];
248 epp->packed_buffer=tmp;
249 epp->currentline=row;
253 * epp_expand - converts loaded 8-bit file into 16-bit one
254 * by appending packed string of zeros to each row
255 * return 0 on succes -1 of failure.
257 * ME_INVALID_MODE - file is not loaded
258 * ME_INVALID_FILE - file already have maximum depth
259 * ME_OUT_OF_MEMORY - no comments
262 int epp_expand (EPP *epp)
263 { unsigned char *tail; /* here prepaired packed tail is kept*/
264 /* ATTENCTION, packtail is VERY poisoneuos fish*/
266 unsigned char *byteptr,
267 **row;/* pointer to pointer to current packed row */
269 unsigned short *width; /* pointer to current element of widthtable */
271 /* check if passed file is suitable for expanding */
272 if (!(epp->mode&MAP_LOADED)) {
273 map_error=ME_INVALID_MODE;
277 /* nowhere to expand */
278 map_error=ME_INVALID_FILE;
282 /* any error, which occurs further, should be ME_OUT_OF_MEMORY*/
283 map_error=ME_OUT_OF_MEMORY;
285 /* prepare packed tail */
286 tail_length=((epp->lc-epp->fc+254)/255)*2;
287 tail=malloc(tail_length);
288 if (!tail) return -1;
289 for (i=epp->lc-epp->fc,byteptr=tail;i>0;i-=255) {
290 int count=i>255?255:i;
294 /* reallocate rows */
296 for (i=epp->fc,width=epp->widthtable,row=row_buffer;
297 i<epp->lc;i++,row++,width++) {
298 unsigned char *tmp=realloc(*row,*width+tail_length);
300 /* realloc fails, trying to restore status quo */
301 for (i--,width--;i>=epp->fc;i--,width--)
305 /* fill newly allocated memory */
306 memcpy(tmp+*width,tail,tail_length);
307 /* store new row ptr and new width */
310 /* Width overflow is not checked, becouse packed string of zeros
311 couldn't overflow even most lengthly 8-bit row */
313 /* fix epp->kind value */
315 /* and write it to disk immediately, becouse no one cares about
316 updating this field in header, but this function */
317 fseek(epp->F,0,SEEK_SET);
318 fread(&h,128,1,epp->F);
319 /* read errors are not checked, becouse thay are quite improbable */
320 h.kind=swapshort(epp->kind);
321 fseek(epp->F,0,SEEK_SET);
322 fwrite(&h,128,1,epp->F);
323 /* Now we are ready to exit successifully */