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

Annotation of /public/pc/tools/osdk/main/pictconv/sources/atari_converter.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

1 dbug 208
2     #define _CRT_SECURE_NO_WARNINGS
3    
4     #include <assert.h>
5    
6     #include <io.h>
7    
8     #include <iostream>
9    
10     #include "common.h"
11    
12     #include "defines.h"
13     #include "getpixel.h"
14    
15     #include "atari_converter.h"
16     #include "shifter_color.h"
17    
18     #include "image.h"
19    
20     #include "freeimage.h"
21    
22     //#define ENABLE_PALETTE_TRACKING
23    
24    
25     // ============================================================================
26     //
27     // AtariClut
28     //
29     // ============================================================================
30    
31     int AtariClut::convert_pixel_shifter(const ShifterColor& color)
32     {
33     assert(m_clut_index_to_color.size()==m_clut_color_to_index.size());
34     std::map<ShifterColor,int>::iterator it=m_clut_color_to_index.find(color);
35     if (it==m_clut_color_to_index.end())
36     {
37     // Not found - need to search the first free slot...
38     //int index=m_clut_color_to_index.size();
39     for (int index=0;index<16;index++)
40     {
41     std::map<int,ShifterColor>::iterator it=m_clut_index_to_color.find(index);
42     if (it==m_clut_index_to_color.end())
43     {
44     //assert(index<16);
45     m_clut_color_to_index[color]=index;
46     m_clut_index_to_color[index]=color;
47     assert(m_clut_color_to_index[m_clut_index_to_color[index]]==index);
48     assert(m_clut_index_to_color[m_clut_color_to_index[color]]==color);
49     assert(m_clut_index_to_color.size()==m_clut_color_to_index.size());
50     return index;
51     }
52     }
53     // Color not found, we have a problem... like we have more than 16 colors Oo
54     assert(0);
55     return 0; // assert ?
56     }
57     else
58     {
59     // Return existing index
60     return it->second;
61     }
62     }
63    
64     int AtariClut::convert_pixel_shifter(const RgbColor& rgb)
65     {
66     ShifterColor color(rgb);
67     return convert_pixel_shifter(color);
68     }
69    
70     void AtariClut::SetColor(const ShifterColor& color,int index)
71     {
72     assert(index<16);
73    
74     m_clut_color_to_index[color]=index;
75     m_clut_index_to_color[index]=color;
76     }
77    
78     void AtariClut::SetColor(const RgbColor& rgb,int index)
79     {
80     ShifterColor color(rgb);
81     SetColor(color,index);
82     }
83    
84    
85    
86     // The idea is to reorder the colors in a way that limits the differences
87     // from one clut to another. An obvious fix is to make the identical colors
88     // stay on the same index.
89     void AtariClut::Reorder(AtariClut& baseClut)
90     {
91     #if 1
92     AtariClut newClut;
93    
94     // Code that computes the error between colors and choose the closest one
95     std::map<int,ShifterColor>::iterator it=baseClut.m_clut_index_to_color.begin();
96     while (it!=baseClut.m_clut_index_to_color.end())
97     {
98     ShifterColor baseColor=it->second;
99    
100     std::map<int,ShifterColor>::iterator foundIt=m_clut_index_to_color.end();
101     int foundDifference=0;
102    
103     std::map<int,ShifterColor>::iterator searchIt=m_clut_index_to_color.begin();
104     while (searchIt!=m_clut_index_to_color.end())
105     {
106     ShifterColor searchColor=searchIt->second;
107    
108     int difference=baseColor.ComputeDifference(searchColor);
109     if ((foundIt==m_clut_index_to_color.end()) || (difference<=foundDifference))
110     {
111     foundIt =searchIt;
112     foundDifference =difference;
113     }
114     ++searchIt;
115     }
116    
117     if (foundIt!=m_clut_index_to_color.end())
118     {
119     // Found a match
120     ShifterColor foundColor=foundIt->second;
121     newClut.convert_pixel_shifter(foundColor);
122    
123     std::map<ShifterColor,int>::iterator deleteIt=m_clut_color_to_index.find(foundColor);
124     assert(deleteIt!=m_clut_color_to_index.end());
125    
126     m_clut_index_to_color.erase(foundIt);
127     m_clut_color_to_index.erase(deleteIt);
128     }
129    
130     ++it;
131     }
132     m_clut_index_to_color.swap(newClut.m_clut_index_to_color);
133     m_clut_color_to_index.swap(newClut.m_clut_color_to_index);
134     #else
135     // Code that performs exact match
136     std::map<ShifterColor,int>::iterator it=baseClut.m_clut_color_to_index.begin();
137     while (it!=baseClut.m_clut_color_to_index.end())
138     {
139     ShifterColor baseColor=(*it).first;
140     int baseIndex=(*it).second;
141    
142     std::map<ShifterColor,int>::iterator findIt=m_clut_color_to_index.find(baseColor);
143     if (findIt!=m_clut_color_to_index.end())
144     {
145     // Found a match
146     int foundIndex=findIt->second;
147     if (foundIndex!=baseIndex)
148     {
149     // Different indexes in the palette, we need to swap
150     ShifterColor swappedColor=m_clut_index_to_color[baseIndex];
151     m_clut_index_to_color[foundIndex]=swappedColor;
152     m_clut_color_to_index[swappedColor] =foundIndex;
153    
154     m_clut_index_to_color[baseIndex]=baseColor;
155     m_clut_color_to_index[baseColor]=baseIndex;
156     }
157     }
158     ++it;
159     }
160     #endif
161     }
162    
163     void AtariClut::SaveClut(long handle) const
164     {
165     unsigned short clut[16];
166     memset(clut,0,sizeof(clut));
167    
168     assert(m_clut_color_to_index.size()<=16);
169     std::map<ShifterColor,int>::const_iterator it=m_clut_color_to_index.begin();
170     while (it!=m_clut_color_to_index.end())
171     {
172     int index=it->second;
173     assert(index<16);
174     const ShifterColor& color=it->first;
175     if (index<16)
176     {
177     // Atari ST is a big endian machine
178     clut[index]=color.GetBigEndianValue();
179     }
180     ++it;
181     }
182     _write(handle,clut,32);
183     }
184    
185    
186     void AtariClut::SaveClutAsText(std::string& text) const
187     {
188     unsigned short clut[16];
189     memset(clut,0,sizeof(clut));
190    
191     assert(m_clut_color_to_index.size()<=16);
192     std::map<ShifterColor,int>::const_iterator it=m_clut_color_to_index.begin();
193     while (it!=m_clut_color_to_index.end())
194     {
195     int index=it->second;
196     assert(index<16);
197     const ShifterColor& color=it->first;
198     if (index<16)
199     {
200     clut[index]=color.GetValue();
201     }
202     ++it;
203     }
204    
205     char buffer[64];
206     for (int index=0;index<16;index++)
207     {
208     if (index!=0)
209     {
210     text+=",";
211     }
212     sprintf(buffer,"$%04x",clut[index]);
213     text+=buffer;
214     }
215     }
216    
217    
218     void AtariClut::GetColors(std::vector<RGBQUAD>& colors) const
219     {
220     const std::map<ShifterColor,int>& reservedColor=m_clut_color_to_index;
221     assert(m_clut_color_to_index.size()==m_clut_index_to_color.size());
222    
223     unsigned int color_count=reservedColor.size();
224     if (color_count)
225     {
226     colors.resize(color_count);
227    
228     std::vector<RGBQUAD>::iterator itDest=colors.begin();
229     std::map<ShifterColor,int>::const_iterator itSource=reservedColor.begin();
230     while (itSource!=reservedColor.end())
231     {
232     const ShifterColor& sourceColor=itSource->first;
233     RgbColor rgbColor=sourceColor.GetRgb();
234    
235     RGBQUAD& destColor=*itDest;
236     destColor.rgbRed =rgbColor.m_red;
237     destColor.rgbGreen =rgbColor.m_green;
238     destColor.rgbBlue =rgbColor.m_blue;
239    
240     ++itSource;
241     ++itDest;
242     }
243     }
244     }
245    
246    
247     // ============================================================================
248     //
249     // AtariPictureConverter
250     //
251     // ============================================================================
252    
253     AtariPictureConverter::AtariPictureConverter() :
254     PictureConverter(MACHINE_ATARIST),
255     m_format(FORMAT_SINGLE_PALETTE),
256     m_palette_mode(PALETTE_AUTOMATIC),
257     m_buffer(0)
258     {
259     set_buffer_size(320,200); // Default size
260    
261     clear_screen();
262     }
263    
264     AtariPictureConverter::~AtariPictureConverter()
265     {
266     delete[] m_buffer;
267     }
268    
269    
270     void AtariPictureConverter::set_buffer_size(int width,int height)
271     {
272     m_buffer_width =width;
273     m_buffer_height =height;
274     m_buffer_cols =((width+15)/16)*2*4; // *wordsize*bitplanscount
275     m_buffer_size=m_buffer_height*m_buffer_cols;
276    
277     delete[] m_buffer;
278     m_buffer=new unsigned char[m_buffer_size];
279     }
280    
281    
282    
283     void AtariPictureConverter::clear_screen()
284     {
285     for (unsigned int i=0;i<m_buffer_size;i++)
286     {
287     m_buffer[i]=0;
288     }
289     }
290    
291    
292     bool AtariPictureConverter::Convert(const ImageContainer& sourcePicture)
293     {
294     ImageContainer convertedPicture(sourcePicture);
295    
296     #ifdef ENABLE_PALETTE_TRACKING
297     {
298     // ------- debug start
299     std::string clutAsText;
300     AtariClut& clut=GetClut(0);
301     clut.SaveClutAsText(clutAsText);
302     clutAsText+="\r\n";
303     std::cout << "AtariPictureConverter::Convert:" << clutAsText;
304     // ------- debug end
305     }
306     std::cout << "AtariPictureConverter::Convert:PaletteMode" << m_palette_mode << "\r\n";
307     #endif
308    
309 dbug 406 if (m_blockmode!=BLOCKMODE_DISABLED)
310     {
311     std::cout << "-b1 (block mode) not supported on this machine";
312     return false;
313     }
314 dbug 208
315     if (m_format==FORMAT_SINGLE_PALETTE)
316     {
317     m_flagPalettePerScanline=false;
318     if (m_palette_mode==PALETTE_FROM_LAST_PIXELS)
319     {
320     // Can's use this mode if only one palette should be exported
321     std::cout << "-p2 (Last pixels of each line of the picture contains the palette) requires -f1 (Multi palette format)";
322     return false;
323     }
324     }
325     else
326     {
327     m_flagPalettePerScanline=true;
328     }
329    
330     switch (m_palette_mode)
331     {
332     case PALETTE_AUTOMATIC:
333     // Nothing to do
334     break;
335    
336     case PALETTE_FROM_LAST_LINE:
337     {
338     // Cut the first line, and extract the palette
339     ImageContainer lockedPalette;
340     if (!lockedPalette.CreateFromImage(convertedPicture,0,convertedPicture.GetHeight()-2,convertedPicture.GetWidth(),2))
341     {
342     return false;
343     }
344    
345     if (!convertedPicture.CreateFromImage(convertedPicture,0,0,convertedPicture.GetWidth(),convertedPicture.GetHeight()-2))
346     {
347     return false;
348     }
349    
350     unsigned int clut_start=0;
351     unsigned int clut_end=1;
352     if (m_format==FORMAT_MULTIPLE_PALETTE)
353     {
354     clut_end=convertedPicture.GetHeight();
355     }
356    
357     RgbColor ignoreColor=lockedPalette.ReadColor(0,0);
358     for (unsigned int index=0;index<16;index++)
359     {
360     RgbColor rgbColor=lockedPalette.ReadColor(index,1);
361     if (rgbColor!=ignoreColor)
362     {
363     // This color should be locked for this index
364     for (unsigned int line=clut_start;line<clut_end;line++)
365     {
366     AtariClut& clut=GetClut(line);
367     clut.SetColor(rgbColor,index);
368     }
369     }
370     }
371    
372     }
373     break;
374    
375     case PALETTE_FROM_LAST_PIXELS:
376     {
377     // Cut the first 16 pixels on the left, and extract the palette for each
378     ImageContainer lockedPalette;
379     if (!lockedPalette.CreateFromImage(convertedPicture,convertedPicture.GetWidth()-17,0,17,convertedPicture.GetHeight()))
380     {
381     return false;
382     }
383    
384     if (!convertedPicture.CreateFromImage(convertedPicture,0,0,convertedPicture.GetWidth()-17,convertedPicture.GetHeight()))
385     {
386     return false;
387     }
388    
389     for (unsigned int line=0;line<lockedPalette.GetHeight();line++)
390     {
391     AtariClut& clut=GetClut(line);
392     RgbColor ignoreColor=lockedPalette.ReadColor(0,0);
393     for (unsigned int index=0;index<16;index++)
394     {
395     RgbColor rgbColor=lockedPalette.ReadColor(1+index,line);
396     if (rgbColor!=ignoreColor)
397     {
398     // This color should be locked for this index
399     clut.SetColor(rgbColor,index);
400     #ifdef ENABLE_PALETTE_TRACKING
401     if (line==0)
402     {
403     std::cout << "AtariPictureConverter::SetColor:" << (int)rgbColor.m_red << (int)rgbColor.m_green << (int)rgbColor.m_blue << "/" << index << "\r\n";
404     }
405     #endif
406     }
407     }
408     #ifdef ENABLE_PALETTE_TRACKING
409    
410     {
411     // ------- debug start
412     std::string clutAsText;
413     //AtariClut& clut=GetClut(0);
414     clut.SaveClutAsText(clutAsText);
415     clutAsText+="\r\n";
416     std::cout << "AtariPictureConverter::ConvertLoopForLine:" << line << "=" << clutAsText;
417     // ------- debug end
418     }
419     #endif
420     //_BREAK_IF_((line==5));
421     }
422     }
423     break;
424     }
425    
426    
427     #ifdef ENABLE_PALETTE_TRACKING
428     {
429     // ------- debug start
430     std::string clutAsText;
431     AtariClut& clut=GetClut(0);
432     clut.SaveClutAsText(clutAsText);
433     clutAsText+="\r\n";
434     std::cout << "AtariPictureConverter::Convert:" << clutAsText;
435     // ------- debug end
436     }
437     #endif
438    
439     set_buffer_size(convertedPicture.GetWidth(),convertedPicture.GetHeight());
440    
441     clear_screen();
442    
443     switch (m_format)
444     {
445     case FORMAT_SINGLE_PALETTE:
446     convertedPicture.ReduceColorDepth(&GetClut(0));
447     convert_shifter(convertedPicture);
448     break;
449    
450     case FORMAT_MULTIPLE_PALETTE:
451     m_flagPalettePerScanline=true;
452     convertedPicture.ReduceColorDepthPerScanline(&m_cluts);
453     convert_shifter(convertedPicture);
454     break;
455    
456     default:
457     // Oops
458     return false;
459     break;
460     }
461     return true;
462     }
463    
464    
465     AtariClut& AtariPictureConverter::GetClut(unsigned int scanline)
466     {
467     if (m_flagPalettePerScanline) return m_cluts[scanline];
468     else return m_cluts[0];
469     }
470    
471    
472     void AtariPictureConverter::convert_shifter(const ImageContainer& sourcePicture)
473     {
474     //
475     // Perform the Atari ST bitplan conversion
476     // We proceed in three phases for the multi palette pictures, because we want the
477     // colors to stay about the same between one line and another, to avoid horrible
478     // color glitches when moving the pictures horizontally.
479    
480     #ifdef ENABLE_PALETTE_TRACKING
481     // ------- debug start
482     std::string clutAsText;
483     AtariClut& clut=GetClut(0);
484     clut.SaveClutAsText(clutAsText);
485     clutAsText+="\r\n";
486     std::cout << "AtariPictureConverter::convert_shifter(start):" << clutAsText;
487     // ------- debug end
488     #endif
489     if (m_flagPalettePerScanline)
490     {
491     // Phase one: Collect palettes
492     {
493     for (unsigned int y=0;y<m_buffer_height;y++)
494     {
495     AtariClut& clut=GetClut(y);
496    
497     for (unsigned int x=0;x<m_buffer_width;x++)
498     {
499     //_BREAK_IF_((y==5) && (x==565));
500     RgbColor rgb=sourcePicture.ReadColor(x,y);
501     clut.convert_pixel_shifter(rgb);
502     }
503     }
504     }
505    
506     // Phase two: Optimize the palette
507     {
508     /*
509     for (unsigned int y=0;y<m_buffer_height-1;y++)
510     {
511     AtariClut& clut1=GetClut(y);
512     AtariClut& clut2=GetClut(y+1);
513     clut2.Reorder(clut1);
514     }
515     */
516     }
517     }
518    
519    
520     // Phase three: Generate the atari format bitplan
521     {
522     unsigned char *ptr_hires=(unsigned char*)m_buffer;
523     for (unsigned int y=0;y<m_buffer_height;y++)
524     {
525     //_BREAK_IF_(y==110);
526    
527     AtariClut& clut=GetClut(y);
528    
529     unsigned int x=0;
530     while (x<m_buffer_width)
531     {
532     unsigned int p0=0;
533     unsigned int p1=0;
534     unsigned int p2=0;
535     unsigned int p3=0;
536    
537     for (int bit=0;bit<16;bit++)
538     {
539     p0<<=1;
540     p1<<=1;
541     p2<<=1;
542     p3<<=1;
543     RgbColor rgb=sourcePicture.ReadColor(x,y);
544     int color=clut.convert_pixel_shifter(rgb);
545     if (color&1)
546     {
547     p0|=1;
548     }
549     if (color&2)
550     {
551     p1|=1;
552     }
553     if (color&4)
554     {
555     p2|=1;
556     }
557     if (color&8)
558     {
559     p3|=1;
560     }
561     x++;
562     }
563     *ptr_hires++=static_cast<unsigned char>((p0>>8)&255);
564     *ptr_hires++=static_cast<unsigned char>(p0&255);
565     *ptr_hires++=static_cast<unsigned char>((p1>>8)&255);
566     *ptr_hires++=static_cast<unsigned char>(p1&255);
567     *ptr_hires++=static_cast<unsigned char>((p2>>8)&255);
568     *ptr_hires++=static_cast<unsigned char>(p2&255);
569     *ptr_hires++=static_cast<unsigned char>((p3>>8)&255);
570     *ptr_hires++=static_cast<unsigned char>(p3&255);
571     }
572     }
573     }
574    
575     #ifdef ENABLE_PALETTE_TRACKING
576     {
577     // ------- debug start
578     std::string clutAsText;
579     AtariClut& clut=GetClut(0);
580     clut.SaveClutAsText(clutAsText);
581     clutAsText+="\r\n";
582     std::cout << "AtariPictureConverter::convert_shifter(end):" << clutAsText;
583     // ------- debug end
584     }
585     #endif
586     }
587    
588    
589     bool AtariPictureConverter::TakeSnapShot(ImageContainer& sourcePicture)
590     {
591     if (!sourcePicture.Allocate(m_buffer_width,m_buffer_height,24))
592     {
593     return false;
594     }
595    
596     #ifdef ENABLE_PALETTE_TRACKING
597     {
598     // ------- debug start
599     std::string clutAsText;
600     AtariClut& clut=GetClut(0);
601     clut.SaveClutAsText(clutAsText);
602     clutAsText+="\r\n";
603     std::cout << "AtariPictureConverter::TakeSnapShot:" << clutAsText;
604     // ------- debug end
605     }
606     #endif
607    
608     unsigned short* pShort=(unsigned short*)m_buffer;
609     for (unsigned int y=0;y<m_buffer_height;y++)
610     {
611     AtariClut& clut=GetClut(y);
612    
613     for (unsigned int x=0;x<m_buffer_width;x+=16)
614     {
615     unsigned short p0=*pShort++;
616     unsigned short p1=*pShort++;
617     unsigned short p2=*pShort++;
618     unsigned short p3=*pShort++;
619    
620     p0=((p0&255)<<8) | (p0>>8);
621     p1=((p1&255)<<8) | (p1>>8);
622     p2=((p2&255)<<8) | (p2>>8);
623     p3=((p3&255)<<8) | (p3>>8);
624    
625     for (int xx=0;xx<16;xx++)
626     {
627     int index=(p0&1) | ((p1&1)<<1) | ((p2&1)<<2) | ((p3&1)<<3);
628    
629     ShifterColor shifterColor=clut.m_clut_index_to_color[index];
630    
631     RgbColor rgb(shifterColor.GetRgb());
632    
633     sourcePicture.WriteColor(rgb,x+15-xx,y);
634    
635     p0>>=1;
636     p1>>=1;
637     p2>>=1;
638     p3>>=1;
639     }
640     }
641     }
642     return true;
643     }
644    
645    
646    
647     void AtariPictureConverter::SaveToFile(long handle,int output_format)
648     {
649     switch (output_format)
650     {
651     case DEVICE_FORMAT_RAWBUFFER_WITH_XYHEADER:
652     {
653     unsigned short x=static_cast<unsigned short>(get_buffer_width());
654     unsigned short y=static_cast<unsigned short>(get_buffer_height());
655    
656     _write(handle,&x,2);
657     _write(handle,&y,2);
658     }
659     break;
660    
661     case DEVICE_FORMAT_RAWBUFFER_WITH_PALETTE:
662     {
663     std::string clutAsText;
664     if (m_flagPalettePerScanline)
665     {
666     assert(m_cluts.size()==get_buffer_height());
667     std::map<int,AtariClut>::iterator it=m_cluts.begin();
668     while (it!=m_cluts.end())
669     {
670     AtariClut& clut=it->second;
671     clut.SaveClut(handle);
672     clut.SaveClutAsText(clutAsText);
673     clutAsText+="\r\n";
674     ++it;
675     }
676     }
677     else
678     {
679     AtariClut& clut=m_cluts[0];
680     clut.SaveClut(handle);
681     clut.SaveClutAsText(clutAsText);
682     }
683     clutAsText+="\r\n";
684     }
685     break;
686    
687     case DEVICE_FORMAT_RAWBUFFER:
688     // No header for raw
689     break;
690     }
691     _write(handle,(unsigned char*)m_buffer,GetBufferSize());
692     }
693    

  ViewVC Help
Powered by ViewVC 1.1.26