Develop and Download Open Source Software

Browse CVS Repository

Contents of /mame32jp/mame32jp/src/png.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (show annotations) (download) (as text)
Wed Apr 24 03:53:20 2002 UTC (21 years, 11 months ago) by zero
Branch: MAIN
CVS Tags: ver_0_60_1, ver0_59_13, ver0_59_14, ver0_60_2, ver0_60_3, ver0_60_4, ver0_60_5, HEAD
Changes since 1.4: +0 -0 lines
File MIME type: text/x-csrc
*** empty log message ***

1 /*********************************************************************
2
3 png.c
4
5 PNG reading functions.
6
7 07/15/1998 Created by Mathis Rosenhauer
8 10/02/1998 Code clean up and abstraction by Mike Balfour
9 and Mathis Rosenhauer
10 10/15/1998 Image filtering. MLR
11 11/09/1998 Bit depths 1-8 MLR
12 11/10/1998 Some additional PNG chunks recognized MLR
13 05/14/1999 Color type 2 and PNG save functions added
14 05/15/1999 Handle RGB555 while saving, use osd_fxxx
15 functions for writing MSH
16 04/27/2001 Simple MNG support MLR
17
18 TODO : Fully comply with the "Recommendations for Decoders"
19 of the W3C
20
21 *********************************************************************/
22
23 #include <math.h>
24 #include <zlib.h>
25 #include "driver.h"
26 #include "png.h"
27
28 extern char build_version[];
29 extern UINT32 direct_rgb_components[3]; /* Used to determine the RGB layout in direct modes */
30
31 /* convert_uint is here so we don't have to deal with byte-ordering issues */
32 static UINT32 convert_from_network_order (UINT8 *v)
33 {
34 UINT32 i;
35
36 i = (v[0]<<24) | (v[1]<<16) | (v[2]<<8) | (v[3]);
37 return i;
38 }
39
40 int png_unfilter(struct png_info *p)
41 {
42 int i, j, bpp, filter;
43 INT32 prediction, pA, pB, pC, dA, dB, dC;
44 UINT8 *src, *dst;
45
46 if((p->image = (UINT8 *)malloc (p->height*p->rowbytes))==NULL)
47 {
48 logerror("Out of memory\n");
49 free (p->fimage);
50 return 0;
51 }
52
53 src = p->fimage;
54 dst = p->image;
55 bpp = p->bpp;
56
57 for (i=0; i<p->height; i++)
58 {
59 filter = *src++;
60 if (!filter)
61 {
62 memcpy (dst, src, p->rowbytes);
63 src += p->rowbytes;
64 dst += p->rowbytes;
65 }
66 else
67 for (j=0; j<p->rowbytes; j++)
68 {
69 pA = (j<bpp) ? 0: *(dst - bpp);
70 pB = (i<1) ? 0: *(dst - p->rowbytes);
71 pC = ((j<bpp)||(i<1)) ? 0: *(dst - p->rowbytes - bpp);
72
73 switch (filter)
74 {
75 case PNG_PF_Sub:
76 prediction = pA;
77 break;
78 case PNG_PF_Up:
79 prediction = pB;
80 break;
81 case PNG_PF_Average:
82 prediction = ((pA + pB) / 2);
83 break;
84 case PNG_PF_Paeth:
85 prediction = pA + pB - pC;
86 dA = abs(prediction - pA);
87 dB = abs(prediction - pB);
88 dC = abs(prediction - pC);
89 if (dA <= dB && dA <= dC) prediction = pA;
90 else if (dB <= dC) prediction = pB;
91 else prediction = pC;
92 break;
93 default:
94 logerror("Unknown filter type %i\n",filter);
95 prediction = 0;
96 }
97 *dst = 0xff & (*src + prediction);
98 dst++; src++;
99 }
100 }
101
102 free (p->fimage);
103 return 1;
104 }
105
106 int png_verify_signature (void *fp)
107 {
108 INT8 signature[8];
109
110 if (osd_fread (fp, signature, 8) != 8)
111 {
112 logerror("Unable to read PNG signature (EOF)\n");
113 return 0;
114 }
115
116 if (memcmp(signature, PNG_Signature, 8))
117 {
118 logerror("PNG signature mismatch found: %s expected: %s\n",signature,PNG_Signature);
119 return 0;
120 }
121 return 1;
122 }
123
124 int png_inflate_image (struct png_info *p)
125 {
126 unsigned long fbuff_size;
127
128 fbuff_size = p->height * (p->rowbytes + 1);
129
130 if((p->fimage = (UINT8 *)malloc (fbuff_size))==NULL)
131 {
132 logerror("Out of memory\n");
133 free (p->zimage);
134 return 0;
135 }
136
137 if (uncompress(p->fimage, &fbuff_size, p->zimage, p->zlength) != Z_OK)
138 {
139 logerror("Error while inflating image\n");
140 return 0;
141 }
142
143 free (p->zimage);
144 return 1;
145 }
146
147 int png_read_file(void *fp, struct png_info *p)
148 {
149 /* translates color_type to bytes per pixel */
150 const int samples[] = {1, 0, 3, 1, 2, 0, 4};
151
152 UINT32 chunk_length, chunk_type=0, chunk_crc, crc;
153 UINT8 *chunk_data, *temp;
154 UINT8 str_chunk_type[5], v[4];
155
156 struct idat
157 {
158 struct idat *next;
159 int length;
160 UINT8 *data;
161 } *ihead, *pidat;
162
163 if ((ihead = malloc (sizeof(struct idat))) == 0)
164 return 0;
165
166 pidat = ihead;
167
168 p->zlength = 0;
169 p->num_palette = 0;
170 p->num_trans = 0;
171 p->trans = NULL;
172 p->palette = NULL;
173
174 if (png_verify_signature(fp)==0)
175 return 0;
176
177 while (chunk_type != PNG_CN_IEND)
178 {
179 if (osd_fread(fp, v, 4) != 4)
180 logerror("Unexpected EOF in PNG\n");
181 chunk_length=convert_from_network_order(v);
182
183 if (osd_fread(fp, str_chunk_type, 4) != 4)
184 logerror("Unexpected EOF in PNG file\n");
185
186 str_chunk_type[4]=0; /* terminate string */
187
188 crc=crc32(0,str_chunk_type, 4);
189 chunk_type = convert_from_network_order(str_chunk_type);
190
191 if (chunk_length)
192 {
193 if ((chunk_data = (UINT8 *)malloc(chunk_length+1))==NULL)
194 {
195 logerror("Out of memory\n");
196 return 0;
197 }
198 if (osd_fread (fp, chunk_data, chunk_length) != chunk_length)
199 {
200 logerror("Unexpected EOF in PNG file\n");
201 free(chunk_data);
202 return 0;
203 }
204
205 crc=crc32(crc,chunk_data, chunk_length);
206 }
207 else
208 chunk_data = NULL;
209
210 if (osd_fread(fp, v, 4) != 4)
211 logerror("Unexpected EOF in PNG\n");
212 chunk_crc=convert_from_network_order(v);
213
214 if (crc != chunk_crc)
215 {
216 logerror("CRC check failed while reading PNG chunk %s\n",str_chunk_type);
217 logerror("Found: %08X Expected: %08X\n",crc,chunk_crc);
218 return 0;
219 }
220
221 logerror("Reading PNG chunk %s\n", str_chunk_type);
222
223 switch (chunk_type)
224 {
225 case PNG_CN_IHDR:
226 p->width = convert_from_network_order(chunk_data);
227 p->height = convert_from_network_order(chunk_data+4);
228 p->bit_depth = *(chunk_data+8);
229 p->color_type = *(chunk_data+9);
230 p->compression_method = *(chunk_data+10);
231 p->filter_method = *(chunk_data+11);
232 p->interlace_method = *(chunk_data+12);
233 free (chunk_data);
234
235 logerror("PNG IHDR information:\n");
236 logerror("Width: %i, Height: %i\n", p->width, p->height);
237 logerror("Bit depth %i, color type: %i\n", p->bit_depth, p->color_type);
238 logerror("Compression method: %i, filter: %i, interlace: %i\n",
239 p->compression_method, p->filter_method, p->interlace_method);
240 break;
241
242 case PNG_CN_PLTE:
243 p->num_palette=chunk_length/3;
244 p->palette=chunk_data;
245 logerror("%i palette entries\n", p->num_palette);
246 break;
247
248 case PNG_CN_tRNS:
249 p->num_trans=chunk_length;
250 p->trans=chunk_data;
251 logerror("%i transparent palette entries\n", p->num_trans);
252 break;
253
254 case PNG_CN_IDAT:
255 pidat->data = chunk_data;
256 pidat->length = chunk_length;
257 if ((pidat->next = malloc (sizeof(struct idat))) == 0)
258 return 0;
259 pidat = pidat->next;
260 pidat->next = 0;
261 p->zlength += chunk_length;
262 break;
263
264 case PNG_CN_tEXt:
265 {
266 char *text = (char *)chunk_data;
267
268 while(*text++) ;
269 chunk_data[chunk_length]=0;
270 logerror("Keyword: %s\n", chunk_data);
271 logerror("Text: %s\n", text);
272 }
273 free(chunk_data);
274 break;
275
276 case PNG_CN_tIME:
277 {
278 UINT8 *t=chunk_data;
279 logerror("Image last-modification time: %i/%i/%i (%i:%i:%i) GMT\n",
280 ((short)(*t) << 8)+ (short)(*(t+1)), *(t+2), *(t+3), *(t+4), *(t+5), *(t+6));
281 }
282
283 free(chunk_data);
284 break;
285
286 case PNG_CN_gAMA:
287 p->source_gamma = convert_from_network_order(chunk_data)/100000.0;
288 logerror( "Source gamma: %f\n",p->source_gamma);
289
290 free(chunk_data);
291 break;
292
293 case PNG_CN_pHYs:
294 p->xres = convert_from_network_order(chunk_data);
295 p->yres = convert_from_network_order(chunk_data+4);
296 p->resolution_unit = *(chunk_data+8);
297 logerror("Pixel per unit, X axis: %i\n",p->xres);
298 logerror("Pixel per unit, Y axis: %i\n",p->yres);
299 if (p->resolution_unit)
300 logerror("Unit is meter\n");
301 else
302 logerror("Unit is unknown\n");
303 free(chunk_data);
304 break;
305
306 case PNG_CN_IEND:
307 break;
308
309 default:
310 if (chunk_type & 0x20000000)
311 logerror("Ignoring ancillary chunk %s\n",str_chunk_type);
312 else
313 logerror("Ignoring critical chunk %s!\n",str_chunk_type);
314 if (chunk_data)
315 free(chunk_data);
316 break;
317 }
318 }
319 if ((p->zimage = (UINT8 *)malloc(p->zlength))==NULL)
320 {
321 logerror("Out of memory\n");
322 return 0;
323 }
324
325 /* combine idat chunks to compressed image data */
326 temp = p->zimage;
327 while (ihead->next)
328 {
329 pidat = ihead;
330 memcpy (temp, pidat->data, pidat->length);
331 free (pidat->data);
332 temp += pidat->length;
333 ihead = pidat->next;
334 free (pidat);
335 }
336 p->bpp = (samples[p->color_type] * p->bit_depth) / 8;
337 p->rowbytes = ceil((p->width * p->bit_depth * samples[p->color_type]) / 8.0);
338
339 if (png_inflate_image(p)==0)
340 return 0;
341
342 if(png_unfilter (p)==0)
343 return 0;
344
345 return 1;
346 }
347
348 int png_read_info(void *fp, struct png_info *p)
349 {
350 UINT32 chunk_length, chunk_type=0, chunk_crc, crc;
351 UINT8 *chunk_data;
352 UINT8 str_chunk_type[5], v[4];
353 int res = 0;
354
355 if (png_verify_signature(fp)==0)
356 return 0;
357
358 while (chunk_type != PNG_CN_IEND)
359 {
360 if (osd_fread(fp, v, 4) != 4)
361 logerror("Unexpected EOF in PNG\n");
362 chunk_length=convert_from_network_order(v);
363
364 if (osd_fread(fp, str_chunk_type, 4) != 4)
365 logerror("Unexpected EOF in PNG file\n");
366
367 str_chunk_type[4]=0; /* terminate string */
368
369 crc=crc32(0,str_chunk_type, 4);
370 chunk_type = convert_from_network_order(str_chunk_type);
371
372 if (chunk_length)
373 {
374 if ((chunk_data = (UINT8 *)malloc(chunk_length+1))==NULL)
375 {
376 logerror("Out of memory\n");
377 return 0;
378 }
379 if (osd_fread (fp, chunk_data, chunk_length) != chunk_length)
380 {
381 logerror("Unexpected EOF in PNG file\n");
382 free(chunk_data);
383 return 0;
384 }
385
386 crc=crc32(crc,chunk_data, chunk_length);
387 }
388 else
389 chunk_data = NULL;
390
391 if (osd_fread(fp, v, 4) != 4)
392 logerror("Unexpected EOF in PNG\n");
393 chunk_crc=convert_from_network_order(v);
394
395 if (crc != chunk_crc)
396 {
397 logerror("CRC check failed while reading PNG chunk %s\n",str_chunk_type);
398 logerror("Found: %08X Expected: %08X\n",crc,chunk_crc);
399 return 0;
400 }
401
402 logerror("Reading PNG chunk %s\n", str_chunk_type);
403
404 switch (chunk_type)
405 {
406 case PNG_CN_IHDR:
407 p->width = convert_from_network_order(chunk_data);
408 p->height = convert_from_network_order(chunk_data+4);
409 p->bit_depth = *(chunk_data+8);
410 p->color_type = *(chunk_data+9);
411 p->compression_method = *(chunk_data+10);
412 p->filter_method = *(chunk_data+11);
413 p->interlace_method = *(chunk_data+12);
414 free (chunk_data);
415
416 logerror("PNG IHDR information:\n");
417 logerror("Width: %i, Height: %i\n", p->width, p->height);
418 logerror("Bit depth %i, color type: %i\n", p->bit_depth, p->color_type);
419 logerror("Compression method: %i, filter: %i, interlace: %i\n",
420 p->compression_method, p->filter_method, p->interlace_method);
421 break;
422
423 case PNG_CN_tEXt:
424 {
425 char *text = (char *)chunk_data;
426 int c;
427
428 while(*text++) ;
429 chunk_data[chunk_length]=0;
430 if (strcmp ((const char *)chunk_data, "Screen") == 0)
431 {
432 c = sscanf (text, "%i%i%i%i", &p->screen.min_x, &p->screen.max_x,
433 &p->screen.min_y, &p->screen.max_y);
434 if (c == 4)
435 {
436 res = 1;
437 logerror("Screen location found at %i, %i, %i, %i\n",
438 p->screen.min_x, p->screen.max_x,
439 p->screen.min_y, p->screen.max_y);
440 }
441 else
442 logerror("Invalid %s value %s\n", chunk_data, text);
443 }
444 }
445 free(chunk_data);
446 break;
447
448 default:
449 if (chunk_data)
450 free(chunk_data);
451 break;
452 }
453 }
454 return res;
455 }
456
457 /* Expands a p->image from p->bit_depth to 8 bit */
458 int png_expand_buffer_8bit (struct png_info *p)
459 {
460 int i,j, k;
461 UINT8 *inp, *outp, *outbuf;
462
463 if (p->bit_depth < 8)
464 {
465 if ((outbuf = (UINT8 *)malloc(p->width*p->height))==NULL)
466 {
467 logerror("Out of memory\n");
468 return 0;
469 }
470
471 inp = p->image;
472 outp = outbuf;
473
474 for (i = 0; i < p->height; i++)
475 {
476 for(j = 0; j < p->width / ( 8 / p->bit_depth); j++)
477 {
478 for (k = 8 / p->bit_depth-1; k >= 0; k--)
479 *outp++ = (*inp >> k * p->bit_depth) & (0xff >> (8 - p->bit_depth));
480 inp++;
481 }
482 if (p->width % (8 / p->bit_depth))
483 {
484 for (k = p->width % (8 / p->bit_depth)-1; k >= 0; k--)
485 *outp++ = (*inp >> k * p->bit_depth) & (0xff >> (8 - p->bit_depth));
486 inp++;
487 }
488 }
489 free (p->image);
490 p->image = outbuf;
491 }
492 return 1;
493 }
494
495 void png_delete_unused_colors (struct png_info *p)
496 {
497 int i, tab[256], pen=0, trns=0;
498 UINT8 ptemp[3*256], ttemp[256];
499
500 memset (tab, 0, 256*sizeof(int));
501 memcpy (ptemp, p->palette, 3*p->num_palette);
502 memcpy (ttemp, p->trans, p->num_trans);
503
504 /* check which colors are actually used */
505 for (i = 0; i < p->height*p->width; i++)
506 tab[p->image[i]]++;
507
508 /* shrink palette and transparency */
509 for (i = 0; i < p->num_palette; i++)
510 if (tab[i])
511 {
512 p->palette[3*pen+0]=ptemp[3*i+0];
513 p->palette[3*pen+1]=ptemp[3*i+1];
514 p->palette[3*pen+2]=ptemp[3*i+2];
515 if (i < p->num_trans)
516 {
517 p->trans[pen] = ttemp[i];
518 trns++;
519 }
520 tab[i] = pen++;
521 }
522
523 /* remap colors */
524 for (i = 0; i < p->height*p->width; i++)
525 p->image[i]=tab[p->image[i]];
526
527 if (p->num_palette!=pen)
528 logerror("%i unused pen(s) deleted\n", p->num_palette-pen);
529
530 p->num_palette = pen;
531 p->num_trans = trns;
532 }
533
534 /********************************************************************************
535
536 PNG write functions
537
538 ********************************************************************************/
539
540 struct png_text
541 {
542 char *data;
543 int length;
544 struct png_text *next;
545 };
546
547 static struct png_text *png_text_list = 0;
548
549 static void convert_to_network_order (UINT32 i, UINT8 *v)
550 {
551 v[0]=i>>24;
552 v[1]=(i>>16)&0xff;
553 v[2]=(i>>8)&0xff;
554 v[3]=i&0xff;
555 }
556
557 int png_add_text (const char *keyword, const char *text)
558 {
559 struct png_text *pt;
560
561 pt = malloc (sizeof(struct png_text));
562 if (pt == 0)
563 return 0;
564
565 pt->length = strlen(keyword) + strlen(text) + 1;
566 pt->data = malloc (pt->length + 1);
567 if (pt->data == 0)
568 return 0;
569
570 strcpy (pt->data, keyword);
571 strcpy (pt->data + strlen(keyword) + 1, text);
572 pt->next = png_text_list;
573 png_text_list = pt;
574
575 return 1;
576 }
577
578 static int write_chunk(void *fp, UINT32 chunk_type, UINT8 *chunk_data, UINT32 chunk_length)
579 {
580 UINT32 crc;
581 UINT8 v[4];
582 int written;
583
584 /* write length */
585 convert_to_network_order(chunk_length, v);
586 written = osd_fwrite(fp, v, 4);
587
588 /* write type */
589 convert_to_network_order(chunk_type, v);
590 written += osd_fwrite(fp, v, 4);
591
592 /* calculate crc */
593 crc=crc32(0, v, 4);
594 if (chunk_length > 0)
595 {
596 /* write data */
597 written += osd_fwrite(fp, chunk_data, chunk_length);
598 crc=crc32(crc, chunk_data, chunk_length);
599 }
600 convert_to_network_order(crc, v);
601
602 /* write crc */
603 written += osd_fwrite(fp, v, 4);
604
605 if (written != 3*4+chunk_length)
606 {
607 logerror("Chunk write failed\n");
608 return 0;
609 }
610 return 1;
611 }
612
613 int png_write_sig(void *fp)
614 {
615 /* PNG Signature */
616 if (osd_fwrite(fp, PNG_Signature, 8) != 8)
617 {
618 logerror("PNG sig write failed\n");
619 return 0;
620 }
621 return 1;
622 }
623
624 int png_write_datastream(void *fp, struct png_info *p)
625 {
626 UINT8 ihdr[13];
627 struct png_text *pt;
628
629 /* IHDR */
630 convert_to_network_order(p->width, ihdr);
631 convert_to_network_order(p->height, ihdr+4);
632 *(ihdr+8) = p->bit_depth;
633 *(ihdr+9) = p->color_type;
634 *(ihdr+10) = p->compression_method;
635 *(ihdr+11) = p->filter_method;
636 *(ihdr+12) = p->interlace_method;
637 logerror("Type(%d) Color Depth(%d)\n", p->color_type,p->bit_depth);
638 if (write_chunk(fp, PNG_CN_IHDR, ihdr, 13)==0)
639 return 0;
640
641 /* PLTE */
642 if (p->num_palette > 0)
643 if (write_chunk(fp, PNG_CN_PLTE, p->palette, p->num_palette*3)==0)
644 return 0;
645
646 /* IDAT */
647 if (write_chunk(fp, PNG_CN_IDAT, p->zimage, p->zlength)==0)
648 return 0;
649
650 /* tEXt */
651 while (png_text_list)
652 {
653 pt = png_text_list;
654 if (write_chunk(fp, PNG_CN_tEXt, (UINT8 *)pt->data, pt->length)==0)
655 return 0;
656 free (pt->data);
657
658 png_text_list = pt->next;
659 free (pt);
660 }
661
662 /* IEND */
663 if (write_chunk(fp, PNG_CN_IEND, NULL, 0)==0)
664 return 0;
665
666 return 1;
667 }
668
669 int png_filter(struct png_info *p)
670 {
671 int i;
672 UINT8 *src, *dst;
673
674 if((p->fimage = (UINT8 *)malloc (p->height*(p->rowbytes+1)))==NULL)
675 {
676 logerror("Out of memory\n");
677 return 0;
678 }
679
680 dst = p->fimage;
681 src = p->image;
682
683 for (i=0; i<p->height; i++)
684 {
685 *dst++ = 0; /* No filter */
686 memcpy (dst, src, p->rowbytes);
687 src += p->rowbytes;
688 dst += p->rowbytes;
689 }
690 return 1;
691 }
692
693 int png_deflate_image(struct png_info *p)
694 {
695 unsigned long zbuff_size;
696
697 zbuff_size = (p->height*(p->rowbytes+1))*1.1+12;
698
699 if((p->zimage = (UINT8 *)malloc (zbuff_size))==NULL)
700 {
701 logerror("Out of memory\n");
702 return 0;
703 }
704
705 if (compress(p->zimage, &zbuff_size, p->fimage, p->height*(p->rowbytes+1)) != Z_OK)
706 {
707 logerror("Error while deflating image\n");
708 return 0;
709 }
710 p->zlength = zbuff_size;
711
712 return 1;
713 }
714
715 static int png_pack_buffer (struct png_info *p)
716 {
717 UINT8 *outp, *inp;
718 int i,j,k;
719
720 outp = inp = p->image;
721
722 if (p->bit_depth < 8)
723 {
724 for (i=0; i<p->height; i++)
725 {
726 for(j=0; j<p->width/(8/p->bit_depth); j++)
727 {
728 for (k=8/p->bit_depth-1; k>=0; k--)
729 *outp |= *inp++ << k * p->bit_depth;
730 outp++;
731 *outp = 0;
732 }
733 if (p->width % (8/p->bit_depth))
734 {
735 for (k=p->width%(8/p->bit_depth)-1; k>=0; k--)
736 *outp |= *inp++ << k * p->bit_depth;
737 outp++;
738 *outp = 0;
739 }
740 }
741 }
742 return 1;
743 }
744
745
746 /*********************************************************************
747
748 Writes an mame_bitmap in a PNG file. If the depth of the bitmap
749 is 8, a color type 3 PNG with palette is written. Otherwise a
750 color type 2 true color RGB PNG is written.
751
752 *********************************************************************/
753
754 static int png_create_datastream(void *fp, struct mame_bitmap *bitmap)
755 {
756 int i, j;
757 int r, g, b;
758 UINT32 color;
759 UINT8 *ip;
760 struct png_info p;
761
762 memset (&p, 0, sizeof (struct png_info));
763 p.xscale = p.yscale = p.source_gamma = 0.0;
764 p.palette = p.trans = p.image = p.zimage = p.fimage = NULL;
765 p.width = bitmap->width;
766 p.height = bitmap->height;
767
768 if ((Machine->color_depth == 16) && (Machine->drv->total_colors <= 256))
769 {
770 p.color_type = 3;
771 if((p.palette = (UINT8 *)malloc (3*256))==NULL)
772 {
773 logerror("Out of memory\n");
774 return 0;
775 }
776 memset (p.palette, 0, 3*256);
777 /* get palette */
778 for (i = 0; i < Machine->drv->total_colors; i++)
779 palette_get_color(i,&p.palette[3*i],&p.palette[3*i+1],&p.palette[3*i+2]);
780
781 p.num_palette = 256;
782 if((p.image = (UINT8 *)malloc (p.height*p.width))==NULL)
783 {
784 logerror("Out of memory\n");
785 return 0;
786 }
787
788 for (i = 0; i < p.height; i++)
789 for (j = 0; j < p.width; j++)
790 p.image[i * p.width + j] = ((UINT16 *)bitmap->line[i])[j];
791
792 png_delete_unused_colors (&p);
793 p.bit_depth = p.num_palette > 16 ? 8 : p.num_palette > 4 ? 4 : p.num_palette > 2 ? 2 : 1;
794 p.rowbytes=ceil((p.width*p.bit_depth)/8.0);
795 if (png_pack_buffer (&p) == 0)
796 return 0;
797
798 }
799 else
800 {
801 p.color_type = 2;
802 p.rowbytes = p.width * 3;
803 p.bit_depth = 8;
804 if((p.image = (UINT8 *)malloc (p.height * p.rowbytes))==NULL)
805 {
806 logerror("Out of memory\n");
807 return 0;
808 }
809
810 ip = p.image;
811
812 switch (Machine->color_depth)
813 {
814 case 16: /* 16BIT */
815 for (i = 0; i < p.height; i++)
816 for (j = 0; j < p.width; j++)
817 {
818 palette_get_color(((UINT16 *)bitmap->line[i])[j],ip, ip+1, ip+2);
819 ip += 3;
820 }
821 break;
822 case 15: /* DIRECT_15BIT */
823 for (i = 0; i < p.height; i++)
824 for (j = 0; j < p.width; j++)
825 {
826 color = ((UINT16 *)bitmap->line[i])[j];
827
828 r = (color & direct_rgb_components[0]) / (direct_rgb_components[0] / 0x1f);
829 g = (color & direct_rgb_components[1]) / (direct_rgb_components[1] / 0x1f);
830 b = (color & direct_rgb_components[2]) / (direct_rgb_components[2] / 0x1f);
831
832 *ip++ = (r << 3) | (r >> 2);
833 *ip++ = (g << 3) | (g >> 2);
834 *ip++ = (b << 3) | (b >> 2);
835 }
836 break;
837 case 32: /* DIRECT_32BIT */
838 for (i = 0; i < p.height; i++)
839 for (j = 0; j < p.width; j++)
840 {
841 color = ((UINT32 *)bitmap->line[i])[j];
842
843 r = (color & direct_rgb_components[0]) / (direct_rgb_components[0] / 0xff);
844 g = (color & direct_rgb_components[1]) / (direct_rgb_components[1] / 0xff);
845 b = (color & direct_rgb_components[2]) / (direct_rgb_components[2] / 0xff);
846
847 *ip++ = r;
848 *ip++ = g;
849 *ip++ = b;
850 }
851 break;
852 default:
853 logerror("Unknown color depth\n");
854 break;
855 }
856 }
857 if(png_filter (&p)==0)
858 return 0;
859
860 if (png_deflate_image(&p)==0)
861 return 0;
862
863 if (png_write_datastream(fp, &p)==0)
864 return 0;
865
866 if (p.palette) free (p.palette);
867 if (p.image) free (p.image);
868 if (p.zimage) free (p.zimage);
869 if (p.fimage) free (p.fimage);
870 return 1;
871 }
872
873 int png_write_bitmap(void *fp, struct mame_bitmap *bitmap)
874 {
875 char text[1024];
876
877 #ifdef MESS
878 sprintf (text, "MESS %s", build_version);
879 #else
880 sprintf (text, "MAME %s", build_version);
881 #endif
882 png_add_text("Software", text);
883 sprintf (text, "%s %s", Machine->gamedrv->manufacturer, Machine->gamedrv->description);
884 png_add_text("System", text);
885
886 if(png_write_sig(fp) == 0)
887 return 0;
888
889 if(png_create_datastream(fp, bitmap) == 0)
890 return 0;
891
892 return 1;
893 }
894
895 /********************************************************************************
896
897 MNG write functions
898
899 ********************************************************************************/
900
901 static int mng_status;
902
903 int mng_capture_start(void *fp, struct mame_bitmap *bitmap)
904 {
905 UINT8 mhdr[28];
906 /* UINT8 term; */
907
908 if (osd_fwrite(fp, MNG_Signature, 8) != 8)
909 {
910 logerror("MNG sig write failed\n");
911 return 0;
912 }
913
914 memset (mhdr, 0, 28);
915 convert_to_network_order(bitmap->width, mhdr);
916 convert_to_network_order(bitmap->height, mhdr+4);
917 convert_to_network_order(Machine->drv->frames_per_second, mhdr+8);
918 convert_to_network_order(0x0041, mhdr+24); /* Simplicity profile */
919 /* frame count and play time unspecified because
920 we don't know at this stage */
921 if (write_chunk(fp, MNG_CN_MHDR, mhdr, 28)==0)
922 return 0;
923
924 /* term = 0x03; loop sequence */
925 /* if (write_chunk(fp, MNG_CN_TERM, &term, 1)==0) */
926 /* return 0; */
927
928 mng_status = 1;
929 return 1;
930 }
931
932 int mng_capture_frame(void *fp, struct mame_bitmap *bitmap)
933 {
934 if (mng_status)
935 {
936 if(png_create_datastream(fp, bitmap) == 0)
937 return 0;
938 return 1;
939 }
940 else
941 {
942 logerror("MNG recording not running\n");
943 return 0;
944 }
945 }
946
947 int mng_capture_stop(void *fp)
948 {
949 if (write_chunk(fp, MNG_CN_MEND, NULL, 0)==0)
950 return 0;
951
952 mng_status = 0;
953 return 1;
954 }
955
956 int mng_capture_status(void)
957 {
958 return mng_status;
959 }
960

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26