1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 
5 #include "general.h"
6 #include "fileoutput.h"
7 
8 /*
9 
10 Ringtone Tools - Copyright 2001-2005 Michael Kohn (mike@mikekohn.net)
11 This falls under the Kohnian license.  Please read
12 it at http://ringtonetools.mikekohn.net/
13 
14 This program is NOT opensourced.  You may not use any part
15 of this program for your own software.
16 
17 */
18 
19 /* BMP */
20 
write_bmp_info_header(FILE * out,struct note_t * note,int bits,int * palette,int palette_count)21 void write_bmp_info_header(FILE *out, struct note_t *note, int bits, int *palette, int palette_count)
22 {
23 int t;
24 /* int t,d; */
25 
26   /* d=ftell(out); */
27 
28   write_long(out,40);            /* biSize */
29   write_long(out,note->width);
30   write_long(out,note->height);
31   write_word(out,1);
32   write_word(out,bits);
33   write_long(out,0);             /* compression */
34   /* write_long(out,image_size); */
35   write_long(out,0);
36   write_long(out,0);             /* biXPelsperMetre */
37   write_long(out,0);             /* biYPelsperMetre */
38   write_long(out,palette_count); /* biClrUsed */
39   write_long(out,palette_count); /* biClrImportant */
40 
41   for (t=0; t<palette_count; t++)
42   { write_long(out,palette[t]); }
43 
44 /*
45   t=ftell(out);
46   fseek(out,d,SEEK_SET);
47   write_long(out,t-d);
48   fseek(out,t,SEEK_SET);
49 */
50 }
51 
write_bmp_header(FILE * out,struct note_t * note)52 void write_bmp_header(FILE *out, struct note_t *note)
53 {
54   write_chars(out,"BM");
55   write_long(out,0);
56   write_word(out,0);
57   write_word(out,0);
58   write_long(out,0);   /* size */
59 }
60 
color_distance(int c1,int c2)61 int color_distance(int c1, int c2)
62 {
63 int d;
64 
65   d=abs((c1&255)-(c2&255))+(((c1>>8)&255)-((c2>>8)&255))+(((c1>>16)&255)-((c2>>16)&255));
66 
67   return d/3;
68 }
69 
compute_palette(struct note_t * note,int * palette,int * palette_count,int true_color)70 int compute_palette(struct note_t *note,int *palette,int *palette_count,int true_color)
71 {
72 int l,ptr,c,count;
73 
74   count=0;
75   l=note->width*note->height;
76 
77   for (ptr=0; ptr<l; ptr++)
78   {
79     for (c=0; c<count; c++)
80     {
81       if (palette[c]==note->picture[ptr]) break;
82     }
83 
84     if (c==count)
85     {
86       if (count>=256)
87       {
88         if (true_color==1) return 24;
89         return 8;
90       }
91       palette[count++]=note->picture[ptr];
92     }
93   }
94 
95   *palette_count=count;
96 
97   if (count<=2) return 1;
98     else
99   if (count<=16) return 4;
100     else
101   if (count<=256) return 8;
102 
103   return 24;
104 }
105 
get_color(int col,int * palette,int palette_count)106 int get_color(int col, int *palette, int palette_count)
107 {
108 int d,c;
109 
110   for (c=0; c<palette_count; c++)
111   {
112     if (col==palette[c]) return c;
113   }
114 
115   for (d=0; d<255; d++)
116   {
117     for (c=0; c<palette_count; c++)
118     {
119       if (color_distance(col,palette[c])<=d) return c;
120     }
121   }
122 
123   return 0;
124 }
125 
write_bmp_data(FILE * out,struct note_t * note,int bits,int * palette,int palette_count)126 void write_bmp_data(FILE *out, struct note_t *note, int bits, int *palette, int palette_count)
127 {
128 int x,y,c,b,k,padding;
129 
130   if (bits==1)
131   {
132     padding=note->width/8;
133     if ((note->width%8)!=0) padding++;
134     padding=padding%4;
135     if (padding==0) padding=4;
136 
137     for (y=note->height-1; y>=0; y--)
138     {
139       x=0;
140       while(x<note->width)
141       {
142         k=0;
143 
144         for (b=7; b>=0; b--)
145         {
146           if (x<note->width)
147           {
148             c=note->picture[x+(y*note->width)];
149             c=((c&255)+((c>>8)&255)+((c>>16)&255))/3;
150 
151             if (c>COLOR_THRESHOLD)
152             { k=k+(1<<b); }
153           }
154           x++;
155         }
156         putc(k,out);
157       }
158 
159       for (x=padding; x<4; x++)
160       { putc(0,out); }
161     }
162   }
163     else
164   if (bits==4)
165   {
166     padding=(note->width>>1)+(note->width&1);
167     padding=(padding%4);
168     if (padding==0) padding=4;
169 
170     for (y=note->height-1; y>=0; y--)
171     {
172       for (x=0; x<note->width; x++)
173       {
174         b=get_color(note->picture[x+(y*note->width)],palette,palette_count)<<4;
175         x++;
176         if (x<note->width);
177         { b|=get_color(note->picture[x+(y*note->width)],palette,palette_count); }
178         putc(b,out);
179       }
180 
181       for (x=padding; x<4; x++)
182       { putc(0,out); }
183     }
184   }
185     else
186   if (bits==8)
187   {
188     padding=(note->width)%4;
189     if (padding==0) padding=4;
190 
191     for (y=note->height-1; y>=0; y--)
192     {
193       for (x=0; x<note->width; x++)
194       {
195         putc(get_color(note->picture[x+(y*note->width)],palette,palette_count),out);
196       }
197 
198       for (x=padding; x<4; x++)
199       { putc(0,out); }
200     }
201   }
202     else
203   if (bits==24)
204   {
205     padding=(note->width*3)%4;
206     if (padding==0) padding=4;
207 
208     for (y=note->height-1; y>=0; y--)
209     {
210       for (x=0; x<note->width; x++)
211       {
212         putc(((note->picture[x+(y*note->width)])&255),out);
213         putc(((note->picture[x+(y*note->width)]>>8)&255),out);
214         putc(((note->picture[x+(y*note->width)]>>16)&255),out);
215       }
216 
217       for (x=padding; x<4; x++)
218       { putc(0,out); }
219     }
220   }
221 
222 }
223 
write_bmp_footer(FILE * out,struct note_t * note)224 void write_bmp_footer(FILE *out, struct note_t *note)
225 {
226 int data_length,palette_count,bits;
227 int palette[256];
228 int t;
229 
230   palette_count=0;
231 
232   if ((note->bmp_flags&4)==0)
233   {
234     bits=1;
235     palette[palette_count++]=0;
236     palette[palette_count++]=0xffffff;
237   }
238     else
239   {
240     bits=compute_palette(note,palette,&palette_count,1);
241   }
242 
243   write_bmp_info_header(out,note,bits,palette,palette_count);
244 
245   data_length=ftell(out);
246   fseek(out,10,SEEK_SET);
247   write_long(out,data_length);
248   fseek(out,data_length,SEEK_SET);
249 
250   /* printf("pointer to data %d\n",data_length); */
251 
252   t=ftell(out);
253   write_bmp_data(out,note,bits,palette,palette_count);
254 
255   data_length=ftell(out);
256   fseek(out,2,SEEK_SET);
257   write_long(out,data_length);
258   fseek(out,34,SEEK_SET);
259   write_long(out,data_length-t);
260   fseek(out,data_length,SEEK_SET);
261 }
262 
263 /*
264 void write_bmp_footer(FILE *out, struct note_t *note)
265 {
266 int x,y,k,b,c;
267 int padding=0;
268 int data_length;
269 int image_size;
270 
271   if ((note->bmp_flags&4)==0)
272   {
273     image_size=note->width/8;
274     if (note->width%8>0) image_size++;
275     if (image_size%4!=0)
276     { image_size=image_size+(4-(image_size%4)); }
277   }
278     else
279   {
280     image_size=note->width*3;
281     while ((image_size%4)!=0) image_size++;
282     image_size=image_size*note->height;
283   }
284 
285 
286   data_length=ftell(out);
287   fseek(out,2,SEEK_SET);
288   write_long(out,data_length);
289   fseek(out,data_length,SEEK_SET);
290 }
291 
292 */
293 
write_text_footer(FILE * out,struct note_t * note)294 void write_text_footer(FILE *out, struct note_t *note)
295 {
296 int x,y,c;
297 
298   for (y=0; y<note->height; y++)
299   {
300     for (x=0; x<note->width; x++)
301     {
302       c=note->picture[x+(y*note->width)];
303       c=((c&255)+((c>>8)&255)+((c>>16)&255))/3;
304 
305       if (c>COLOR_THRESHOLD)
306       { putc('*',out); }
307         else
308       { putc(' ',out); }
309     }
310     putc('\n',out);
311   }
312 }
313 
write_wbmp_header(FILE * out,struct note_t * note)314 void write_wbmp_header(FILE *out, struct note_t *note)
315 {
316   putc(0,out);
317   putc(0,out);
318   putc(note->width,out);
319   putc(note->height,out);
320 }
321 
write_wbmp_footer(FILE * out,struct note_t * note)322 void write_wbmp_footer(FILE *out, struct note_t *note)
323 {
324 int x,y,k,b,c;
325 int ptr;
326 
327   ptr=0;
328 
329   for (y=0; y<note->height; y++)
330   {
331     x=0;
332     while (x<note->width)
333     {
334       k=0;
335 
336       for (b=7; b>=0; b--)
337       {
338         if (x<note->width)
339         {
340           c=note->picture[ptr++];
341           c=((c&255)+((c>>8)&255)+((c>>16)&255))/3;
342 
343           if (c>COLOR_THRESHOLD)
344           { k=k+(1<<b); }
345         }
346         x++;
347       }
348       putc(k,out);
349     }
350   }
351 }
352 
353 
write_icon_header(FILE * out,struct note_t * note)354 void write_icon_header(FILE *out, struct note_t *note)
355 {
356   if (note->width!=16 && note->width!=32 && note->width!=64)
357   {
358     note->width=0;
359     printf("Invalid width for icon file\n");
360     return;
361   }
362 
363   if (note->height!=16 && note->height!=32 && note->height!=64)
364   {
365     note->height=0;
366     printf("Invalid width for icon file\n");
367     return;
368   }
369 
370   write_word(out,0);
371   write_word(out,1);
372   write_word(out,1);
373 
374   putc(note->width,out);
375   putc(note->height,out);
376 }
377 
write_icon_footer(FILE * out,struct note_t * note)378 void write_icon_footer(FILE *out, struct note_t *note)
379 {
380 int data_length,palette_count,bits,bmp_start;
381 int palette[256],t,d,k,p,x,y;
382 
383   palette_count=0;
384 
385   if ((note->bmp_flags&4)==0)
386   {
387     bits=1;
388     palette[palette_count++]=0;
389     palette[palette_count++]=0xffffff;
390   }
391     else
392   {
393     bits=compute_palette(note,palette,&palette_count,1);
394   }
395 
396   if (bits>=8)
397   { putc(0,out); }
398     else
399   { putc((1<<bits),out); }
400 
401   putc(0,out);
402   write_word(out,0);
403   write_word(out,0);
404   t=ftell(out);
405   write_long(out,0);
406   write_long(out,ftell(out)+4);
407 
408 #ifdef DEBUG
409 printf("Palette count=%d  bits=%d\n",palette_count,bits);
410 #endif
411 
412   bmp_start=ftell(out);
413   write_bmp_info_header(out,note,bits,palette,palette_count);
414   if ((1<<bits)!=palette_count && bits<24)
415   {
416     d=1<<bits;
417     for (k=palette_count; k<d; k++)
418     {
419       write_long(out,0);
420     }
421   }
422   write_bmp_data(out,note,bits,palette,palette_count);
423 
424   for (y=note->height-1; y>=0; y--)
425   {
426     x=0;
427     while(x<note->width)
428     {
429       k=0;
430       if (note->trans>=0)
431       {
432         for (p=7; p>=0; p--)
433         {
434           if (x<note->width && note->picture[x+(y*note->width)]==note->trans)
435           { k=k+(1<<p); }
436           x++;
437         }
438       }
439         else
440       { x=x+8; }
441       putc(k,out);
442     }
443 
444     if ((x%32)!=0)
445     {
446       p=((x%32)/8);
447       for(k=0; k<p; k++) putc(0,out);
448     }
449   }
450 
451   data_length=ftell(out);
452 
453   fseek(out,t,SEEK_SET);              /* Icon Offset */
454   write_long(out,data_length-bmp_start);
455   /* write_long(out,data_length-(t+8)); */
456 
457   fseek(out,t+16,SEEK_SET);           /* biHeight */
458   write_long(out,note->height*2);
459 
460   fseek(out,t+28,SEEK_SET);           /* biSizeImage */
461   /* write_long(out,data_length-d-40); */
462   write_long(out,0);
463   write_long(out,0);
464   write_long(out,0);
465   write_long(out,0);
466   write_long(out,0);
467 
468   /* write_long(out,data_length-(t+8-40)); */
469   fseek(out,data_length,SEEK_SET);
470 
471 }
472 
473 
474