Mercurial > hg > dmlib
comparison gfxconv.c @ 415:d94f4bcb4be3
IFFMaster RAW output works now, at least to some extent.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sat, 03 Nov 2012 03:50:42 +0200 |
parents | b529b7e8ff83 |
children | 238e6baf01a8 |
comparison
equal
deleted
inserted
replaced
414:c452a459e552 | 415:d94f4bcb4be3 |
---|---|
7 */ | 7 */ |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include "dmlib.h" | 9 #include "dmlib.h" |
10 #include "dmargs.h" | 10 #include "dmargs.h" |
11 #include "dmfile.h" | 11 #include "dmfile.h" |
12 #include "dmbstr.h" | |
12 #include "dmmutex.h" | 13 #include "dmmutex.h" |
13 #include "lib64gfx.h" | 14 #include "lib64gfx.h" |
14 | 15 |
15 //#define UNFINISHED 1 | 16 //#define UNFINISHED 1 |
16 | 17 |
75 optPlanedWidth = 1, | 76 optPlanedWidth = 1, |
76 optBPP = 4; | 77 optBPP = 4; |
77 int optInSkip = 0; | 78 int optInSkip = 0; |
78 BOOL optInMulticolor = FALSE, | 79 BOOL optInMulticolor = FALSE, |
79 optSequential = FALSE, | 80 optSequential = FALSE, |
80 optPaletted = FALSE; | 81 optPaletted = FALSE, |
82 optInterleave = FALSE; | |
81 int optColors[C64_MAX_COLORS]; | 83 int optColors[C64_MAX_COLORS]; |
82 | 84 |
83 | 85 |
84 static DMOptArg optList[] = | 86 static DMOptArg optList[] = |
85 { | 87 { |
96 #ifdef UNFINISHED | 98 #ifdef UNFINISHED |
97 {10, 'b', "bformat", "Force input bitmap format (see below)", OPT_ARGREQ }, | 99 {10, 'b', "bformat", "Force input bitmap format (see below)", OPT_ARGREQ }, |
98 #endif | 100 #endif |
99 {11, 'w', "width", "Item width (number of items per row, min 1)", OPT_ARGREQ }, | 101 {11, 'w', "width", "Item width (number of items per row, min 1)", OPT_ARGREQ }, |
100 {12, 'P', "paletted", "Use indexed/paletted output (png, pcx output only)", OPT_NONE }, | 102 {12, 'P', "paletted", "Use indexed/paletted output (png, pcx output only)", OPT_NONE }, |
101 {13, 'b', "bpp", "Bits per pixel (certain image output formats)", OPT_ARGREQ }, | 103 {13, 'b', "bplanes", "Bits per pixel OR # of bitplanes (certain output formats)", OPT_ARGREQ }, |
104 {14, 'I', "interleave", "Interleave scanlines (default: output whole planes)", OPT_NONE }, | |
102 }; | 105 }; |
103 | 106 |
104 static const int optListN = sizeof(optList) / sizeof(optList[0]); | 107 static const int optListN = sizeof(optList) / sizeof(optList[0]); |
105 | 108 |
106 | 109 |
272 } | 275 } |
273 break; | 276 break; |
274 | 277 |
275 case 12: | 278 case 12: |
276 optPaletted = TRUE; | 279 optPaletted = TRUE; |
280 break; | |
281 | |
282 case 13: | |
283 { | |
284 int tmp = atoi(optArg); | |
285 if (tmp < 1 || tmp > 8) | |
286 { | |
287 dmError("Invalid bitplanes/bpp value '%s'.\n", optArg); | |
288 return FALSE; | |
289 } | |
290 optBPP = tmp; | |
291 } | |
292 break; | |
293 | |
294 case 14: | |
295 optInterleave = TRUE; | |
277 break; | 296 break; |
278 | 297 |
279 default: | 298 default: |
280 dmError("Unknown option '%s'.\n", currArg); | 299 dmError("Unknown option '%s'.\n", currArg); |
281 return FALSE; | 300 return FALSE; |
507 | 526 |
508 return 0; | 527 return 0; |
509 } | 528 } |
510 | 529 |
511 | 530 |
512 typedef struct | 531 int dmWriteIFFMasterRAWImageFILE(FILE *fp, DMImage *img, int scale, int nplanes, BOOL interleave) |
513 { | 532 { |
514 int bpp; | 533 int xc, yc, plane, res; |
515 DMImage *img; | 534 DMBitStream bs; |
516 FILE *fp; | 535 |
517 } DMRawData; | 536 if ((res = dmInitBitStream(&bs, fp)) != DMERR_OK) |
518 | 537 return res; |
519 | 538 |
520 static BOOL dmWriteIFFMasterRAWRow(void *cbdata, Uint8 *row, size_t len) | 539 if (interleave) |
521 { | 540 { |
522 DMRawData *raw = (DMRawData *) cbdata; | 541 // Output bitplanes in interleaved format (each plane of line sequentially) |
523 size_t i; | 542 for (yc = 0; yc < img->height; yc++) |
524 | 543 { |
525 for (i = 0; i < len; i++) | 544 for (plane = 0; plane < nplanes; plane++) |
526 { | 545 { |
527 } | 546 Uint8 *sp = img->data + yc * img->pitch; |
528 | 547 for (xc = 0; xc < img->width; xc++) |
529 return fwrite(row, sizeof(Uint8), len, raw->fp) == len; | 548 { |
530 } | 549 if (!dmPutBits(&bs, (sp[xc] & (1 << plane)) ? 1 : 0, 1)) |
531 | 550 return DMERR_FWRITE; |
532 | 551 } |
533 int dmWriteIFFMasterRAWImageFILE(FILE *fp, DMImage *img, int scale, int bpp) | 552 } |
534 { | 553 } |
535 DMRawData raw; | 554 } |
536 | 555 else |
537 raw.fp = fp; | 556 { |
538 raw.img = img; | 557 // Output each bitplane in sequence |
539 raw.bpp = bpp; | 558 for (plane = 0; plane < nplanes; plane++) |
540 | 559 { |
541 return dmWriteImageData(img, (void *) &raw, dmWriteIFFMasterRAWRow, scale, DM_IFMT_PALETTE); | 560 for (yc = 0; yc < img->height; yc++) |
542 } | 561 { |
543 | 562 Uint8 *sp = img->data + yc * img->pitch; |
544 int dmWriteIFFMasterRAWImage(const char *filename, DMImage *img, int scale, int bpp) | 563 for (xc = 0; xc < img->width; xc++) |
564 { | |
565 if (!dmPutBits(&bs, (sp[xc] & (1 << plane)) ? 1 : 0, 1)) | |
566 return DMERR_FWRITE; | |
567 } | |
568 } | |
569 } | |
570 } | |
571 | |
572 return dmFlushBitStream(&bs); | |
573 } | |
574 | |
575 int dmWriteIFFMasterRAWImage(const char *filename, DMImage *img, int scale, int nplanes, BOOL interleave) | |
545 { | 576 { |
546 FILE *fp; | 577 FILE *fp; |
547 int res; | 578 int res; |
548 | 579 |
549 if ((fp = fopen(filename, "wb")) == NULL) | 580 if ((fp = fopen(filename, "wb")) == NULL) |
550 { | 581 { |
551 dmError("IFFMasterRAW: Could not open file '%s' for writing.\n", filename); | 582 dmError("IFFMasterRAW: Could not open file '%s' for writing.\n", filename); |
552 return -15; | 583 return DMERR_FOPEN; |
553 } | 584 } |
554 | 585 |
555 res = dmWriteIFFMasterRAWImageFILE(fp, img, scale, bpp); | 586 res = dmWriteIFFMasterRAWImageFILE(fp, img, scale, nplanes, interleave); |
556 | 587 |
557 fclose(fp); | 588 fclose(fp); |
558 return res; | 589 return res; |
559 } | 590 } |
560 | 591 |
584 | 615 |
585 // Create output file | 616 // Create output file |
586 if ((fp = fopen(filename, "wb")) == NULL) | 617 if ((fp = fopen(filename, "wb")) == NULL) |
587 { | 618 { |
588 dmError("PPM: could not open file '%s' for writing.\n", filename); | 619 dmError("PPM: could not open file '%s' for writing.\n", filename); |
589 return -15; | 620 return DMERR_FOPEN; |
590 } | 621 } |
591 | 622 |
592 res = dmWritePPMImageFILE(fp, img, scale); | 623 res = dmWritePPMImageFILE(fp, img, scale); |
593 | 624 |
594 fclose(fp); | 625 fclose(fp); |
614 int dmWritePNGImageFILE(FILE *fp, DMImage *img, int scale, int format) | 645 int dmWritePNGImageFILE(FILE *fp, DMImage *img, int scale, int format) |
615 { | 646 { |
616 png_structp png_ptr = NULL; | 647 png_structp png_ptr = NULL; |
617 png_infop info_ptr = NULL; | 648 png_infop info_ptr = NULL; |
618 png_colorp palette = NULL; | 649 png_colorp palette = NULL; |
619 int fmt; | 650 int fmt, res = DMERR_OK; |
620 | 651 |
621 // Create PNG structures | 652 // Create PNG structures |
622 png_ptr = png_create_write_struct( | 653 png_ptr = png_create_write_struct( |
623 PNG_LIBPNG_VER_STRING, | 654 PNG_LIBPNG_VER_STRING, |
624 NULL, NULL, NULL); | 655 NULL, NULL, NULL); |
625 | 656 |
626 if (png_ptr == NULL) | 657 if (png_ptr == NULL) |
627 { | 658 { |
628 dmError("PNG: png_create_write_struct() failed.\n"); | 659 dmError("PNG: png_create_write_struct() failed.\n"); |
660 res = DMERR_MALLOC; | |
629 goto error; | 661 goto error; |
630 } | 662 } |
631 | 663 |
632 info_ptr = png_create_info_struct(png_ptr); | 664 info_ptr = png_create_info_struct(png_ptr); |
633 if (info_ptr == NULL) | 665 if (info_ptr == NULL) |
634 { | 666 { |
635 dmError("PNG: png_create_info_struct(%p) failed.\n", png_ptr); | 667 dmError("PNG: png_create_info_struct(%p) failed.\n", png_ptr); |
668 res = DMERR_INIT_FAIL; | |
636 goto error; | 669 goto error; |
637 } | 670 } |
638 | 671 |
639 if (setjmp(png_jmpbuf(png_ptr))) | 672 if (setjmp(png_jmpbuf(png_ptr))) |
640 { | 673 { |
641 dmError("PNG: Error during image writing..\n"); | 674 dmError("PNG: Error during image writing..\n"); |
675 res = DMERR_INIT_FAIL; | |
642 goto error; | 676 goto error; |
643 } | 677 } |
644 | 678 |
645 png_init_io(png_ptr, fp); | 679 png_init_io(png_ptr, fp); |
646 | 680 |
697 dmWriteImageData(img, (void *) png_ptr, dmWritePNGRow, scale, format); | 731 dmWriteImageData(img, (void *) png_ptr, dmWritePNGRow, scale, format); |
698 | 732 |
699 // Write footer | 733 // Write footer |
700 png_write_end(png_ptr, NULL); | 734 png_write_end(png_ptr, NULL); |
701 | 735 |
702 png_free(png_ptr, palette); | |
703 palette = NULL; | |
704 | |
705 // Deallocate shit | |
706 if (png_ptr && info_ptr) | |
707 { | |
708 png_destroy_write_struct(&png_ptr, &info_ptr); | |
709 } | |
710 | |
711 return 0; | |
712 | |
713 error: | 736 error: |
714 png_free(png_ptr, palette); | 737 png_free(png_ptr, palette); |
715 palette = NULL; | 738 palette = NULL; |
716 | 739 |
717 if (png_ptr && info_ptr) | 740 if (png_ptr && info_ptr) |
718 { | |
719 png_destroy_write_struct(&png_ptr, &info_ptr); | 741 png_destroy_write_struct(&png_ptr, &info_ptr); |
720 } | 742 |
721 return -15; | 743 return res; |
722 } | 744 } |
723 | 745 |
724 | 746 |
725 int dmWritePNGImage(const char *filename, DMImage *img, int scale, int format) | 747 int dmWritePNGImage(const char *filename, DMImage *img, int scale, int format) |
726 { | 748 { |
728 FILE *fp; | 750 FILE *fp; |
729 | 751 |
730 if ((fp = fopen(filename, "wb")) == NULL) | 752 if ((fp = fopen(filename, "wb")) == NULL) |
731 { | 753 { |
732 dmError("PNG: could not open file '%s' for writing.\n", filename); | 754 dmError("PNG: could not open file '%s' for writing.\n", filename); |
733 return -15; | 755 return DMERR_FOPEN; |
734 } | 756 } |
735 | 757 |
736 res = dmWritePNGImageFILE(fp, img, scale, format); | 758 res = dmWritePNGImageFILE(fp, img, scale, format); |
737 | 759 |
738 fclose(fp); | 760 fclose(fp); |
848 | 870 |
849 return TRUE; | 871 return TRUE; |
850 } | 872 } |
851 | 873 |
852 | 874 |
853 int dmWritePCXImage(const char *filename, DMImage *img, int scale, BOOL paletted) | 875 int dmWritePCXImageFILE(FILE *fp, DMImage *img, int scale, BOOL paletted) |
854 { | 876 { |
855 DMPCXData pcx; | 877 DMPCXData pcx; |
856 DMPCXHeader hdr; | 878 DMPCXHeader hdr; |
857 int res; | 879 int res; |
858 | 880 |
859 // Create output file | 881 // Create output file |
860 pcx.buf = NULL; | 882 pcx.buf = NULL; |
861 pcx.format = paletted ? DM_IFMT_PALETTE : DM_IFMT_RGB_PLANE; | 883 pcx.format = paletted ? DM_IFMT_PALETTE : DM_IFMT_RGB_PLANE; |
862 pcx.header = &hdr; | 884 pcx.header = &hdr; |
863 if ((pcx.fp = fopen(filename, "wb")) == NULL) | 885 pcx.fp = fp; |
864 { | |
865 dmError("PCX: Could not open file '%s' for writing.\n", filename); | |
866 res = DMERR_FOPEN; | |
867 goto error; | |
868 } | |
869 | 886 |
870 // Create PCX header | 887 // Create PCX header |
871 memset(&hdr, 0, sizeof(hdr)); | 888 memset(&hdr, 0, sizeof(hdr)); |
872 if (paletted) | 889 if (paletted) |
873 { | 890 { |
969 dm_fwrite_byte(pcx.fp, 0); | 986 dm_fwrite_byte(pcx.fp, 0); |
970 } | 987 } |
971 } | 988 } |
972 | 989 |
973 error: | 990 error: |
974 if (pcx.fp != NULL) | |
975 fclose(pcx.fp); | |
976 | |
977 dmFree(pcx.buf); | 991 dmFree(pcx.buf); |
978 | 992 return res; |
993 } | |
994 | |
995 | |
996 int dmWritePCXImage(const char *filename, DMImage *img, int scale, BOOL paletted) | |
997 { | |
998 FILE *fp; | |
999 int res; | |
1000 | |
1001 if ((fp = fopen(filename, "wb")) == NULL) | |
1002 { | |
1003 dmError("PCX: Could not open file '%s' for writing.\n", filename); | |
1004 return DMERR_FOPEN; | |
1005 } | |
1006 | |
1007 res = dmWritePCXImageFILE(fp, img, scale, paletted); | |
1008 | |
1009 fclose(fp); | |
979 return res; | 1010 return res; |
980 } | 1011 } |
981 | 1012 |
982 | 1013 |
983 static BOOL dmPCXDecodeRLERow(FILE *fp, Uint8 *buf, const size_t bufLen) | 1014 static BOOL dmPCXDecodeRLERow(FILE *fp, Uint8 *buf, const size_t bufLen) |
1282 return 0; | 1313 return 0; |
1283 } | 1314 } |
1284 #endif | 1315 #endif |
1285 | 1316 |
1286 | 1317 |
1287 int dmWriteImage(char *filename, DMImage *image, int format, BOOL paletted, int scale, int bpp) | 1318 int dmWriteImage(char *filename, DMImage *image) |
1288 { | 1319 { |
1289 switch (format) | 1320 switch (optOutFormat) |
1290 { | 1321 { |
1291 #ifdef HAVE_LIBPNG | 1322 #ifdef HAVE_LIBPNG |
1292 case OUTFMT_PNG: | 1323 case OUTFMT_PNG: |
1293 return dmWritePNGImage(filename, image, scale, paletted ? DM_IFMT_PALETTE : DM_IFMT_RGBA); | 1324 return dmWritePNGImage(filename, image, optScale, optPaletted ? DM_IFMT_PALETTE : DM_IFMT_RGBA); |
1294 #endif | 1325 #endif |
1295 | 1326 |
1296 case OUTFMT_PPM: | 1327 case OUTFMT_PPM: |
1297 return dmWritePPMImage(filename, image, scale); | 1328 return dmWritePPMImage(filename, image, optScale); |
1298 | 1329 |
1299 case OUTFMT_PCX: | 1330 case OUTFMT_PCX: |
1300 return dmWritePCXImage(filename, image, scale, paletted); | 1331 return dmWritePCXImage(filename, image, optScale, optPaletted); |
1301 | 1332 |
1302 case OUTFMT_ARAW: | 1333 case OUTFMT_ARAW: |
1303 { | 1334 { |
1304 int res; | 1335 int res; |
1305 char *palFilename = dm_strdup_printf("%s.pal", filename); | 1336 char *palFilename = dm_strdup_printf("%s.pal", filename); |
1306 res = dmWriteIFFMasterRAWPalette(palFilename, image, 1 << bpp); | 1337 res = dmWriteIFFMasterRAWPalette(palFilename, image, 1 << optBPP); |
1307 dmFree(palFilename); | 1338 dmFree(palFilename); |
1308 if (res != DMERR_OK) | 1339 if (res != DMERR_OK) |
1309 return res; | 1340 return res; |
1310 | 1341 |
1311 return dmWriteIFFMasterRAWImage(filename, image, scale, bpp); | 1342 return dmWriteIFFMasterRAWImage(filename, image, optScale, optBPP, optInterleave); |
1312 } | 1343 } |
1313 | 1344 |
1314 default: | 1345 default: |
1315 return FALSE; | 1346 return FALSE; |
1316 } | 1347 } |
1466 { | 1497 { |
1467 dmError("Could not allocate memory for filename template?\n"); | 1498 dmError("Could not allocate memory for filename template?\n"); |
1468 goto error; | 1499 goto error; |
1469 } | 1500 } |
1470 | 1501 |
1471 dmWriteImage(outFilename, outImage, optOutFormat, optPaletted, optScale, optBPP); | 1502 dmWriteImage(outFilename, outImage); |
1472 dmFree(outFilename); | 1503 dmFree(outFilename); |
1473 } | 1504 } |
1474 else | 1505 else |
1475 { | 1506 { |
1476 if (++outX >= optPlanedWidth) | 1507 if (++outX >= optPlanedWidth) |
1483 itemCount++; | 1514 itemCount++; |
1484 } | 1515 } |
1485 | 1516 |
1486 if (!optSequential) | 1517 if (!optSequential) |
1487 { | 1518 { |
1488 dmWriteImage(optOutFilename, outImage, optOutFormat, optPaletted, optScale, optBPP); | 1519 dmWriteImage(optOutFilename, outImage); |
1489 } | 1520 } |
1490 | 1521 |
1491 dmImageFree(outImage); | 1522 dmImageFree(outImage); |
1492 } | 1523 } |
1493 | 1524 |
1649 { | 1680 { |
1650 case OUTFMT_PCX: | 1681 case OUTFMT_PCX: |
1651 case OUTFMT_PPM: | 1682 case OUTFMT_PPM: |
1652 case OUTFMT_PNG: | 1683 case OUTFMT_PNG: |
1653 case OUTFMT_ARAW: | 1684 case OUTFMT_ARAW: |
1654 res = dmWriteImage(optOutFilename, img, optOutFormat, optPaletted, optScale, optBPP); | 1685 res = dmWriteImage(optOutFilename, img); |
1655 break; | 1686 break; |
1656 } | 1687 } |
1657 } | 1688 } |
1658 break; | 1689 break; |
1659 } | 1690 } |