5fd823e78c13e2466646f310330fc9f4631c4b16
[blender-staging.git] / source / blender / imbuf / intern / iff.c
1 /**
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  * iff.c
28  *
29  * $Id$
30  */
31
32 #include "BLI_blenlib.h"
33 #include "imbuf.h"
34 #include "imbuf_patch.h"
35 #include "IMB_imbuf_types.h"
36 #include "IMB_iff.h"
37 #ifdef WIN32
38 #include <io.h>
39 #include "BLI_winstuff.h"
40 #endif
41
42 unsigned short imb_start_iff(struct ImBuf *ibuf, int file)
43 {
44         unsigned int *point, size, *buf;
45         
46         if ((point=buf=(unsigned int *)malloc(32768))==0) return FALSE;
47
48         *point++ = FORM;                                /* FORMxxxxILBM in buffer */
49         *point++ = 0;
50
51         if (IS_amiga(ibuf)){
52                 struct BitMapHeader *bmhd;
53
54                 *point++ = ILBM;
55                 *point++ = CAMG;
56                 *point++ = 4;
57                 *point++ = (ibuf->ftype & 0xffff);
58
59                 *point++=BMHD;
60                 *point++=sizeof(struct BitMapHeader);
61
62                 bmhd=(struct BitMapHeader *)point;              /* bmhd points to location where bmhd will be */
63                 point=(unsigned int *)((char *)point+sizeof(struct BitMapHeader));      /* advance pointer already */
64
65                 bmhd->w=ibuf->x;
66                 bmhd->h=ibuf->y;
67                 bmhd->pageWidth=ibuf->x;
68                 bmhd->pageHeight=ibuf->y;
69                 bmhd->x=0;
70                 bmhd->y=0;
71                 bmhd->nPlanes=ibuf->depth;
72                 bmhd->masking=0;
73                 if (ibuf->flags & IB_vert){
74                         bmhd->compression=2;
75                 }
76                 else{
77                         bmhd->compression=1;
78                 }
79                 bmhd->pad1=0;
80                 bmhd->transparentColor=0;
81                 bmhd->xAspect=1;
82                 bmhd->yAspect=1;
83         } else if (IS_anim(ibuf)){
84                 struct Adat *adat;
85                 extern float adat_gamma;
86                 extern float adat_distort;
87                 
88                 *point++ = ANIM;
89                 *point++ = ADAT;
90                 *point++ = BIG_LONG(sizeof(struct Adat));
91
92                 adat = (struct Adat *)point;
93                 point = (unsigned int *)((char *)point+sizeof(struct Adat));    /* advance pointer already */
94
95                 adat->w = BIG_SHORT(ibuf->x);
96                 adat->h = BIG_SHORT(ibuf->y);
97
98                 adat->type = BIG_SHORT(ibuf->ftype);
99                 adat->xorig = BIG_SHORT(ibuf->xorig);
100                 adat->yorig = BIG_SHORT(ibuf->yorig);
101                 adat->pad = 0;
102                 adat->gamma = adat_gamma;
103                 adat->distort = adat_distort;
104         }
105
106         size=((uchar *)point-(uchar *)buf);
107         if (write(file,buf,size)!=size){
108                 free(buf);
109                 return (FALSE);
110         }
111
112         if (ibuf->cmap){
113                 if (IS_anim(ibuf)){
114                         size = ibuf->maxcol * sizeof(int);
115                         buf[0] = CMAP;
116                         buf[1] = BIG_LONG(size);
117                         if (write(file,buf,8) != 8){
118                                 free(buf);
119                                 return (FALSE);
120                         }
121                         if (write(file,ibuf->cmap,size) != size){
122                                 free(buf);
123                                 return (FALSE);
124                         }
125                 } else{
126                         uchar *cpoint,*cols;
127                         unsigned int i,bits;
128
129                         point = buf;
130                         if (IS_amiga(ibuf)){
131                                 *(point++) = CMAP;
132                                 *(point++) = BIG_LONG(3*ibuf->maxcol);
133                         }
134
135                         cpoint = (uchar *) point;
136                         cols = (uchar *)ibuf->cmap;
137                         if ((ibuf->cbits > 0) && (ibuf->cbits < 8)){
138                                 bits = ~((1 << (8-ibuf->cbits)) - 1);
139                         } else bits = -1;
140
141                         if (IS_ham(ibuf)) bits = -1;
142                         
143                         for (i=0 ; i<ibuf->maxcol ; i++){
144                                 *(cpoint++) = cols[0] & bits;
145                                 *(cpoint++) = cols[1] & bits;
146                                 *(cpoint++) = cols[2] & bits;
147                                 cols += 4;
148                         }
149                         if (ibuf->maxcol & 1) *(cpoint++)=0;
150
151                         size=(cpoint-(uchar *)buf);
152                         if (write(file,buf,size)!=size){
153                                 free(buf);
154                                 return (FALSE);
155                         }
156                 }
157         }
158
159         if (IS_amiga(ibuf)) buf[0] = BODY;
160         if (IS_anim(ibuf)) buf[0] = BODY;
161         buf[1]=0;
162
163         if (write(file,buf,8)!=8){
164                 free(buf);
165                 return(FALSE);
166         }
167
168         free(buf);
169         return (TRUE);
170 }
171
172
173 unsigned short imb_update_iff(int file, int code)
174 {
175         int     buf[2], filelen, skip;
176         uchar nop;
177
178         if (file<=0) return (FALSE);
179
180         filelen = BLI_filesize(file)-8;                 /* calc filelength  */
181
182         lseek(file,0L,2);               /* seek end */
183
184         if (filelen & 1){                                               /* make length 'even' */
185                 switch(code){
186                 case BODY:
187                         nop = IFFNOP;
188                         break;
189                 }
190                 if (write(file,&nop,1)!=1) return (FALSE);
191                 filelen++;
192         }
193         lseek(file,4L,0);
194
195         buf[0] = BIG_LONG(filelen);
196         
197         if (write(file, buf, 4) != 4) return (FALSE);
198         if (code == 0) return (TRUE);
199
200         filelen-=4;
201         lseek(file,4L,1);
202
203         while (filelen>0){              /* seek BODY */
204                 read(file, buf, 8);
205                 filelen -= 8;
206                 if (buf[0] == code) break;
207                 
208                 skip = (BIG_LONG(buf[1]) + 1) & ~1;
209                 filelen -= skip;
210                 lseek(file, skip, 1);
211         }
212         if (filelen <= 0) {
213                 printf("update_iff: couldn't find chunk\n");
214                 return (FALSE);
215         }
216
217         lseek(file, -4L, 1);
218         
219         buf[0] = BIG_LONG(filelen);
220         
221         if (write(file, buf, 4)!=4) return (FALSE);
222
223         return (TRUE);
224 }