/[projet1]/public/pc/tools/osdk/main/pictconv/sources/oric_converter.cpp
Defence Force logotype

Contents of /public/pc/tools/osdk/main/pictconv/sources/oric_converter.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 406 - (show annotations)
Mon Sep 20 18:59:17 2010 UTC (9 years, 1 month ago) by dbug
File size: 26269 byte(s)
Updated the OSDK with the latest code of most of the tools.

1
2
3 #include <assert.h>
4 #include <io.h>
5 #include <conio.h>
6 #include <fcntl.h>
7 #include <iostream>
8
9 #include <sys/types.h>
10 #include <sys/stat.h>
11
12 #include "freeimage.h"
13
14 #include "defines.h"
15 #include "getpixel.h"
16 #include "hires.h"
17 #include "oric_converter.h"
18 #include "dithering.h"
19
20 #include "common.h"
21
22 #include "image.h"
23
24
25
26 //
27 // dither_riemersma
28 //
29 void dither_riemersma_monochrom(ImageContainer& image,int width,int height);
30 void dither_riemersma_rgb(ImageContainer& image,int width,int height);
31
32
33 char *PtrSpaces;
34 char BufferSpaces[]=" ";
35
36 int gcur_line=0;
37 int gmax_count=0;
38
39 bool FlagDebug=true;
40
41
42 // ============================================================================
43 //
44 // OricRgbColor
45 //
46 // ============================================================================
47
48 class OricRgbColor : public RgbColor
49 {
50 public:
51 void SetOricColor(ORIC_COLOR color)
52 {
53 if (color&1) m_red=255;
54 else m_red=0;
55
56 if (color&2) m_green=255;
57 else m_green=0;
58
59 if (color&4) m_blue=255;
60 else m_blue=0;
61 }
62 };
63
64
65 // ============================================================================
66 //
67 // OricPictureConverter
68 //
69 // ============================================================================
70
71 OricPictureConverter::OricPictureConverter() :
72 PictureConverter(MACHINE_ORIC),
73 m_format(FORMAT_MONOCHROM),
74 m_buffer(0),
75 m_flag_setbit6(true)
76 {
77
78 set_buffer_size(240,200); // Default size
79
80 clear_screen();
81 }
82
83 OricPictureConverter::~OricPictureConverter()
84 {
85 delete[] m_buffer;
86 }
87
88
89
90 void OricPictureConverter::set_buffer_size(int width,int height)
91 {
92 m_buffer_width =width;
93 m_buffer_height =height;
94 m_buffer_cols =(width+5)/6;
95 m_buffer_size =m_buffer_height*m_buffer_cols;
96
97 delete[] m_buffer;
98 m_buffer=new unsigned char[m_buffer_size];
99 }
100
101
102
103 void OricPictureConverter::clear_screen()
104 {
105 //
106 // Fill the screen with a neutral value (64=white space for hires)
107 //
108 unsigned char nFillValue;
109 if (m_flag_setbit6)
110 {
111 nFillValue=64;
112 }
113 else
114 {
115 nFillValue=0;
116 }
117 for (unsigned int i=0;i<m_buffer_size;i++)
118 {
119 m_buffer[i]=nFillValue;
120 }
121 }
122
123
124
125
126 ORIC_COLOR OricPictureConverter::convert_pixel_monochrom(const ImageContainer& sourcePicture,unsigned int x,unsigned int y)
127 {
128 RgbColor rgb=sourcePicture.ReadColor(x,y);
129
130 unsigned char r=rgb.m_red;
131 unsigned char g=rgb.m_green;
132 unsigned char b=rgb.m_blue;
133
134 switch (m_dither)
135 {
136 case DITHER_NONE:
137 //
138 // Simple BLACK/WHITE selection
139 // based on the global luminosity.
140 //
141 if ((r+g+b)>127+127+127)
142 {
143 r=255;
144 g=255;
145 b=255;
146 }
147 else
148 {
149 r=0;
150 g=0;
151 b=0;
152 }
153 break;
154
155 case DITHER_ALTERNATE:
156 case DITHER_ALTERNATE_INVERSED:
157 //
158 // Semi dithering :))
159 // BLACK/GREY/WHITE
160 //
161 if ((r+g+b)>170*3)
162 {
163 r=255;
164 g=255;
165 b=255;
166 }
167 else
168 if ((r+g+b)<85*3)
169 {
170 r=0;
171 g=0;
172 b=0;
173 }
174 else
175 {
176 if ((x^y)&1)
177 {
178 if (m_dither==DITHER_ALTERNATE_INVERSED)
179 {
180 r=255;
181 g=255;
182 b=255;
183 }
184 else
185 {
186 r=0;
187 g=0;
188 b=0;
189 }
190 }
191 else
192 {
193 if (m_dither==DITHER_ALTERNATE_INVERSED)
194 {
195 r=0;
196 g=0;
197 b=0;
198 }
199 else
200 {
201 r=255;
202 g=255;
203 b=255;
204 }
205 }
206 }
207 break;
208
209 case DITHER_ORDERED:
210 {
211 //
212 // Use a dithering matrix
213 //
214 int bit=1 << ((x&3) | ((y&3)<<2));
215
216 unsigned char c=(r+g+b)/3;
217 if (DitherMask[(c*8)/255]&bit) c=255;
218 else c=0;
219
220 r=g=b=c;
221 }
222 break;
223
224 case DITHER_RIEMERSMA:
225 break;
226 case DITHER_FLOYD:
227 break;
228
229 default:
230 break;
231 }
232
233 if (r|g|b)
234 return ORIC_COLOR_WHITE;
235 return ORIC_COLOR_BLACK;
236 }
237
238
239
240 ORIC_COLOR OricPictureConverter::convert_pixel_rgb(const ImageContainer& sourcePicture,unsigned int x,unsigned int y)
241 {
242 RgbColor rgb1=sourcePicture.ReadColor(x,y+0);
243 RgbColor rgb2=sourcePicture.ReadColor(x,y+1);
244 RgbColor rgb3=sourcePicture.ReadColor(x,y+2);
245
246 unsigned char r=(rgb1.m_red +rgb2.m_red +rgb3.m_red )/3;
247 unsigned char g=(rgb1.m_green+rgb2.m_green+rgb3.m_green)/3;
248 unsigned char b=(rgb1.m_blue +rgb2.m_blue +rgb3.m_blue )/3;
249
250 int c;
251
252 switch (m_dither)
253 {
254 case DITHER_NONE:
255 //
256 // Simple BLACK/COMPONENT selection
257 // based on the global luminosity.
258 //
259 c=y % 3;
260
261 switch (c)
262 {
263 case 0:
264 if (r>127) r=255;
265 else r=0;
266 g=0;
267 b=0;
268 break;
269 case 1:
270 if (g>127) g=255;
271 else g=0;
272 r=0;
273 b=0;
274 break;
275 case 2:
276 if (b>127) b=255;
277 else b=0;
278 r=0;
279 g=0;
280 break;
281 }
282 if (r|g|b)
283 return ORIC_COLOR_WHITE;
284 return ORIC_COLOR_BLACK;
285 break;
286
287 case DITHER_ALTERNATE:
288 //
289 // Semi dithering :))
290 // BLACK/GREY/WHITE
291 //
292 c=y % 3;
293
294 switch (c)
295 {
296 case 0:
297 if (r>170) r=255;
298 else
299 if (r<85) r=0;
300 else r=(unsigned char)(255*((x^y)&1));
301 g=0;
302 b=0;
303 break;
304 case 1:
305 if (g>170) g=255;
306 else
307 if (g<85) g=0;
308 else g=(unsigned char)(255*((x^y)&1));
309 r=0;
310 b=0;
311 break;
312 case 2:
313 if (b>170) b=255;
314 else
315 if (b<85) b=0;
316 else b=(unsigned char)(255*((x^y)&1));
317 r=0;
318 g=0;
319 break;
320 }
321 if (r|g|b)
322 return ORIC_COLOR_WHITE;
323 return ORIC_COLOR_BLACK;
324 break;
325
326 case DITHER_ORDERED:
327 {
328 //
329 // Use a dithering matrix
330 //
331 int bit=1 << ((x&3) | ((y&3)<<2));
332
333 c=y % 3;
334
335 switch (c)
336 {
337 case 0:
338 if (DitherMask[(r*8)/255]&bit) r=255;
339 else r=0;
340 g=0;
341 b=0;
342 break;
343 case 1:
344 if (DitherMask[(g*8)/255]&bit) g=255;
345 else g=0;
346 r=0;
347 b=0;
348 break;
349 case 2:
350 if (DitherMask[(b*8)/255]&bit) b=255;
351 else b=0;
352 r=0;
353 g=0;
354 break;
355 }
356 if (r|g|b)
357 return ORIC_COLOR_WHITE;
358 return ORIC_COLOR_BLACK;
359 }
360 break;
361
362 case DITHER_FLOYD:
363 break;
364
365 default:
366 break;
367 }
368 return ORIC_COLOR_BLACK;
369 }
370
371
372
373
374
375 ORIC_COLOR OricPictureConverter::convert_pixel_rb(const ImageContainer& sourcePicture,unsigned int x,unsigned int y)
376 {
377 RgbColor rgb1=sourcePicture.ReadColor(x,y+0);
378 RgbColor rgb2=sourcePicture.ReadColor(x,y+1);
379 RgbColor rgb3=sourcePicture.ReadColor(x,y+2);
380
381 unsigned char r=(rgb1.m_red+rgb2.m_red +rgb3.m_red)/3;
382 unsigned char gb=(rgb1.m_green+rgb2.m_green+rgb3.m_green+rgb1.m_blue+rgb2.m_blue +rgb3.m_blue)/6;
383
384 int c;
385 switch (m_dither)
386 {
387 case DITHER_NONE:
388 //
389 // Simple BLACK/COMPONENT selection
390 // based on the global luminosity.
391 //
392 c=y % 2;
393
394 switch (c)
395 {
396 case 0:
397 if (r>127) r=255;
398 else r=0;
399 gb=0;
400 break;
401 case 1:
402 if (gb>127) gb=255;
403 else gb=0;
404 r=0;
405 break;
406 }
407 break;
408
409 case DITHER_ALTERNATE:
410 //
411 // Semi dithering :))
412 // BLACK/GREY/WHITE
413 //
414 c=y % 2;
415
416 switch (c)
417 {
418 case 0:
419 if (r>170) r=255;
420 else
421 if (r<85) r=0;
422 else r=(unsigned char)(255*((x^y)&1));
423 gb=0;
424 break;
425 case 1:
426 if (gb>170) gb=255;
427 else
428 if (gb<85) gb=0;
429 else gb=(unsigned char)(255*((x^y)&1));
430 r=0;
431 break;
432 }
433 break;
434
435 case DITHER_ORDERED:
436 //
437 // Use a dithering matrix
438 //
439 int bit;
440
441 bit=1 << ((x&3) | ((y&3)<<2));
442
443 c=y % 2;
444
445 switch (c)
446 {
447 case 0:
448 if (DitherMask[(r*8)/255]&bit) r=255;
449 else r=0;
450 gb=0;
451 break;
452 case 1:
453 if (DitherMask[(gb*8)/255]&bit) gb=255;
454 else gb=0;
455 r=0;
456 break;
457 }
458 break;
459
460 case DITHER_FLOYD:
461 break;
462
463 default:
464 break;
465 }
466
467 if (r|gb)
468 return ORIC_COLOR_WHITE;
469 return ORIC_COLOR_BLACK;
470 }
471
472
473
474
475
476
477
478 void OricPictureConverter::convert_monochrom(const ImageContainer& sourcePicture)
479 {
480 ImageContainer convertedPicture(sourcePicture);
481
482 //
483 // Perform the global dithering, if required
484 //
485 switch (m_dither)
486 {
487 case DITHER_RIEMERSMA:
488 dither_riemersma_monochrom(convertedPicture,m_buffer_width,m_buffer_height);
489 m_dither=DITHER_NONE;
490 break;
491 }
492
493 //
494 // Perform the HIRES convers
495 //
496 unsigned char* ptr_hires=m_buffer;
497 for (unsigned int y=0;y<m_buffer_height;y++)
498 {
499 int x=0;
500 for (int col=0;col<m_buffer_cols;col++)
501 {
502 unsigned char val=0;
503 for (int bit=0;bit<6;bit++)
504 {
505 val<<=1;
506 ORIC_COLOR color=convert_pixel_monochrom(convertedPicture,x,y);
507 if (color!=ORIC_COLOR_BLACK)
508 {
509 val|=1;
510 }
511 x++;
512 }
513 if (m_flag_setbit6)
514 {
515 // In some cases you don't want to get the bit 6 to be set at all
516 val|=64;
517 }
518 *ptr_hires++=val;
519 }
520 }
521 }
522
523
524 void OricPictureConverter::convert_twilighte_mask(const ImageContainer& sourcePicture)
525 {
526 ImageContainer convertedPicture(sourcePicture);
527
528 //
529 // Perform the global dithering, if required
530 //
531 switch (m_dither)
532 {
533 case DITHER_RIEMERSMA:
534 dither_riemersma_monochrom(convertedPicture,m_buffer_width,m_buffer_height);
535 m_dither=DITHER_NONE;
536 break;
537 }
538
539 //
540 // Perform the HIRES conversion
541 //
542 unsigned char* ptr_hires=m_buffer;
543 for (unsigned int y=0;y<m_buffer_height;y++)
544 {
545 int x=0;
546 for (int col=0;col<m_buffer_cols;col++)
547 {
548 unsigned char mask=0;
549 unsigned char mask_control=0;
550 unsigned char val=0;
551 for (int bit=0;bit<6;bit++)
552 {
553 val<<=1;
554 mask_control<<=1;
555
556 // Get the original pixel color
557 BYTE *ptr_byte=FreeImage_GetBitsRowCol(convertedPicture.GetBitmap(),x,y);
558 int color=0;
559 if ((*ptr_byte++)>128) color|=4;
560 if ((*ptr_byte++)>128) color|=2;
561 if ((*ptr_byte++)>128) color|=1;
562
563 switch (color)
564 {
565 case ORIC_COLOR_BLACK:
566 // Paper
567 val|=0;
568 mask_control|=1;
569 break;
570
571 case ORIC_COLOR_WHITE:
572 // Ink
573 val|=1;
574 mask_control|=1;
575 break;
576
577 default:
578 // mask
579 if (bit<=2)
580 {
581 mask|=2;
582 }
583 else
584 {
585 mask|=1;
586 }
587 break;
588 }
589 x++;
590 }
591
592 //
593 // Test if we have mask/pixels conflicts
594 //
595 /*
596 if ( ((mask&1) && (mask_control&(1+2+4))) ||
597 ((mask&2) && (mask_control&(8+16+32))) )
598 {
599 printf("\r\nMask/Ink/Paper problem Line %d Bloc %d",y,col);
600 }
601 */
602
603 //
604 // Write the value
605 //
606 *ptr_hires++=val|(mask<<6);
607 }
608 }
609 }
610
611
612
613 void OricPictureConverter::convert_rgb(const ImageContainer& sourcePicture)
614 {
615 ImageContainer convertedPicture(sourcePicture);
616
617 //
618 // Perform the global dithering, if required
619 //
620 switch (m_dither)
621 {
622 case DITHER_RIEMERSMA:
623 dither_riemersma_rgb(convertedPicture,m_buffer_width,m_buffer_height);
624 m_dither=DITHER_NONE;
625 break;
626 }
627
628 //
629 // Perform the HIRES conversion
630 //
631 unsigned char* ptr_hires=m_buffer;
632 for (unsigned int y=0;y<m_buffer_height;y++)
633 {
634 //
635 // Write RgbColor attrib
636 //
637 switch (y%3)
638 {
639 case 0:
640 *ptr_hires++=ORIC_COLOR_RED;
641 break;
642 case 1:
643 *ptr_hires++=ORIC_COLOR_GREEN;
644 break;
645 case 2:
646 *ptr_hires++=ORIC_COLOR_BLUE;
647 break;
648 }
649
650 int x=0;
651 for (int col=1;col<m_buffer_cols;col++)
652 {
653 unsigned char val=0;
654 for (int bit=0;bit<6;bit++)
655 {
656 val<<=1;
657 ORIC_COLOR color=convert_pixel_rgb(convertedPicture,x,y);
658 if (color!=ORIC_COLOR_BLACK)
659 {
660 val|=1;
661 }
662 x++;
663 }
664 if (m_flag_setbit6)
665 {
666 // In some cases you don't want the bit 6 to be set at all
667 val|=64;
668 }
669 *ptr_hires++=val;
670 }
671 }
672 }
673
674
675
676
677
678
679
680
681
682 void OricPictureConverter::convert_rb(const ImageContainer& sourcePicture)
683 {
684 ImageContainer convertedPicture(sourcePicture);
685
686 //
687 // Perform the global dithering, if required
688 //
689 switch (m_dither)
690 {
691 case DITHER_RIEMERSMA:
692 dither_riemersma_rgb(convertedPicture,m_buffer_width,m_buffer_height);
693 m_dither=DITHER_NONE;
694 break;
695 }
696
697 //
698 // Perform the HIRES conversion
699 //
700 unsigned char *ptr_hires=m_buffer;
701 for (unsigned int y=0;y<m_buffer_height;y++)
702 {
703 //
704 // Write RgbColor attrib
705 //
706 switch (y%2)
707 {
708 case 0:
709 *ptr_hires++=ORIC_COLOR_RED;
710 break;
711 case 1:
712 *ptr_hires++=ORIC_COLOR_WHITE;
713 break;
714 }
715
716 int x=0;
717 for (int col=0;col<39;col++)
718 {
719 unsigned char val=0;
720 for (int bit=0;bit<6;bit++)
721 {
722 val<<=1;
723 ORIC_COLOR color=convert_pixel_rb(convertedPicture,x,y);
724 if (color!=ORIC_COLOR_BLACK)
725 {
726 val|=1;
727 }
728 x++;
729 }
730 if (m_flag_setbit6)
731 {
732 // In some cases you don't want the bit 6 to be set at all
733 val|=64;
734 }
735 *ptr_hires++=val;
736 }
737 }
738 }
739
740
741
742 /*
743 - u8: nombre de couleurs sur le bloc (1, 2, ou invalide)
744 - u8: couleur 1
745 - u8: couleur 2
746 - u8: flag (inverse vidéo possible, ...)
747 */
748 struct BLOC6
749 {
750 unsigned char color_count;
751 unsigned char color[2];
752 unsigned char value;
753 };
754
755
756 BLOC6 Bloc6Buffer[40]; // For 240 pixel wide pictures
757
758
759 /*
760
761 Les cas possibles:
762 - 6 pixels unis.
763 * Ils peuvent être d'une de ces couleurs:
764 Utilisation de la couleur courante du papier
765 Utilisation de la couleur courante de l'encre
766 Utilisation de la couleur courante du papier, avec inversion vidéo
767 Utilisation de la couleur courante de l'encre, avec inversion vidéo
768
769 * On peur y faire:
770 Changement de papier de la même couleur
771 Changement de papier d'une couleur inversée de la couleur, en mettant la vidéo inverse
772
773
774
775 - 6 pixels, utilisant deux couleurs.
776
777
778
779
780 */
781
782
783
784
785 bool RecurseLine(unsigned char count,BLOC6 *ptr_bloc6,unsigned char *ptr_hires,unsigned char cur_paper,unsigned char cur_ink)
786 {
787 PtrSpaces-=2;
788
789 /*
790 if (gcur_line==138)
791 {
792 printf("\r\n Count:%d Paper:%d Ink:%d",count,cur_paper,cur_ink);
793 }
794 */
795 /*
796 if ((time(0)-gLastTimer)>2)
797 {
798 //
799 // End of recursion with error
800 //
801 if (!FlagDebug)
802 {
803 return false;
804 }
805 }
806 */
807
808 if (count<gmax_count)
809 {
810 gmax_count=count;
811 //printf("\r\n MaxCount:%d",gmax_count);
812 /*
813 if ((gcur_line==138) && (gmax_count==34))
814 {
815 __asm {int 3 }
816 }
817 */
818 }
819
820 if (!count)
821 {
822 //
823 // End of recursion
824 //
825 return true;
826 }
827
828 unsigned char color_count=ptr_bloc6->color_count;
829 unsigned char c0=ptr_bloc6->color[0];
830 unsigned char c1=ptr_bloc6->color[1];
831 unsigned char v =ptr_bloc6->value;
832
833
834 count--;
835 ptr_bloc6++;
836 ptr_hires++;
837
838 if (color_count==1)
839 {
840 // ========================================
841 // The current bloc of pixels is using only
842 // one color. It's the right opportunity to
843 // change either the PAPER or the INK color.
844 // ========================================
845
846 if (c0==cur_paper)
847 {
848 //
849 // The 6 pixels are using the current paper color.
850 //
851
852 // Use current paper color
853 if (FlagDebug) printf("\r\n %sUse paper color (%d)",PtrSpaces,cur_paper);
854 if (RecurseLine(count,ptr_bloc6,ptr_hires,cur_paper,cur_ink))
855 {
856 ptr_hires[-1]=64;
857 return true;
858 }
859
860 // Try each of the 8 possible ink colors
861 for (unsigned char color=0;color<8;color++)
862 {
863 if (FlagDebug) printf("\r\n %sUse paper color (%d) while changing ink color to (%d)",PtrSpaces,cur_paper,color);
864 if (RecurseLine(count,ptr_bloc6,ptr_hires,cur_paper,color))
865 {
866 ptr_hires[-1]=color;
867 return true;
868 }
869 }
870 }
871
872 // Use current ink color
873 if (c0==cur_ink)
874 {
875 if (FlagDebug) printf("\r\n %sUse ink color (%d)",PtrSpaces,cur_ink);
876 if (RecurseLine(count,ptr_bloc6,ptr_hires,cur_paper,cur_ink))
877 {
878 ptr_hires[-1]=64|63;
879 return true;
880 }
881 }
882
883
884 if (c0==(7-cur_paper))
885 {
886 //
887 // The 6 pixels are using the current inverted paper color.
888 //
889
890 // Use current paper color
891 if (FlagDebug) printf("\r\n %sUse inverted paper color (%d => %d)",PtrSpaces,cur_paper,7-cur_paper);
892 if (RecurseLine(count,ptr_bloc6,ptr_hires,cur_paper,cur_ink))
893 {
894 ptr_hires[-1]=128|64;
895 return true;
896 }
897
898 // Try each of the 8 possible ink colors
899 for (unsigned char color=0;color<8;color++)
900 {
901 if (FlagDebug) printf("\r\n %sUse inverted paper color (%d => %d) while changing ink color to (%d)",PtrSpaces,cur_paper,7-cur_paper,color);
902 if (RecurseLine(count,ptr_bloc6,ptr_hires,cur_paper,color))
903 {
904 ptr_hires[-1]=128|color;
905 return true;
906 }
907 }
908 }
909
910 // Use current inverted ink color
911 if (c0==(7-cur_ink))
912 {
913 if (FlagDebug) printf("\r\n %sUse inverted ink color (%d => %d)",PtrSpaces,cur_ink,7-cur_ink);
914 if (RecurseLine(count,ptr_bloc6,ptr_hires,cur_paper,cur_ink))
915 {
916 ptr_hires[-1]=128|64|63;
917 return true;
918 }
919 }
920
921 // Change paper color
922 if (FlagDebug) printf("\r\n %sChange paper color to (%d)",PtrSpaces,c0);
923 if (RecurseLine(count,ptr_bloc6,ptr_hires,c0,cur_ink))
924 {
925 ptr_hires[-1]=16+c0;
926 return true;
927 }
928
929
930 // Change paper color, using inverse vidéo
931 if (FlagDebug) printf("\r\n %sChange paper color to (%d) using inversion (%d)",PtrSpaces,7-c0,c0);
932 if (RecurseLine(count,ptr_bloc6,ptr_hires,7-c0,cur_ink))
933 {
934 ptr_hires[-1]=128|16+(7-c0);
935 return true;
936 }
937 }
938 else
939 {
940 // ========================================
941 // The current bloc of pixels is using two
942 // different colors. It's totaly impossible
943 // to use attributes changes on this one.
944 // ========================================
945
946
947 // Try simple pixels.
948 if ((c0==cur_paper) && (c1==cur_ink))
949 {
950 if (FlagDebug) printf("\r\n %sUse current colors (%d,%d)",PtrSpaces,cur_paper,cur_ink);
951 if (RecurseLine(count,ptr_bloc6,ptr_hires,cur_paper,cur_ink))
952 {
953 ptr_hires[-1]=64|v;
954 return true;
955 }
956 }
957
958 // Try simple pixels, but invert the bitmask.
959 if ((c0==cur_ink) && (c1==cur_paper))
960 {
961 if (FlagDebug) printf("\r\n %sUse current colors (%d,%d)",PtrSpaces,cur_paper,cur_ink);
962 if (RecurseLine(count,ptr_bloc6,ptr_hires,cur_paper,cur_ink))
963 {
964 ptr_hires[-1]=64|(v^63);
965 return true;
966 }
967 }
968
969 // Try simple video inverted pixels.
970 if ((c0==(7-cur_paper)) && (c1==(7-cur_ink)))
971 {
972 if (FlagDebug) printf("\r\n %sUse current inverted colors (%d,%d) => (%d,%d)",PtrSpaces,cur_paper,cur_ink,7-cur_paper,7-cur_ink);
973 if (RecurseLine(count,ptr_bloc6,ptr_hires,cur_paper,cur_ink))
974 {
975 ptr_hires[-1]=128|64|v;
976 return true;
977 }
978 }
979
980 // Try simple video inverted pixels, but invert the bitmask.
981 if ((c0==(7-cur_ink)) && (c1==(7-cur_paper)))
982 {
983 if (FlagDebug) printf("\r\n %sUse current inverted colors (%d,%d) => (%d,%d)",PtrSpaces,cur_paper,cur_ink,7-cur_paper,7-cur_ink);
984 if (RecurseLine(count,ptr_bloc6,ptr_hires,cur_paper,cur_ink))
985 {
986 ptr_hires[-1]=128|64|(v^63);
987 return true;
988 }
989 }
990 }
991
992 //printf("\r\n ==== back track !!! ====");
993 //getch();
994 PtrSpaces+=2;
995 return false;
996 }
997
998
999
1000
1001
1002
1003
1004 void OricPictureConverter::convert_colored(const ImageContainer& sourcePicture)
1005 {
1006 ImageContainer convertedPicture(sourcePicture);
1007
1008 int col,bit;
1009
1010 //
1011 // Phase 1: Create a buffer with infos
1012 //
1013 bool flag=false;
1014 unsigned char *ptr_hires=m_buffer;
1015
1016 bool error_in_picture=false;
1017
1018 for (unsigned y=0;y<m_buffer_height;y++)
1019 {
1020 if (m_flag_debug)
1021 {
1022 printf("\r\nLine %d ",y);
1023 }
1024
1025 BLOC6 *ptr_bloc6=Bloc6Buffer;
1026 bool error_in_line=false;
1027
1028 //
1029 // Create a buffer for the scanline
1030 //
1031 int x=0;
1032 for (col=0;col<m_buffer_cols;col++)
1033 {
1034 bool error_in_bloc=false;
1035
1036 // Init that bloc
1037 ptr_bloc6->color_count=0;
1038 ptr_bloc6->color[0]=0;
1039 ptr_bloc6->color[1]=0;
1040 ptr_bloc6->value=0;
1041
1042 for (bit=0;bit<6;bit++)
1043 {
1044 ptr_bloc6->value<<=1;
1045
1046 // Get the original pixel color
1047 BYTE *ptr_byte=FreeImage_GetBitsRowCol(convertedPicture.GetBitmap(),x,y);
1048 unsigned char color=0;
1049 if ((*ptr_byte++)>128) color|=4;
1050 if ((*ptr_byte++)>128) color|=2;
1051 if ((*ptr_byte++)>128) color|=1;
1052
1053 // Check if it's already present in the color map
1054 switch (ptr_bloc6->color_count)
1055 {
1056 case 0:
1057 ptr_bloc6->color_count++;
1058 ptr_bloc6->color[0]=color;
1059 ptr_bloc6->color[1]=color; // To avoid later tests
1060 break;
1061
1062 case 1:
1063 if (ptr_bloc6->color[0]!=color)
1064 {
1065 // one more color
1066 ptr_bloc6->color_count++;
1067 ptr_bloc6->color[1]=color;
1068 ptr_bloc6->value|=1;
1069 }
1070 break;
1071
1072 case 2:
1073 if (ptr_bloc6->color[0]!=color)
1074 {
1075 if (ptr_bloc6->color[1]==color)
1076 {
1077 // second color
1078 ptr_bloc6->value|=1;
1079 }
1080 else
1081 {
1082 // color overflow !!!
1083 ptr_bloc6->color_count++;
1084
1085 error_in_bloc=true;
1086 }
1087 }
1088 break;
1089 }
1090 x++;
1091 }
1092
1093 if (error_in_bloc)
1094 {
1095 if (!error_in_line)
1096 {
1097 printf("\r\nLine %d ",y);
1098 }
1099 printf("[%d colors bloc %d] ",ptr_bloc6->color_count,col);
1100 error_in_line=true;
1101 }
1102 ptr_bloc6++;
1103 }
1104 if (error_in_line)
1105 {
1106 error_in_picture=true;
1107 }
1108
1109 //
1110 // Convert to monochrome
1111 //
1112 //gLastTimer=time(0);
1113 ptr_bloc6=Bloc6Buffer;
1114
1115 unsigned char val;
1116
1117 PtrSpaces=BufferSpaces+strlen(BufferSpaces);
1118 gcur_line=y;
1119 gmax_count=m_buffer_cols;
1120 if (RecurseLine((unsigned char)m_buffer_cols,ptr_bloc6,ptr_hires,0,7))
1121 //if (RecurseLine(7,ptr_bloc6,ptr_hires,0,7))
1122 {
1123 //
1124 // Recursion work.
1125 // Nothing to do.
1126 //
1127 if (FlagDebug)
1128 {
1129 printf("\r\n ======= found =====");
1130 printf("\r\n Dump: ");
1131 for (col=0;col<7;col++)
1132 {
1133 val=ptr_hires[col];
1134 printf("[%d,%d,%d] ",(val>>7)&1,(val>>6)&1,(val&63));
1135 }
1136
1137 //getch();
1138 }
1139 ptr_bloc6+=m_buffer_cols;
1140 ptr_hires+=m_buffer_cols;
1141 }
1142 else
1143 {
1144 if (!error_in_line)
1145 {
1146 printf("\r\nLine %d ",y);
1147 }
1148 printf(" max:%d ",gmax_count);
1149
1150 //
1151 // Unable to perfom conversion
1152 // Use standard monochrom algorithm
1153 //
1154 x=0;
1155 for (col=0;col<m_buffer_cols;col++)
1156 {
1157 if (flag)
1158 {
1159 if (ptr_bloc6->color_count>2)
1160 {
1161 val=127;
1162 }
1163 else
1164 {
1165 val=64;
1166 }
1167 }
1168 else
1169 {
1170 val=64+ptr_bloc6->value;
1171 }
1172 *ptr_hires++=val;
1173 ptr_bloc6++;
1174 }
1175 }
1176 }
1177 }
1178
1179
1180 bool OricPictureConverter::Convert(const ImageContainer& sourcePicture)
1181 {
1182 if (m_blockmode==BLOCKMODE_ENABLED)
1183 {
1184 // Find the blocks, and then continue the conversion
1185 sourcePicture.FindBlocks(m_block_data);
1186 //std::cout << "-b1 (block mode) not supported on this machine";
1187 //return false;
1188 }
1189
1190 if ( (m_format==OricPictureConverter::FORMAT_COLORED) &&
1191 ((sourcePicture.GetWidth()%6)==0) &&
1192 (sourcePicture.GetWidth()>240))
1193 {
1194 printf("\r\n Colored pictures should be at most 240 pixels wide, and multiple of 6 pixel wide.");
1195 return false;
1196 }
1197
1198 set_buffer_size(sourcePicture.GetWidth(),sourcePicture.GetHeight());
1199
1200 clear_screen();
1201
1202 switch (m_format)
1203 {
1204 case FORMAT_MONOCHROM:
1205 convert_monochrom(sourcePicture);
1206 break;
1207
1208 case FORMAT_COLORED:
1209 convert_colored(sourcePicture);
1210 break;
1211
1212 case FORMAT_RGB:
1213 convert_rgb(sourcePicture);
1214 break;
1215
1216 case FORMAT_RB:
1217 convert_rb(sourcePicture);
1218 break;
1219
1220 case FORMAT_TRUETEXT:
1221 break;
1222
1223 case FORMAT_TWILIGHTE_MASK:
1224 convert_twilighte_mask(sourcePicture);
1225 break;
1226
1227 default:
1228 // Oops
1229 return false;
1230 break;
1231 }
1232 return true;
1233 }
1234
1235
1236
1237 bool OricPictureConverter::TakeSnapShot(ImageContainer& sourcePicture)
1238 {
1239 if (!sourcePicture.Allocate(m_buffer_width,m_buffer_height,24))
1240 {
1241 return false;
1242 }
1243
1244 unsigned char *ptr_hires=m_buffer;
1245 for (unsigned int y=0;y<m_buffer_height;y++)
1246 {
1247 ORIC_COLOR paper=ORIC_COLOR_BLACK;
1248 ORIC_COLOR ink =ORIC_COLOR_WHITE;
1249
1250 int x=0;
1251 for (int col=0;col<m_buffer_cols;col++)
1252 {
1253 int val=*ptr_hires++;
1254 int val2=val&127;
1255
1256 ORIC_COLOR cpaper=paper;
1257 ORIC_COLOR cink =ink;
1258 if (val2<8)
1259 {
1260 ink=(ORIC_COLOR)val2;
1261 val2=0;
1262 cpaper =paper;
1263 cink =ink;
1264 }
1265 else
1266 if ((val2>=16) && (val2<(16+8)))
1267 {
1268 paper=(ORIC_COLOR)(val2-16);
1269 val2=0;
1270 cpaper =paper;
1271 cink =ink;
1272 }
1273
1274 if (val&128)
1275 {
1276 cpaper=(ORIC_COLOR)(7-cpaper);
1277 cink=(ORIC_COLOR)(7-cink);
1278 }
1279
1280 for (int bit=0;bit<6;bit++)
1281 {
1282 OricRgbColor rgb;
1283 if (val2 & (1<<(5-bit)))
1284 {
1285 rgb.SetOricColor(cink);
1286 }
1287 else
1288 {
1289 rgb.SetOricColor(cpaper);
1290 }
1291 sourcePicture.WriteColor(rgb,x,y);
1292 x++;
1293 }
1294 }
1295 }
1296 return true;
1297 }
1298
1299
1300
1301 //
1302 // Contains an hexa dump of the following
1303 // auto-loadable BASIC program:
1304 //
1305 // 10 HIRES
1306 // 20 CLOAD""
1307 //
1308 unsigned char BasicLoader[]=
1309 {
1310 0x16,0x16,0x16,0x24,0x00,0xff,0x00,0xc7,0x05,0x11,0x05,0x01,0x00,0x48,0x49,0x52,
1311 0x4c,0x4f,0x41,0x44,0x00,0x07,0x05,0x0a,0x00,0xa2,0x00,0x0f,0x05,0x14,0x00,0xb6,
1312 0x22,0x22,0x00,0x00,0x00,0x55
1313 };
1314
1315
1316
1317
1318 void OricPictureConverter::save_header(long handle,int adress_begin)
1319 {
1320 unsigned char Header[]=
1321 {
1322 // 0
1323 0x16,0x16,0x16,
1324 // 3
1325 0x24,
1326 // 4
1327 0x00,0x00,
1328 // 6
1329 0x80,0x00,
1330 // 8
1331 0xbf,0xdf,
1332 // 10
1333 0xa0,0x00,
1334 // 12
1335 0x00
1336 };
1337
1338 int adress_end=adress_begin+m_buffer_size;
1339 Header[ 8]=(unsigned char)((adress_end>>8)&255);
1340 Header[ 9]=(unsigned char)( adress_end&255);
1341 Header[10]=(unsigned char)((adress_begin>>8)&255);
1342 Header[11]=(unsigned char)( adress_begin&255);
1343 _write(handle,Header,13);
1344 }
1345
1346 void OricPictureConverter::SaveToFile(long handle,int output_format)
1347 {
1348 switch (output_format)
1349 {
1350 case DEVICE_FORMAT_RAWBUFFER_WITH_XYHEADER:
1351 {
1352 unsigned char x=static_cast<unsigned char>(get_buffer_width());
1353 unsigned char y=static_cast<unsigned char>(get_buffer_height());
1354
1355 _write(handle,&x,1);
1356 _write(handle,&y,1);
1357 }
1358 break;
1359
1360 case DEVICE_FORMAT_RAWBUFFER_WITH_PALETTE:
1361 break;
1362
1363 case DEVICE_FORMAT_RAWBUFFER:
1364 // No header for raw
1365 break;
1366
1367 case DEVICE_FORMAT_BASIC_TAPE:
1368 _write(handle,BasicLoader,sizeof(BasicLoader));
1369 default: // Fall trough
1370 bool flag_header=true;
1371 if (flag_header)
1372 {
1373 save_header(handle,0xa000);
1374 //_write(handle,Header,13);
1375 _write(handle,"",1); //_write(handle,name,strlen(name)+1);
1376 }
1377 break;
1378 }
1379 _write(handle,(unsigned char*)m_buffer,GetBufferSize());
1380 }
1381

  ViewVC Help
Powered by ViewVC 1.1.26