Mercurial > hg > dmlib
comparison gfxconv.c @ 435:e4a3f183e463
Modularize some more.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sat, 03 Nov 2012 16:08:30 +0200 |
parents | b583a682f12d |
children | 2a4de5fe4003 |
comparison
equal
deleted
inserted
replaced
434:380c226c75af | 435:e4a3f183e463 |
---|---|
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" | |
13 #include "dmmutex.h" | 12 #include "dmmutex.h" |
13 #include "libgfx.h" | |
14 #include "lib64gfx.h" | 14 #include "lib64gfx.h" |
15 | 15 |
16 //#define UNFINISHED 1 | 16 //#define UNFINISHED 1 |
17 | |
18 #ifdef DM_USE_LIBPNG | |
19 #include <png.h> | |
20 #endif | |
21 | |
22 enum | |
23 { | |
24 IMGFMT_PNG, | |
25 IMGFMT_PPM, | |
26 IMGFMT_PCX, | |
27 IMGFMT_ARAW, | |
28 | |
29 IMGFMT_LAST | |
30 }; | |
31 | |
32 static const char *imageFormatList[IMGFMT_LAST] = | |
33 { | |
34 "PNG", | |
35 "PPM", | |
36 "PCX", | |
37 "ARAW", | |
38 }; | |
39 | 17 |
40 enum | 18 enum |
41 { | 19 { |
42 FFMT_AUTO = 0, | 20 FFMT_AUTO = 0, |
43 | 21 |
118 int optInFormat = FFMT_AUTO, | 96 int optInFormat = FFMT_AUTO, |
119 optOutFormat = FFMT_ASCII, | 97 optOutFormat = FFMT_ASCII, |
120 optInSubFormat = IMGFMT_PNG, | 98 optInSubFormat = IMGFMT_PNG, |
121 optOutSubFormat = IMGFMT_PNG, | 99 optOutSubFormat = IMGFMT_PNG, |
122 optItemCount = -1, | 100 optItemCount = -1, |
123 optScale = 2, | |
124 optPlanedWidth = 1, | 101 optPlanedWidth = 1, |
125 optForcedFormat = -1, | 102 optForcedFormat = -1; |
126 optBPP = 4; | |
127 int optInSkip = 0; | 103 int optInSkip = 0; |
128 BOOL optInMulticolor = FALSE, | 104 BOOL optInMulticolor = FALSE, |
129 optSequential = FALSE, | 105 optSequential = FALSE; |
130 optPaletted = FALSE, | |
131 optInterleave = FALSE; | |
132 int optColors[C64_MAX_COLORS]; | 106 int optColors[C64_MAX_COLORS]; |
133 | 107 |
108 DMImageSpec optSpec = | |
109 { | |
110 .scale = 2, | |
111 .nplanes = 4, | |
112 .interleave = FALSE, | |
113 .paletted = FALSE, | |
114 .format = 0, | |
115 }; | |
134 | 116 |
135 static DMOptArg optList[] = | 117 static DMOptArg optList[] = |
136 { | 118 { |
137 { 0, '?', "help", "Show this help", OPT_NONE }, | 119 { 0, '?', "help", "Show this help", OPT_NONE }, |
138 { 15, 'v', "verbose", "Increase verbosity", OPT_NONE }, | 120 { 15, 'v', "verbose", "Increase verbosity", OPT_NONE }, |
342 if (tmp < 1 || tmp > 50) | 324 if (tmp < 1 || tmp > 50) |
343 { | 325 { |
344 dmError("Invalid scale value '%s'.\n", optArg); | 326 dmError("Invalid scale value '%s'.\n", optArg); |
345 return FALSE; | 327 return FALSE; |
346 } | 328 } |
347 optScale = tmp; | 329 optSpec.scale = tmp; |
348 } | 330 } |
349 break; | 331 break; |
350 | 332 |
351 case 11: | 333 case 11: |
352 { | 334 { |
359 optPlanedWidth = tmp; | 341 optPlanedWidth = tmp; |
360 } | 342 } |
361 break; | 343 break; |
362 | 344 |
363 case 12: | 345 case 12: |
364 optPaletted = TRUE; | 346 optSpec.paletted = TRUE; |
365 break; | 347 break; |
366 | 348 |
367 case 13: | 349 case 13: |
368 { | 350 { |
369 int tmp = atoi(optArg); | 351 int tmp = atoi(optArg); |
370 if (tmp < 1 || tmp > 8) | 352 if (tmp < 1 || tmp > 8) |
371 { | 353 { |
372 dmError("Invalid bitplanes/bpp value '%s'.\n", optArg); | 354 dmError("Invalid bitplanes/bpp value '%s'.\n", optArg); |
373 return FALSE; | 355 return FALSE; |
374 } | 356 } |
375 optBPP = tmp; | 357 optSpec.nplanes = tmp; |
376 } | 358 } |
377 break; | 359 break; |
378 | 360 |
379 case 14: | 361 case 14: |
380 optInterleave = TRUE; | 362 optSpec.interleave = TRUE; |
381 break; | 363 break; |
382 | 364 |
383 default: | 365 default: |
384 dmError("Unknown option '%s'.\n", currArg); | 366 dmError("Unknown option '%s'.\n", currArg); |
385 return FALSE; | 367 return FALSE; |
487 } | 469 } |
488 (*offs)++; | 470 (*offs)++; |
489 } | 471 } |
490 | 472 |
491 | 473 |
492 int dmWriteImageData(DMImage *img, void *cbdata, BOOL (*writeRowCB)(void *, Uint8 *, size_t), int scale, int format) | |
493 { | |
494 int x, y, yscale, xscale, res = 0, rowSize, rowWidth; | |
495 Uint8 *row = NULL; | |
496 | |
497 // Allocate memory for row buffer | |
498 rowWidth = img->width * scale; | |
499 rowSize = rowWidth * dmImageGetBytesPerPixel(format); | |
500 | |
501 if ((row = dmMalloc(rowSize + 16)) == NULL) | |
502 { | |
503 res = DMERR_MALLOC; | |
504 goto done; | |
505 } | |
506 | |
507 // Generate the image | |
508 for (y = 0; y < img->height; y++) | |
509 { | |
510 Uint8 *ptr = row, | |
511 *ptr1 = row, | |
512 *ptr2 = ptr1 + rowWidth, | |
513 *ptr3 = ptr2 + rowWidth; | |
514 | |
515 for (x = 0; x < img->width; x++) | |
516 { | |
517 Uint8 c = img->data[(y * img->pitch) + x], qr, qg, qb, qa; | |
518 switch (format) | |
519 { | |
520 case DM_IFMT_PALETTE: | |
521 for (xscale = 0; xscale < scale; xscale++) | |
522 *ptr++ = c; | |
523 break; | |
524 | |
525 case DM_IFMT_RGBA: | |
526 qr = img->pal[c].r; | |
527 qg = img->pal[c].g; | |
528 qb = img->pal[c].b; | |
529 qa = (c == img->ctrans) ? 0 : 255; | |
530 | |
531 for (xscale = 0; xscale < scale; xscale++) | |
532 { | |
533 *ptr++ = qr; | |
534 *ptr++ = qg; | |
535 *ptr++ = qb; | |
536 *ptr++ = qa; | |
537 } | |
538 break; | |
539 | |
540 case DM_IFMT_RGB: | |
541 qr = img->pal[c].r; | |
542 qg = img->pal[c].g; | |
543 qb = img->pal[c].b; | |
544 | |
545 for (xscale = 0; xscale < scale; xscale++) | |
546 { | |
547 *ptr++ = qr; | |
548 *ptr++ = qg; | |
549 *ptr++ = qb; | |
550 } | |
551 break; | |
552 | |
553 case DM_IFMT_RGB_PLANE: | |
554 qr = img->pal[c].r; | |
555 qg = img->pal[c].g; | |
556 qb = img->pal[c].b; | |
557 | |
558 for (xscale = 0; xscale < scale; xscale++) | |
559 { | |
560 *ptr1++ = qr; | |
561 *ptr2++ = qg; | |
562 *ptr3++ = qb; | |
563 } | |
564 break; | |
565 } | |
566 } | |
567 | |
568 for (yscale = 0; yscale < scale; yscale++) | |
569 { | |
570 if (!writeRowCB(cbdata, row, rowSize)) | |
571 { | |
572 res = DMERR_FWRITE; | |
573 goto done; | |
574 } | |
575 } | |
576 } | |
577 | |
578 done: | |
579 dmFree(row); | |
580 return res; | |
581 } | |
582 | |
583 | |
584 #define DMCOL(x) (((x) >> 4) & 0xf) | |
585 | |
586 int dmWriteIFFMasterRAWPalette(const char *filename, DMImage *img, int ncolors) | |
587 { | |
588 FILE *fp; | |
589 int i; | |
590 | |
591 if ((fp = fopen(filename, "w")) == NULL) | |
592 { | |
593 dmError("IFFMasterRAW: Could not open file '%s' for writing.\n", filename); | |
594 return -15; | |
595 } | |
596 | |
597 for (i = 0; i < ncolors; i++) | |
598 { | |
599 int color; | |
600 if (i < img->ncolors) | |
601 { | |
602 color = (DMCOL(img->pal[i].r) << 8) | | |
603 (DMCOL(img->pal[i].g) << 4) | | |
604 (DMCOL(img->pal[i].b)); | |
605 } | |
606 else | |
607 color = 0; | |
608 | |
609 fprintf(fp, "\tdc.w $%04X\n", color); | |
610 } | |
611 | |
612 return 0; | |
613 } | |
614 | |
615 | |
616 int dmWriteIFFMasterRAWImageFILE(FILE *fp, DMImage *img, int scale, int nplanes, BOOL interleave) | |
617 { | |
618 int xc, yc, plane, res; | |
619 DMBitStream bs; | |
620 | |
621 if ((res = dmInitBitStream(&bs, fp)) != DMERR_OK) | |
622 return res; | |
623 | |
624 if (interleave) | |
625 { | |
626 // Output bitplanes in interleaved format (each plane of line sequentially) | |
627 for (yc = 0; yc < img->height; yc++) | |
628 { | |
629 for (plane = 0; plane < nplanes; plane++) | |
630 { | |
631 Uint8 *sp = img->data + yc * img->pitch; | |
632 for (xc = 0; xc < img->width; xc++) | |
633 { | |
634 if (!dmPutBits(&bs, (sp[xc] & (1 << plane)) ? 1 : 0, 1)) | |
635 return DMERR_FWRITE; | |
636 } | |
637 } | |
638 } | |
639 } | |
640 else | |
641 { | |
642 // Output each bitplane in sequence | |
643 for (plane = 0; plane < nplanes; plane++) | |
644 { | |
645 for (yc = 0; yc < img->height; yc++) | |
646 { | |
647 Uint8 *sp = img->data + yc * img->pitch; | |
648 for (xc = 0; xc < img->width; xc++) | |
649 { | |
650 if (!dmPutBits(&bs, (sp[xc] & (1 << plane)) ? 1 : 0, 1)) | |
651 return DMERR_FWRITE; | |
652 } | |
653 } | |
654 } | |
655 } | |
656 | |
657 return dmFlushBitStream(&bs); | |
658 } | |
659 | |
660 int dmWriteIFFMasterRAWImage(const char *filename, DMImage *img, int scale, int nplanes, BOOL interleave) | |
661 { | |
662 FILE *fp; | |
663 int res; | |
664 | |
665 if ((fp = fopen(filename, "wb")) == NULL) | |
666 { | |
667 dmError("IFFMasterRAW: Could not open file '%s' for writing.\n", filename); | |
668 return DMERR_FOPEN; | |
669 } | |
670 | |
671 res = dmWriteIFFMasterRAWImageFILE(fp, img, scale, nplanes, interleave); | |
672 | |
673 fclose(fp); | |
674 return res; | |
675 } | |
676 | |
677 | |
678 static BOOL dmWritePPMRow(void *cbdata, Uint8 *row, size_t len) | |
679 { | |
680 return fwrite(row, sizeof(Uint8), len, (FILE *) cbdata) == len; | |
681 } | |
682 | |
683 | |
684 int dmWritePPMImageFILE(FILE *fp, DMImage *img, int scale) | |
685 { | |
686 // Write PPM header | |
687 fprintf(fp, | |
688 "P6\n%d %d\n255\n", | |
689 img->width * scale, img->height * scale); | |
690 | |
691 // Write image data | |
692 return dmWriteImageData(img, (void *) fp, dmWritePPMRow, scale, DM_IFMT_RGB); | |
693 } | |
694 | |
695 | |
696 int dmWritePPMImage(const char *filename, DMImage *img, int scale) | |
697 { | |
698 FILE *fp; | |
699 int res; | |
700 | |
701 // Create output file | |
702 if ((fp = fopen(filename, "wb")) == NULL) | |
703 { | |
704 dmError("PPM: could not open file '%s' for writing.\n", filename); | |
705 return DMERR_FOPEN; | |
706 } | |
707 | |
708 res = dmWritePPMImageFILE(fp, img, scale); | |
709 | |
710 fclose(fp); | |
711 return res; | |
712 } | |
713 | |
714 | |
715 #ifdef DM_USE_LIBPNG | |
716 static BOOL dmWritePNGRow(void *cbdata, Uint8 *row, size_t len) | |
717 { | |
718 png_structp png_ptr = cbdata; | |
719 (void) len; | |
720 | |
721 if (setjmp(png_jmpbuf(png_ptr))) | |
722 return FALSE; | |
723 | |
724 png_write_row(png_ptr, row); | |
725 | |
726 return TRUE; | |
727 } | |
728 | |
729 | |
730 int dmWritePNGImageFILE(FILE *fp, DMImage *img, int scale, int format) | |
731 { | |
732 png_structp png_ptr = NULL; | |
733 png_infop info_ptr = NULL; | |
734 png_colorp palette = NULL; | |
735 int fmt, res = DMERR_OK; | |
736 | |
737 // Create PNG structures | |
738 png_ptr = png_create_write_struct( | |
739 PNG_LIBPNG_VER_STRING, | |
740 NULL, NULL, NULL); | |
741 | |
742 if (png_ptr == NULL) | |
743 { | |
744 dmError("PNG: png_create_write_struct() failed.\n"); | |
745 res = DMERR_MALLOC; | |
746 goto error; | |
747 } | |
748 | |
749 info_ptr = png_create_info_struct(png_ptr); | |
750 if (info_ptr == NULL) | |
751 { | |
752 dmError("PNG: png_create_info_struct(%p) failed.\n", png_ptr); | |
753 res = DMERR_INIT_FAIL; | |
754 goto error; | |
755 } | |
756 | |
757 if (setjmp(png_jmpbuf(png_ptr))) | |
758 { | |
759 dmError("PNG: Error during image writing..\n"); | |
760 res = DMERR_INIT_FAIL; | |
761 goto error; | |
762 } | |
763 | |
764 png_init_io(png_ptr, fp); | |
765 | |
766 // Write PNG header info | |
767 switch (format) | |
768 { | |
769 case DM_IFMT_PALETTE: fmt = PNG_COLOR_TYPE_PALETTE; break; | |
770 case DM_IFMT_RGB : fmt = PNG_COLOR_TYPE_RGB; break; | |
771 case DM_IFMT_RGBA : fmt = PNG_COLOR_TYPE_RGB_ALPHA; break; | |
772 default: | |
773 dmError("PNG: Internal error, unsupported image format %d.\n", format); | |
774 goto error; | |
775 } | |
776 | |
777 png_set_IHDR(png_ptr, info_ptr, | |
778 img->width * scale, | |
779 img->height * scale, | |
780 8, /* bits per component */ | |
781 fmt, | |
782 PNG_INTERLACE_NONE, | |
783 PNG_COMPRESSION_TYPE_DEFAULT, | |
784 PNG_FILTER_TYPE_DEFAULT); | |
785 | |
786 // Palette | |
787 if (format == DM_IFMT_PALETTE) | |
788 { | |
789 int i; | |
790 | |
791 palette = png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * sizeof(png_color)); | |
792 if (palette == NULL) | |
793 { | |
794 dmError("PNG: Could not allocate palette structure."); | |
795 goto error; | |
796 } | |
797 | |
798 memset(palette, 0, PNG_MAX_PALETTE_LENGTH * sizeof(png_color)); | |
799 | |
800 for (i = 0; i < img->ncolors; i++) | |
801 { | |
802 palette[i].red = img->pal[i].r; | |
803 palette[i].green = img->pal[i].g; | |
804 palette[i].blue = img->pal[i].b; | |
805 } | |
806 | |
807 png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH); | |
808 } | |
809 | |
810 // png_set_gAMA(png_ptr, info_ptr, 2.2); | |
811 | |
812 png_write_info(png_ptr, info_ptr); | |
813 | |
814 | |
815 // Write compressed image data | |
816 dmWriteImageData(img, (void *) png_ptr, dmWritePNGRow, scale, format); | |
817 | |
818 // Write footer | |
819 png_write_end(png_ptr, NULL); | |
820 | |
821 error: | |
822 png_free(png_ptr, palette); | |
823 palette = NULL; | |
824 | |
825 if (png_ptr && info_ptr) | |
826 png_destroy_write_struct(&png_ptr, &info_ptr); | |
827 | |
828 return res; | |
829 } | |
830 | |
831 | |
832 int dmWritePNGImage(const char *filename, DMImage *img, int scale, int format) | |
833 { | |
834 int res; | |
835 FILE *fp; | |
836 | |
837 if ((fp = fopen(filename, "wb")) == NULL) | |
838 { | |
839 dmError("PNG: could not open file '%s' for writing.\n", filename); | |
840 return DMERR_FOPEN; | |
841 } | |
842 | |
843 res = dmWritePNGImageFILE(fp, img, scale, format); | |
844 | |
845 fclose(fp); | |
846 return res; | |
847 } | |
848 #endif | |
849 | |
850 | |
851 typedef struct | |
852 { | |
853 Uint8 r,g,b; | |
854 } DMPCXColor; | |
855 | |
856 | |
857 typedef struct | |
858 { | |
859 Uint8 manufacturer, | |
860 version, | |
861 encoding, | |
862 bpp; | |
863 Uint16 xmin, ymin, xmax, ymax; | |
864 Uint16 hres, vres; | |
865 DMPCXColor colormap[16]; | |
866 Uint8 reserved; | |
867 Uint8 nplanes; | |
868 Uint16 bpl; | |
869 Uint16 palinfo; | |
870 Uint8 filler[58]; | |
871 } DMPCXHeader; | |
872 | |
873 typedef struct | |
874 { | |
875 DMPCXHeader *header; | |
876 Uint8 *buf; | |
877 size_t bufLen, bufOffs; | |
878 int format; | |
879 FILE *fp; | |
880 } DMPCXData; | |
881 | |
882 | |
883 static inline Uint8 dmPCXGetByte(Uint8 *row, const size_t len, const size_t soffs) | |
884 { | |
885 return (soffs < len) ? row[soffs] : 0; | |
886 } | |
887 | |
888 static BOOL dmPCXFlush(DMPCXData *pcx) | |
889 { | |
890 BOOL ret = fwrite(pcx->buf, sizeof(Uint8), pcx->bufOffs, pcx->fp) == pcx->bufOffs; | |
891 pcx->bufOffs = 0; | |
892 return ret; | |
893 } | |
894 | |
895 static inline BOOL dmPCXPutByte(DMPCXData *pcx, const Uint8 val) | |
896 { | |
897 if (pcx->bufOffs < pcx->bufLen) | |
898 { | |
899 pcx->buf[pcx->bufOffs++] = val; | |
900 return TRUE; | |
901 } | |
902 else | |
903 return dmPCXFlush(pcx); | |
904 } | |
905 | |
906 BOOL dmWritePCXRow(void *cbdata, Uint8 *row, size_t len) | |
907 { | |
908 DMPCXData *pcx = (DMPCXData *) cbdata; | |
909 int plane; | |
910 | |
911 for (plane = 0; plane < pcx->header->nplanes; plane++) | |
912 { | |
913 size_t soffs = 0; | |
914 Uint8 data = dmPCXGetByte(row, len, soffs++), | |
915 count = 1; | |
916 | |
917 pcx->bufOffs = 0; | |
918 | |
919 while (soffs < pcx->header->bpl) | |
920 { | |
921 if (data == dmPCXGetByte(row, len, soffs) && count < 63) | |
922 { | |
923 count++; | |
924 soffs++; | |
925 } | |
926 else | |
927 { | |
928 if (count == 1 && (data & 0xC0) != 0xC0) | |
929 { | |
930 if (!dmPCXPutByte(pcx, data)) | |
931 return FALSE; | |
932 } | |
933 else | |
934 { | |
935 if (!dmPCXPutByte(pcx, 0xC0 | count) || | |
936 !dmPCXPutByte(pcx, data)) | |
937 return FALSE; | |
938 } | |
939 | |
940 data = dmPCXGetByte(row, len, soffs++); | |
941 count = 1; | |
942 } | |
943 } | |
944 | |
945 if (count > 1) | |
946 { | |
947 if (!dmPCXPutByte(pcx, 0xC0 | count) || | |
948 !dmPCXPutByte(pcx, data)) | |
949 return FALSE; | |
950 } | |
951 | |
952 if (!dmPCXFlush(pcx)) | |
953 return FALSE; | |
954 } | |
955 | |
956 return TRUE; | |
957 } | |
958 | |
959 | |
960 int dmWritePCXImageFILE(FILE *fp, DMImage *img, int scale, BOOL paletted) | |
961 { | |
962 DMPCXData pcx; | |
963 DMPCXHeader hdr; | |
964 int res; | |
965 | |
966 // Create output file | |
967 pcx.buf = NULL; | |
968 pcx.format = paletted ? DM_IFMT_PALETTE : DM_IFMT_RGB_PLANE; | |
969 pcx.header = &hdr; | |
970 pcx.fp = fp; | |
971 | |
972 // Create PCX header | |
973 memset(&hdr, 0, sizeof(hdr)); | |
974 if (paletted) | |
975 { | |
976 int i; | |
977 for (i = 0; i < (img->ncolors > 16 ? 16 : img->ncolors); i++) | |
978 { | |
979 hdr.colormap[i].r = img->pal[i].r; | |
980 hdr.colormap[i].g = img->pal[i].g; | |
981 hdr.colormap[i].b = img->pal[i].b; | |
982 } | |
983 } | |
984 hdr.manufacturer = 10; | |
985 hdr.version = 5; | |
986 hdr.encoding = 1; | |
987 hdr.bpp = 8; | |
988 hdr.hres = img->width * scale; | |
989 hdr.vres = img->height * scale; | |
990 hdr.xmin = hdr.ymin = 0; | |
991 hdr.xmax = hdr.hres - 1; | |
992 hdr.ymax = hdr.vres - 1; | |
993 hdr.nplanes = dmImageGetBytesPerPixel(pcx.format); | |
994 hdr.palinfo = 1; | |
995 res = (img->width * scale); | |
996 hdr.bpl = res / 2; | |
997 if (res % 2) hdr.bpl++; | |
998 hdr.bpl *= 2; | |
999 | |
1000 dmMsg(2, "PCX: paletted=%d, nplanes=%d, bpp=%d, bpl=%d\n", | |
1001 paletted, hdr.nplanes, hdr.bpp, hdr.bpl); | |
1002 | |
1003 pcx.bufLen = hdr.bpl * 4; | |
1004 if ((pcx.buf = dmMalloc(pcx.bufLen)) == NULL) | |
1005 { | |
1006 dmError("PCX: Could not allocate %d bytes for RLE compression buffer.\n", | |
1007 pcx.bufLen); | |
1008 res = DMERR_MALLOC; | |
1009 goto error; | |
1010 } | |
1011 | |
1012 // Write PCX header | |
1013 if (!dm_fwrite_byte(pcx.fp, hdr.manufacturer) || | |
1014 !dm_fwrite_byte(pcx.fp, hdr.version) || | |
1015 !dm_fwrite_byte(pcx.fp, hdr.encoding) || | |
1016 !dm_fwrite_byte(pcx.fp, hdr.bpp)) | |
1017 { | |
1018 dmError("PCX: Could not write basic header data.\n"); | |
1019 res = DMERR_FWRITE; | |
1020 goto error; | |
1021 } | |
1022 | |
1023 if (!dm_fwrite_le16(pcx.fp, hdr.xmin) || | |
1024 !dm_fwrite_le16(pcx.fp, hdr.ymin) || | |
1025 !dm_fwrite_le16(pcx.fp, hdr.xmax) || | |
1026 !dm_fwrite_le16(pcx.fp, hdr.ymax) || | |
1027 !dm_fwrite_le16(pcx.fp, hdr.hres) || | |
1028 !dm_fwrite_le16(pcx.fp, hdr.vres)) | |
1029 { | |
1030 dmError("PCX: Could not write image dimensions.\n"); | |
1031 res = DMERR_FWRITE; | |
1032 goto error; | |
1033 } | |
1034 | |
1035 if (!dm_fwrite_str(pcx.fp, (Uint8 *) &hdr.colormap, sizeof(hdr.colormap))) | |
1036 { | |
1037 dmError("PCX: Could not write colormap.\n"); | |
1038 res = DMERR_FWRITE; | |
1039 goto error; | |
1040 } | |
1041 | |
1042 if (!dm_fwrite_byte(pcx.fp, hdr.reserved) || | |
1043 !dm_fwrite_byte(pcx.fp, hdr.nplanes) || | |
1044 !dm_fwrite_le16(pcx.fp, hdr.bpl) || | |
1045 !dm_fwrite_le16(pcx.fp, hdr.palinfo) || | |
1046 !dm_fwrite_str(pcx.fp, (Uint8 *) &hdr.filler, sizeof(hdr.filler))) | |
1047 { | |
1048 dmError("PCX: Could not write header remainder.\n"); | |
1049 res = DMERR_FWRITE; | |
1050 goto error; | |
1051 } | |
1052 | |
1053 // Write image data | |
1054 res = dmWriteImageData(img, (void *) &pcx, dmWritePCXRow, scale, pcx.format); | |
1055 | |
1056 // Write VGA palette | |
1057 if (paletted) | |
1058 { | |
1059 int i; | |
1060 dm_fwrite_byte(pcx.fp, 0x0C); | |
1061 dmMsg(2, "PCX: Writing palette of %d active entries.\n", img->ncolors); | |
1062 | |
1063 for (i = 0; i < img->ncolors; i++) | |
1064 { | |
1065 dm_fwrite_byte(pcx.fp, img->pal[i].r); | |
1066 dm_fwrite_byte(pcx.fp, img->pal[i].g); | |
1067 dm_fwrite_byte(pcx.fp, img->pal[i].b); | |
1068 } | |
1069 | |
1070 // Pad the palette, if necessary | |
1071 for (; i < 256; i++) | |
1072 { | |
1073 dm_fwrite_byte(pcx.fp, 0); | |
1074 dm_fwrite_byte(pcx.fp, 0); | |
1075 dm_fwrite_byte(pcx.fp, 0); | |
1076 } | |
1077 } | |
1078 | |
1079 error: | |
1080 dmFree(pcx.buf); | |
1081 return res; | |
1082 } | |
1083 | |
1084 | |
1085 int dmWritePCXImage(const char *filename, DMImage *img, int scale, BOOL paletted) | |
1086 { | |
1087 FILE *fp; | |
1088 int res; | |
1089 | |
1090 if ((fp = fopen(filename, "wb")) == NULL) | |
1091 { | |
1092 dmError("PCX: Could not open file '%s' for writing.\n", filename); | |
1093 return DMERR_FOPEN; | |
1094 } | |
1095 | |
1096 res = dmWritePCXImageFILE(fp, img, scale, paletted); | |
1097 | |
1098 fclose(fp); | |
1099 return res; | |
1100 } | |
1101 | |
1102 | |
1103 static BOOL dmPCXDecodeRLERow(FILE *fp, Uint8 *buf, const size_t bufLen) | |
1104 { | |
1105 size_t offs = 0; | |
1106 do | |
1107 { | |
1108 int count; | |
1109 Uint8 data; | |
1110 | |
1111 if (!dm_fread_byte(fp, &data)) | |
1112 return FALSE; | |
1113 | |
1114 if ((data & 0xC0) == 0xC0) | |
1115 { | |
1116 count = data & 0x3F; | |
1117 if (!dm_fread_byte(fp, &data)) | |
1118 return FALSE; | |
1119 } | |
1120 else | |
1121 count = 1; | |
1122 | |
1123 while (count-- && offs < bufLen) | |
1124 buf[offs++] = data; | |
1125 | |
1126 } while (offs < bufLen); | |
1127 | |
1128 return TRUE; | |
1129 } | |
1130 | |
1131 | |
1132 int dmReadPCXImageFILE(FILE *fp, DMImage **pimg) | |
1133 { | |
1134 DMImage *img; | |
1135 DMPCXData pcx; | |
1136 DMPCXHeader hdr; | |
1137 BOOL paletted; | |
1138 int res = 0, yc, xc; | |
1139 Uint8 *dp; | |
1140 | |
1141 pcx.buf = NULL; | |
1142 | |
1143 // Read PCX header | |
1144 if (!dm_fread_byte(fp, &hdr.manufacturer) || | |
1145 !dm_fread_byte(fp, &hdr.version) || | |
1146 !dm_fread_byte(fp, &hdr.encoding) || | |
1147 !dm_fread_byte(fp, &hdr.bpp)) | |
1148 { | |
1149 dmError("PCX: Could not read basic header data.\n"); | |
1150 res = DMERR_FREAD; | |
1151 goto error; | |
1152 } | |
1153 | |
1154 if (hdr.manufacturer != 10 || | |
1155 hdr.version != 5 || | |
1156 hdr.encoding != 1 || | |
1157 hdr.bpp != 8) | |
1158 { | |
1159 dmError("PCX: Not a PCX file, or unsupported variant.\n"); | |
1160 res = DMERR_FREAD; | |
1161 goto error; | |
1162 } | |
1163 | |
1164 if (!dm_fread_le16(fp, &hdr.xmin) || | |
1165 !dm_fread_le16(fp, &hdr.ymin) || | |
1166 !dm_fread_le16(fp, &hdr.xmax) || | |
1167 !dm_fread_le16(fp, &hdr.ymax) || | |
1168 !dm_fread_le16(fp, &hdr.hres) || | |
1169 !dm_fread_le16(fp, &hdr.vres)) | |
1170 { | |
1171 dmError("PCX: Could not read image dimensions.\n"); | |
1172 res = DMERR_FREAD; | |
1173 goto error; | |
1174 } | |
1175 | |
1176 if (!dm_fread_str(fp, (Uint8 *) &hdr.colormap, sizeof(hdr.colormap))) | |
1177 { | |
1178 dmError("PCX: Could not read colormap.\n"); | |
1179 res = DMERR_FREAD; | |
1180 goto error; | |
1181 } | |
1182 | |
1183 if (!dm_fread_byte(fp, &hdr.reserved) || | |
1184 !dm_fread_byte(fp, &hdr.nplanes) || | |
1185 !dm_fread_le16(fp, &hdr.bpl) || | |
1186 !dm_fread_le16(fp, &hdr.palinfo) || | |
1187 !dm_fread_str(fp, (Uint8 *) &hdr.filler, sizeof(hdr.filler))) | |
1188 { | |
1189 dmError("PCX: Could not read header remainder.\n"); | |
1190 res = DMERR_FREAD; | |
1191 goto error; | |
1192 } | |
1193 | |
1194 if (hdr.nplanes != 3 && hdr.nplanes != 1) | |
1195 { | |
1196 dmError("PCX: Unsupported number of bitplanes %d.\n", hdr.nplanes); | |
1197 res = DMERR_FREAD; | |
1198 goto error; | |
1199 } | |
1200 | |
1201 // Allocate image | |
1202 if ((*pimg = img = dmImageAlloc(hdr.xmax - hdr.xmin + 1, hdr.ymax - hdr.ymin + 1)) == NULL) | |
1203 { | |
1204 dmError("PCX: Could not allocate image structure.\n"); | |
1205 res = DMERR_MALLOC; | |
1206 goto error; | |
1207 } | |
1208 | |
1209 paletted = hdr.nplanes == 1; | |
1210 pcx.bufLen = hdr.nplanes * hdr.bpl; | |
1211 if ((pcx.buf = dmMalloc(pcx.bufLen)) == NULL) | |
1212 { | |
1213 dmError("PCX: Could not allocate RLE buffer.\n"); | |
1214 res = DMERR_MALLOC; | |
1215 goto error; | |
1216 } | |
1217 | |
1218 // Read image data | |
1219 dp = img->data; | |
1220 for (yc = 0; yc < img->height; yc++) | |
1221 { | |
1222 // Decode row of RLE'd data | |
1223 if (!dmPCXDecodeRLERow(fp, pcx.buf, pcx.bufLen)) | |
1224 { | |
1225 dmError("PCX: Error decoding RLE data.\n"); | |
1226 res = DMERR_INVALID_DATA; | |
1227 goto error; | |
1228 } | |
1229 | |
1230 // Decode bitplanes | |
1231 switch (hdr.nplanes) | |
1232 { | |
1233 case 1: | |
1234 memcpy(dp, pcx.buf, img->width); | |
1235 break; | |
1236 | |
1237 case 3: | |
1238 { | |
1239 Uint8 *dptr = dp, | |
1240 *sptr1 = pcx.buf, | |
1241 *sptr2 = sptr1 + hdr.bpl, | |
1242 *sptr3 = sptr2 + hdr.bpl; | |
1243 | |
1244 for (xc = 0; xc < img->width; xc++) | |
1245 { | |
1246 *dptr++ = *sptr1++; | |
1247 *dptr++ = *sptr2++; | |
1248 *dptr++ = *sptr3++; | |
1249 } | |
1250 } | |
1251 break; | |
1252 } | |
1253 | |
1254 dp += img->pitch; | |
1255 } | |
1256 | |
1257 // Read VGA palette | |
1258 if (paletted) | |
1259 { | |
1260 int i; | |
1261 Uint8 tmpb; | |
1262 BOOL read; | |
1263 | |
1264 if (!dm_fread_byte(fp, &tmpb) || tmpb != 0x0C) | |
1265 { | |
1266 read = FALSE; | |
1267 img->ncolors = 16; | |
1268 } | |
1269 else | |
1270 { | |
1271 read = TRUE; | |
1272 img->ncolors = 256; | |
1273 } | |
1274 | |
1275 if ((img->pal = dmCalloc(img->ncolors, sizeof(DMColor))) == NULL) | |
1276 { | |
1277 dmError("PCX: Could not allocate palette data!\n"); | |
1278 res = DMERR_MALLOC; | |
1279 goto error; | |
1280 } | |
1281 | |
1282 if (read) | |
1283 { | |
1284 for (i = 0; i < img->ncolors; i++) | |
1285 { | |
1286 Uint8 tmpR, tmpG, tmpB; | |
1287 if (!dm_fread_byte(fp, &tmpR) || | |
1288 !dm_fread_byte(fp, &tmpG) || | |
1289 !dm_fread_byte(fp, &tmpB)) | |
1290 goto error; | |
1291 | |
1292 img->pal[i].r = tmpR; | |
1293 img->pal[i].g = tmpG; | |
1294 img->pal[i].b = tmpB; | |
1295 } | |
1296 } | |
1297 else | |
1298 { | |
1299 for (i = 0; i < img->ncolors; i++) | |
1300 { | |
1301 if (i < 16) | |
1302 { | |
1303 img->pal[i].r = hdr.colormap[i].r; | |
1304 img->pal[i].g = hdr.colormap[i].g; | |
1305 img->pal[i].b = hdr.colormap[i].b; | |
1306 } | |
1307 } | |
1308 } | |
1309 | |
1310 | |
1311 } | |
1312 | |
1313 error: | |
1314 dmFree(pcx.buf); | |
1315 return res; | |
1316 } | |
1317 | |
1318 | |
1319 int dmReadPCXImage(const char *filename, DMImage **pimg) | |
1320 { | |
1321 FILE *fp; | |
1322 int res; | |
1323 | |
1324 if ((fp = fopen(filename, "rb")) == NULL) | |
1325 { | |
1326 dmError("PCX: Could not open file '%s' for reading.\n", filename); | |
1327 return -15; | |
1328 } | |
1329 | |
1330 res = dmReadPCXImageFILE(fp, pimg); | |
1331 | |
1332 fclose(fp); | |
1333 return res; | |
1334 } | |
1335 | |
1336 | |
1337 static int fmtProbePNG(const Uint8 *buf, const size_t len) | |
1338 { | |
1339 if (len > 64 && buf[0] == 0x89 && | |
1340 buf[1] == 'P' && buf[2] == 'N' && buf[3] == 'G' && | |
1341 buf[4] == 0x0d && buf[5] == 0x0a) | |
1342 return DM_PROBE_SCORE_GOOD; | |
1343 | |
1344 return DM_PROBE_SCORE_FALSE; | |
1345 } | |
1346 | |
1347 | |
1348 static int fmtProbePCX(const Uint8 *buf, const size_t len) | |
1349 { | |
1350 if (len > 128 + 64 && | |
1351 buf[0] == 10 && | |
1352 buf[1] == 5 && | |
1353 buf[2] == 1 && | |
1354 buf[3] == 8) | |
1355 return DM_PROBE_SCORE_GOOD; | |
1356 | |
1357 return DM_PROBE_SCORE_FALSE; | |
1358 } | |
1359 | |
1360 | |
1361 #ifdef UNFINISHED | 474 #ifdef UNFINISHED |
1362 int dmConvertBMP2(DMImage *screen, const DM64Image *img) | 475 int dmConvertBMP2(DMImage *screen, const DM64Image *img) |
1363 { | 476 { |
1364 int yc; | 477 int yc; |
1365 Uint8 *dp = screen->data; | 478 Uint8 *dp = screen->data; |
1398 return 0; | 511 return 0; |
1399 } | 512 } |
1400 #endif | 513 #endif |
1401 | 514 |
1402 | 515 |
1403 int dmWriteImage(char *filename, DMImage *image, BOOL info) | 516 int dmWriteImage(const char *filename, DMImage *image, DMImageSpec *spec, int iformat, BOOL info) |
1404 { | 517 { |
1405 if (info) | 518 if (info) |
1406 { | 519 { |
1407 dmMsg(1, "Outputting %s image %d x %d -> %d x %d [%d]\n", | 520 dmMsg(1, "Outputting %s image %d x %d -> %d x %d [%d]\n", |
1408 imageFormatList[optOutSubFormat], | 521 dmImageFormatList[iformat], |
1409 image->width, image->height, | 522 image->width, image->height, |
1410 image->width * optScale, image->height * optScale, optScale); | 523 image->width * spec->scale, image->height * spec->scale, |
1411 } | 524 spec->scale); |
1412 | 525 } |
1413 switch (optOutSubFormat) | 526 |
527 switch (iformat) | |
1414 { | 528 { |
1415 #ifdef DM_USE_LIBPNG | 529 #ifdef DM_USE_LIBPNG |
1416 case IMGFMT_PNG: | 530 case IMGFMT_PNG: |
1417 if (info) dmMsg(2, "%s output.\n", optPaletted ? "Indexed 8bpp" : "32bit RGBA"); | 531 if (info) dmMsg(2, "%s output.\n", spec->paletted ? "Indexed 8bpp" : "32bit RGBA"); |
1418 return dmWritePNGImage(filename, image, optScale, optPaletted ? DM_IFMT_PALETTE : DM_IFMT_RGBA); | 532 spec->format = spec->paletted ? DM_IFMT_PALETTE : DM_IFMT_RGBA; |
533 return dmWritePNGImage(filename, image, spec); | |
1419 #endif | 534 #endif |
1420 | 535 |
1421 case IMGFMT_PPM: | 536 case IMGFMT_PPM: |
1422 if (info) dmMsg(2, "24bit RGB output.\n"); | 537 if (info) dmMsg(2, "24bit RGB output.\n"); |
1423 return dmWritePPMImage(filename, image, optScale); | 538 spec->format = DM_IFMT_RGB; |
539 return dmWritePPMImage(filename, image, spec); | |
1424 | 540 |
1425 case IMGFMT_PCX: | 541 case IMGFMT_PCX: |
1426 if (info) dmMsg(2, "%s output.\n", optPaletted ? "Indexed 8bpp" : "24bit RGB"); | 542 if (info) dmMsg(2, "%s output.\n", spec->paletted ? "Indexed 8bpp" : "24bit RGB"); |
1427 return dmWritePCXImage(filename, image, optScale, optPaletted); | 543 return dmWritePCXImage(filename, image, spec); |
1428 | 544 |
1429 case IMGFMT_ARAW: | 545 case IMGFMT_ARAW: |
1430 { | 546 { |
1431 int res; | 547 int res; |
1432 char *palFilename = dm_strdup_printf("%s.pal", filename); | 548 char *palFilename = dm_strdup_printf("%s.pal", filename); |
1433 res = dmWriteIFFMasterRAWPalette(palFilename, image, 1 << optBPP); | 549 res = dmWriteIFFMasterRAWPalette(palFilename, image, 1 << optSpec.nplanes); |
1434 dmFree(palFilename); | 550 dmFree(palFilename); |
1435 if (res != DMERR_OK) | 551 if (res != DMERR_OK) |
1436 return res; | 552 return res; |
1437 | 553 |
1438 if (info) dmMsg(2, "%d bitplanes, %s interleave.\n", optBPP, optInterleave ? "with" : "without"); | 554 if (info) dmMsg(2, "%d bitplanes, %s interleave.\n", spec->nplanes, spec->interleave ? "with" : "without"); |
1439 return dmWriteIFFMasterRAWImage(filename, image, optScale, optBPP, optInterleave); | 555 return dmWriteIFFMasterRAWImage(filename, image, spec); |
1440 } | 556 } |
1441 | 557 |
1442 default: | 558 default: |
1443 return FALSE; | 559 return FALSE; |
1444 } | 560 } |
1542 | 658 |
1543 outImage = dmImageAlloc(outWidthPX, outHeight); | 659 outImage = dmImageAlloc(outWidthPX, outHeight); |
1544 dmMsg(1, "Outputting sequence of %d images @ %d x %d -> %d x %d.\n", | 660 dmMsg(1, "Outputting sequence of %d images @ %d x %d -> %d x %d.\n", |
1545 optItemCount, | 661 optItemCount, |
1546 outImage->width, outImage->height, | 662 outImage->width, outImage->height, |
1547 outImage->width * optScale, outImage->height * optScale); | 663 outImage->width * optSpec.scale, outImage->height * optSpec.scale); |
1548 } | 664 } |
1549 else | 665 else |
1550 { | 666 { |
1551 int outIWidth, outIHeight; | 667 int outIWidth, outIHeight; |
1552 if (optItemCount <= 0) | 668 if (optItemCount <= 0) |
1593 { | 709 { |
1594 dmError("Could not allocate memory for filename template?\n"); | 710 dmError("Could not allocate memory for filename template?\n"); |
1595 goto error; | 711 goto error; |
1596 } | 712 } |
1597 | 713 |
1598 dmWriteImage(outFilename, outImage, FALSE); | 714 dmWriteImage(optOutFilename, outImage, &optSpec, optOutSubFormat, TRUE); |
1599 dmFree(outFilename); | 715 dmFree(outFilename); |
1600 } | 716 } |
1601 else | 717 else |
1602 { | 718 { |
1603 if (++outX >= optPlanedWidth) | 719 if (++outX >= optPlanedWidth) |
1610 itemCount++; | 726 itemCount++; |
1611 } | 727 } |
1612 | 728 |
1613 if (!optSequential) | 729 if (!optSequential) |
1614 { | 730 { |
1615 dmWriteImage(optOutFilename, outImage, TRUE); | 731 dmWriteImage(optOutFilename, outImage, &optSpec, optOutSubFormat, TRUE); |
1616 } | 732 } |
1617 | 733 |
1618 dmImageFree(outImage); | 734 dmImageFree(outImage); |
1619 } | 735 } |
1620 | 736 |
1710 optInFormat = FFMT_BITMAP; | 826 optInFormat = FFMT_BITMAP; |
1711 } | 827 } |
1712 | 828 |
1713 if (optInFormat == FFMT_AUTO) | 829 if (optInFormat == FFMT_AUTO) |
1714 { | 830 { |
1715 // XXX, needs a proper probe loop | 831 DMImageFormat *ifmt = NULL; |
1716 if (fmtProbePNG(dataBuf + optInSkip, dataSize - optInSkip)) | 832 int index; |
833 if (dmImageProbeGeneric(dataBuf + optInSkip, dataSize - optInSkip, &ifmt, &index) > 0) | |
1717 { | 834 { |
1718 optInFormat = FFMT_IMAGE; | 835 optInFormat = FFMT_IMAGE; |
1719 optInSubFormat = IMGFMT_PNG; | 836 optInSubFormat = index; |
1720 } | |
1721 else | |
1722 if (fmtProbePCX(dataBuf + optInSkip, dataSize - optInSkip)) | |
1723 { | |
1724 optInFormat = FFMT_IMAGE; | |
1725 optInSubFormat = IMGFMT_PCX; | |
1726 } | 837 } |
1727 } | 838 } |
1728 | 839 |
1729 if (optInFormat == FFMT_AUTO) | 840 if (optInFormat == FFMT_AUTO) |
1730 { | 841 { |
1765 dmDumpSpritesAndChars(inFile); | 876 dmDumpSpritesAndChars(inFile); |
1766 break; | 877 break; |
1767 | 878 |
1768 case FFMT_BITMAP: | 879 case FFMT_BITMAP: |
1769 { | 880 { |
1770 DMImage *img = NULL; | 881 DMImage *outImage = NULL; |
1771 int res = DMERR_OK; | 882 int res = DMERR_OK; |
1772 | 883 |
1773 if (optOutFilename == NULL) | 884 if (optOutFilename == NULL) |
1774 { | 885 { |
1775 dmError("Output filename not set, required for image formats.\n"); | 886 dmError("Output filename not set, required for image formats.\n"); |
1777 } | 888 } |
1778 | 889 |
1779 switch (optOutFormat) | 890 switch (optOutFormat) |
1780 { | 891 { |
1781 case FFMT_IMAGE: | 892 case FFMT_IMAGE: |
1782 if ((img = dmImageAlloc(C64_SCR_WIDTH, C64_SCR_HEIGHT)) == NULL) | 893 if ((outImage = dmImageAlloc(C64_SCR_WIDTH, C64_SCR_HEIGHT)) == NULL) |
1783 { | 894 { |
1784 dmError("Could not allocate output image surface %d x %d.\n", | 895 dmError("Could not allocate output image surface %d x %d.\n", |
1785 C64_SCR_WIDTH, C64_SCR_HEIGHT); | 896 C64_SCR_WIDTH, C64_SCR_HEIGHT); |
1786 goto error; | 897 goto error; |
1787 } | 898 } |
1788 | 899 |
1789 img->pal = (DMColor *) &dmC64Palette; | 900 outImage->pal = (DMColor *) &dmC64Palette; |
1790 img->ncolors = C64_NCOLORS; | 901 outImage->ncolors = C64_NCOLORS; |
1791 img->constpal = TRUE; | 902 outImage->constpal = TRUE; |
1792 | 903 |
1793 if (cfmt->convert != NULL) | 904 if (cfmt->convert != NULL) |
1794 res = cfmt->convert(img, &cimage); | 905 res = cfmt->convert(outImage, &cimage); |
1795 else | 906 else |
1796 res = dmC64ConvertGenericBMP2Image(img, &cimage); | 907 res = dmC64ConvertGenericBMP2Image(outImage, &cimage); |
1797 | 908 |
1798 if (res != DMERR_OK || img == NULL) | 909 if (res != DMERR_OK || outImage == NULL) |
1799 { | 910 { |
1800 dmError("Error in bitmap to image conversion.\n"); | 911 dmError("Error in bitmap to image conversion.\n"); |
1801 goto error; | 912 goto error; |
1802 } | 913 } |
1803 | 914 |
1804 res = dmWriteImage(optOutFilename, img, TRUE); | 915 res = dmWriteImage(optOutFilename, outImage, &optSpec, optOutSubFormat, TRUE); |
1805 break; | 916 break; |
1806 | 917 |
1807 default: | 918 default: |
1808 dmError("Unsupported output format for bitmap/image conversion.\n"); | 919 dmError("Unsupported output format for bitmap/image conversion.\n"); |
1809 break; | 920 break; |
1810 } | 921 } |
1811 | 922 |
1812 dmImageFree(img); | 923 dmImageFree(outImage); |
1813 } | 924 } |
1814 break; | 925 break; |
1815 | 926 |
1816 case FFMT_IMAGE: | 927 case FFMT_IMAGE: |
1817 { | 928 { |
1818 DMImage *img; | 929 DMImage *outImage; |
1819 int res = DMERR_OK; | 930 int res = DMERR_OK; |
1820 | 931 |
1821 if (optOutFilename == NULL) | 932 if (optOutFilename == NULL) |
1822 { | 933 { |
1823 dmError("Output filename not set, required for image formats.\n"); | 934 dmError("Output filename not set, required for image formats.\n"); |
1825 } | 936 } |
1826 | 937 |
1827 // Read input | 938 // Read input |
1828 switch (optInSubFormat) | 939 switch (optInSubFormat) |
1829 { | 940 { |
1830 case IMGFMT_PCX: res = dmReadPCXImageFILE(inFile, &img); break; | 941 case IMGFMT_PCX: res = dmReadPCXImageFILE(inFile, &outImage); break; |
1831 // case IMGFMT_PNG: res = dmReadPNGImageFILE(inFile, &img); break; | 942 // case IMGFMT_PNG: res = dmReadPNGImageFILE(inFile, &outImage); break; |
1832 // case IMGFMT_ARAW: res = dmReadARAWImageFILE(inFile, &img, optBPP); break; | 943 // case IMGFMT_ARAW: res = dmReadARAWImageFILE(inFile, &outImage, optSpec.nplanes); break; |
1833 default: | 944 default: |
1834 dmError("Unsupported input image format for bitmap/image conversion.\n"); | 945 dmError("Unsupported input image format for bitmap/image conversion.\n"); |
1835 break; | 946 break; |
1836 | 947 |
1837 } | 948 } |
1838 | 949 |
1839 if (res != DMERR_OK || img == NULL) | 950 if (res != DMERR_OK || outImage == NULL) |
1840 break; | 951 break; |
1841 | 952 |
1842 switch (optOutFormat) | 953 switch (optOutFormat) |
1843 { | 954 { |
1844 case FFMT_IMAGE: | 955 case FFMT_IMAGE: |
1845 res = dmWriteImage(optOutFilename, img, TRUE); | 956 res = dmWriteImage(optOutFilename, outImage, &optSpec, optOutSubFormat, TRUE); |
1846 break; | 957 break; |
1847 | 958 |
1848 default: | 959 default: |
1849 dmError("Unsupported output format for bitmap/image conversion.\n"); | 960 dmError("Unsupported output format for bitmap/image conversion.\n"); |
1850 break; | 961 break; |
1851 } | 962 } |
1852 | 963 |
1853 dmImageFree(img); | 964 dmImageFree(outImage); |
1854 } | 965 } |
1855 break; | 966 break; |
1856 } | 967 } |
1857 | 968 |
1858 fclose(inFile); | 969 fclose(inFile); |