VDPENC

Page 6/13
1 | 2 | 3 | 4 | 5 | | 7 | 8 | 9 | 10 | 11

Par ARTRAG

Enlighted (6862)

Portrait de ARTRAG

18-05-2007, 20:44

It works only with 8 or 16 bit per pixel.
And it is more than 25MB!!
Only to convert a file!!
Tongue

Par pitpan

Prophet (3152)

Portrait de pitpan

18-05-2007, 23:13

About TGA format, it should be 24 bpp uncompressed (Photoshop rules!)

Thanks for your suggestions to improve the routine. They do make sense. Anyway, I don't see the point in improving the header selection. If the linker is good enough, all unused functions are linked. By the way, my own executable is something like 7 KB. Tiny enough!

Regarding the interest of storing scores is to be able to compare if there are more than one combination with the same score. It is not implemented yet.

And again, it is just my first attemp! I'm sure that I can be improved a lot. That's why I published just the source for you to help Wink. I'll try to publish a new version with your suggestions.

Thank you guys!

Par ARTRAG

Enlighted (6862)

Portrait de ARTRAG

19-05-2007, 01:22

This is what I was meaning. This code runs in 1/200 of the time of the first version and the result is exactly the same
Wink


// Headers!

#include<stdio.h>
#include<time.h>

// Just one function for everything

main(int argc, char **argv)
{

// Vars

 FILE *file,*CHR,*CLR;
 int bc,bp,i,j,x,y,c,p,k,MAXX,MAXY;
 unsigned int n,total=0,done=0,size;
 char *name;
 unsigned char image[512][512][3],header[18],palette[16][3]=

// TMS9918 RGB palette - approximated 50Hz PAL values

{{0x00,0x00,0x00}, //  0 Transparent - black (not used)
 {0x00,0x00,0x00}, //  1 Black
 {0x12,0xFF,0x00}, //  2 Green
 {0x76,0xFF,0x6F}, //  3 Light green
 {0x12,0x00,0xFF}, //  4 Blue
 {0x69,0x69,0xFF}, //  5 Light blue
 {0xA1,0x10,0x10}, //  6 Dark red
 {0x00,0xFF,0xFC}, //  7 Cyan
 {0xFF,0x00,0x00}, //  8 Red
 {0xFF,0x80,0x80}, //  9 Light red
 {0xFF,0xEA,0x00}, // 10 Yellow
 {0xFF,0xFB,0x80}, // 11 Light yellow
 {0x1D,0xA8,0x02}, // 12 Dark green
 {0xFF,0x00,0xFC}, // 13 Magenta
 {0xCC,0xCC,0xCC}, // 14 Light gray
 {0xFF,0xFF,0xFF}};// 15 White

// Get time

 clock();

// Application prompt

 printf("TMSopt v.0.02 - TGA 24bpp to TMS9918 converter\nCoded by Eduardo A. Robsy Petrus & Arturo Ragozini, 2007\n");
// Test if only one command-line parameter is available


 if (argc==1)
 {
  printf("Syntax: TMSopt [file.tga]\n");
  return;
 }

// Open source image (TGA, 24-bit, uncompressed)

 if ((file=fopen(argv[1],"rb"))==NULL)
 {
  printf("cannot open %s file!\n",argv[1]);
  return;
 }

// Read TGA header

 for (i=0;i<18;i++) header[i]=fgetc(file);

// Check header info

 for (i=0,n=0;i<12;i++) n+=header[i];

 if ((n!=2)||(header[2]!=2)||(header[17])||(header[16]!=24))
 {
  printf("Unsupported file format!\n");
  return;
 }

// Calculate size

 MAXX=header[12]|header[13]<<8;
 MAXY=header[14]|header[15]<<8;

 size=((MAXX+7)>>3)*MAXY;

// Check size limits

 if ((!MAXX)||(MAXX>512)||(!MAXY)||(MAXY>512))
 {
  printf("Unsupported size!");
  return;
 }

// Load image data

 for (y=MAXY-1;y>=0;y--)
  for (x=0;x3;y++)
    for (x=0;x<(MAXX+7)>>3;x++)
    {
    for (j=0;j<8;j++)
        // Generate alternatives
    {
        unsigned char c1,c2;
        unsigned long bs=32000;
        unsigned char bp =0, bc = 0;
        
        for (c1=1;c1<16;c1++)
            for (c2=c1+1;c2<16;c2++)
            {
                unsigned int cs = 0;
                unsigned int cp = 0;
                for (i=0;i<8;i++)
                {
                    unsigned int mc1=0,mc2=0;
                    for (k=0;k<3;k++) {
                        mc1+=abs(palette[c1][k]-image[x<<3|i][y<<3|j][k]);
                        mc2+=abs(palette[c2][k]-image[x<<3|i][y<<3|j][k]);
                    }
                    if (mc1>mc2) {
                        cp = (cp<<1) | (0x01);
                        cs += mc2;
                    }
                    else {
                        cp = (cp<<1) | (0x00);
                        cs += mc1;
                    }
                }
                if  (cs4:bc&0x0f][k];
                n<<=1;
            }
        // Update status counter
        
            if (done*100/size<(done+1)*100/size) 
                printf("\b\b\b%2i%%",100*done/size);
            done++;
            total++;
    }    
    }

// Conversion done

 printf("\b\b\bOk   \n");

// Generate new name

 name=malloc(0x100);
 argv[1][strlen(argv[1])-4]=0;
 strcpy(name,argv[1]);
 strcat(name,"_tms.tga");

// Save file header

 file=fopen(name,"wb");

 for (i=0;i<18;i++) fputc(header[i],file);

// Save image data

 for (y=MAXY-1;y>=0;y--)
  for (x=0;x

Some cleanup is needed in order to skip variables now not necessary anymore

Par ARTRAG

Enlighted (6862)

Portrait de ARTRAG

19-05-2007, 01:28

Now it's time for Floyd...

Par ARTRAG

Enlighted (6862)

Portrait de ARTRAG

19-05-2007, 11:10

Now Floyd works!!
But some adjustments are required....


// Headers!

#include<stdio.h>
#include<time.h>

#define uprange(t) (t>255) ? 255:(t)
#define inrange(t) (t<0) ? 0:(uprange(t))

// Just one function for everything

main(int argc, char **argv)
{

// Vars

 FILE *file,*CHR,*CLR;
 int bc,bp,i,j,x,y,c,p,k,MAXX,MAXY;
 unsigned int n,total=0,done=0,size;
 char *name;
 unsigned char image[512][512][3],header[18],palette[16][3]=

// TMS9918 RGB palette - approximated 50Hz PAL values

{{0x00,0x00,0x00}, //  0 Transparent - black (not used)
 {0x00,0x00,0x00}, //  1 Black
 {0x12,0xFF,0x00}, //  2 Green
 {0x76,0xFF,0x6F}, //  3 Light green
 {0x12,0x00,0xFF}, //  4 Blue
 {0x69,0x69,0xFF}, //  5 Light blue
 {0xA1,0x10,0x10}, //  6 Dark red
 {0x00,0xFF,0xFC}, //  7 Cyan
 {0xFF,0x00,0x00}, //  8 Red
 {0xFF,0x80,0x80}, //  9 Light red
 {0xFF,0xEA,0x00}, // 10 Yellow
 {0xFF,0xFB,0x80}, // 11 Light yellow
 {0x1D,0xA8,0x02}, // 12 Dark green
 {0xFF,0x00,0xFC}, // 13 Magenta
 {0xCC,0xCC,0xCC}, // 14 Light gray
 {0xFF,0xFF,0xFF}};// 15 White

// Get time

 clock();

// Application prompt

 printf("TMSopt v.0.03 - TGA 24bpp to TMS9918 converter\nCoded by Eduardo A. Robsy Petrus & Arturo Ragozini, 2007\n");
// Test if only one command-line parameter is available
argc = 2;
argv[1] = malloc(20);
argv[1][0] = 'e';
argv[1][1] = 'a';
argv[1][2] = 'r';
argv[1][3] = 't';
argv[1][4] = 'h';
argv[1][5] = '.';
argv[1][6] = 't';
argv[1][7] = 'g';
argv[1][8] = 'a';
argv[1][9] = 0;


 if (argc==1)
 {
  printf("Syntax: TMSopt [file.tga]\n");
  return;
 }

// Open source image (TGA, 24-bit, uncompressed)

 if ((file=fopen(argv[1],"rb"))==NULL)
 {
  printf("cannot open %s file!\n",argv[1]);
  return;
 }

// Read TGA header

 for (i=0;i<18;i++) header[i]=fgetc(file);

// Check header info

 for (i=0,n=0;i<12;i++) n+=header[i];

 if ((n!=2)||(header[2]!=2)||(header[17])||(header[16]!=24))
 {
  printf("Unsupported file format!\n");
  return;
 }

// Calculate size

 MAXX=header[12]|header[13]<<8;
 MAXY=header[14]|header[15]<<8;

 size=((MAXX+7)>>3)*MAXY;

// Check size limits

 if ((!MAXX)||(MAXX>512)||(!MAXY)||(MAXY>512))
 {
  printf("Unsupported size!");
  return;
 }

// Load image data

 for (y=MAXY-1;y>=0;y--)
  for (x=0;x3;y++)
    for (x=0;x<(MAXX+7)>>3;x++)
        for (j=0;j<8;j++)
        {
            // Generate alternatives
            unsigned char c1,c2;
            unsigned long bs=32000;
            unsigned char bp =0, bc = 0;
            
            for (c1=1;c1<16;c1++)
                for (c2=c1+1;c2<16;c2++)
                {
                    unsigned int cs = 0;
                    unsigned int cp = 0;
                    for (i=0;i<8;i++)
                    {
                        unsigned int mc1=0,mc2=0;
                        for (k=0;k<3;k++) {
                            mc1+=abs(palette[c1][k]-image[x<<3|i][y<<3|j][k]);
                            mc2+=abs(palette[c2][k]-image[x<<3|i][y<<3|j][k]);
                        }
                        if (mc1>mc2) {
                            cp = (cp<<1) | (0x01);
                            cs += mc2;
                        }
                        else {
                            cp = (cp<<1) | (0x00);
                            cs += mc1;
                        }
                    }
                    if  (csmc2)    {   
                        cp = (cp<<1) | (0x01);  
                        for (k=0;k<3;k++) 
                            newpixel[k] = palette[bc2][k];
                    }
                    else    {   
                        cp = (cp<<1) | (0x00);  
                        for (k=0;k<3;k++) 
                            newpixel[k] = palette[bc1][k];
                    }
                    
                    // save the current point 
                                        
                    for (k=0;k<3;k++)     
                        oldpixel[k] = image[x<<3|i][y<<3|j][k];

                    // store the current point - now quantized
                        
                    for (k=0;k<3;k++)     
                        image[x<<3|i][y<<3|j][k] = newpixel[k];

                    // compute the quantization error 
                    
                    for (k=0;k<3;k++)     
                        quant_error[k] = oldpixel[k] - newpixel[k];
                    
                    // spread the quantization error 
                    
                    if ((x<<3|(i+1)) 4:bc&0x0f][k];
//                    n<<=1;
//                }
            // Update status counter
            
                if (done*100/size<(done+1)*100/size) 
                    printf("\b\b\b%2i%%",100*done/size);
                done++;
                total++;
        }    

// Conversion done

 printf("\b\b\bOk   \n");

// Generate new name

 name=malloc(0x100);
 argv[1][strlen(argv[1])-4]=0;
 strcpy(name,argv[1]);
 strcat(name,"_tms.tga");

// Save file header

 file=fopen(name,"wb");

 for (i=0;i<18;i++) fputc(header[i],file);

// Save image data

 for (y=MAXY-1;y>=0;y--)
  for (x=0;x

Par AuroraMSX

Paragon (1902)

Portrait de AuroraMSX

19-05-2007, 12:44

It could use the <string.h> and <malloc.h> headers for the strlen/strcpy/strcat and malloc functions.That'll cost ya one beer
Okay, I'll bite...
"why?"
Because I can't read *_* (I read 'I ' instead of 'It'). Nevah mind.

Par pitpan

Prophet (3152)

Portrait de pitpan

19-05-2007, 14:39

Very cool, ARTRAG!

I was about to code the 2nd alternative when you came with that one and then another one with Floyd-Steinberg!

Amazing!

Par ARTRAG

Enlighted (6862)

Portrait de ARTRAG

19-05-2007, 15:06

note that this Floyd has some "rounding" problems.
The errors loose a lot of usefully digits.
I'm on a version with better math proprieties.

Par ARTRAG

Enlighted (6862)

Portrait de ARTRAG

19-05-2007, 19:48

FULLY WORKING NOW!!
Pitpan, have a look!
PS I tested it only on one image, and I have no idea about the CHR & CLR files
l wait for feedback


/*
---------------------------------------------------------------
TMSOPT v.0.04 - Eduardo A. Robsy Petrus & Arturo Ragozini, 2007
---------------------------------------------------------------
 TGA image converter (24 bpp, uncompressed) to TMS9918 format
---------------------------------------------------------------
Overview
---------------------------------------------------------------
Selects the best local solution for each 8x1 pixel block
Optimization uses the following algorithm:

(a) For each pixel, RGB differences are calculated
  - All RGB channels have the same weight
  - It uses absolute error instead of squared error

(b) This error value is added for all pixels in each 8x1 block

(c) The CHR-CLR combination with lowest error rate is selected

It is a brute-force method, computationally very expensive.
Some patience and a high-clocked CPU computed is recommended.
---------------------------------------------------------------
Compilation instructions
---------------------------------------------------------------
 Tested with GCC/Win32 [mingw]:

   GCC TMSopt.c -oTMSopt.exe -O3 -s

 It is standard C, so there is a fair chance of being portable!
---------------------------------------------------------------
History
---------------------------------------------------------------
 Ages ago   - algorithm created
 16/05/2007 - first C version (RAW format)
 17/05/2007 - TGA format included, some optimization included
 18/05/2007 - Big optimization (200 times faster), support for 
              square errors
 19/05/2007 - Floyd-Stenberg added, scaling for better rounding
---------------------------------------------------------------
Legal disclaimer
---------------------------------------------------------------
 Do whatever you want to do with this code/program.
 Use at your own risk, all responsability would be declined.
 It would be nice if you credit the author, though.
---------------------------------------------------------------
*/

// Headers!

#include<stdio.h>
#include<time.h>
#include<limits.h>


#define scale 32

#define inrange8(t) ((t)<0) ? 0 :(((t)>255) ? 255:(t))

#define clamp(t)    ((t)<0) ? 0 :(((t)>255*scale) ? 255*scale : (t))

/////////////////
// scanning direction
// DIR=1  ->
// DIR=0  <-
#define DIR 1

/////////////////////////////
// switch palette MSX1 MSX2
// (approssimate)

#define MSX1

// Just one function for everything

main(int argc, char **argv)
{

// Vars

 FILE *file,*CHR,*CLR;
 int bc,bp,i,j,x,y,c,p,k,MAXX,MAXY;
 unsigned int n,total=0,done=0,size;
 char *name;
 short image[512][512][3],header[18],palette[16][3];

// TMS9918 RGB palette - approximated 50Hz PAL values
 unsigned int pal[16][3]= {
#ifdef MSX1
{ 0,0,0},
{ 0,0,0},
{ 33,200,66},
{ 94,220,120},
{ 84,85,237},
{ 125,118,252},
{ 212,82,77},
{ 66,235,245},
{ 252,85,84},
{ 255,121,120},
{ 212,193,84},
{ 230,206,128},
{ 33,176,59},
{ 201,91,186},
{ 204,204,204},
{ 255,255,255}
#endif
#ifdef MSX2
{0x00,0x00,0x00}, //  0 Transparent - black (not used)
{0x00,0x00,0x00}, //  1 Black
{0x12,0xFF,0x00}, //  2 Green
{0x76,0xFF,0x6F}, //  3 Light green
{0x12,0x00,0xFF}, //  4 Blue
{0x69,0x69,0xFF}, //  5 Light blue
{0xA1,0x10,0x10}, //  6 Dark red
{0x00,0xFF,0xFC}, //  7 Cyan
{0xFF,0x00,0x00}, //  8 Red
{0xFF,0x80,0x80}, //  9 Light red
{0xFF,0xEA,0x00}, // 10 Yellow
{0xFF,0xFB,0x80}, // 11 Light yellow
{0x1D,0xA8,0x02}, // 12 Dark green
{0xFF,0x00,0xFC}, // 13 Magenta
{0xCC,0xCC,0xCC}, // 14 Light gray
{0xFF,0xFF,0xFF}  // 15 White
#endif
};
// Scale palette

 for (i=0;i<16;i++) 
     for (k=0;k<3;k++) 
        palette[i][k] = scale*pal[i][k];

// Get time

 clock();

// Application prompt

 printf("TMSopt v.0.04 - TGA 24bpp to TMS9918 converter\nCoded by Eduardo A. Robsy Petrus & Arturo Ragozini, 2007\n");
// Test if only one command-line parameter is available

// Guess the name of the image I used for testing
#ifdef DEBUG
argc = 2;
argv[1] = malloc(20);
argv[1][0] = 'e';
argv[1][1] = 'a';
argv[1][2] = 'r';
argv[1][3] = 't';
argv[1][4] = 'h';
argv[1][5] = '.';
argv[1][6] = 't';
argv[1][7] = 'g';
argv[1][8] = 'a';
argv[1][9] = 0;
#endif

 if (argc==1)
 {
  printf("Syntax: TMSopt [file.tga]\n");
  return;
 }

// Open source image (TGA, 24-bit, uncompressed)

 if ((file=fopen(argv[1],"rb"))==NULL)
 {
  printf("cannot open %s file!\n",argv[1]);
  return;
 }

// Read TGA header

 for (i=0;i<18;i++) header[i]=fgetc(file);

// Check header info

 for (i=0,n=0;i<12;i++) n+=header[i];

// I deleted the check on n, was it important ?
 if ((header[2]!=2)||(header[17])||(header[16]!=24))
 {
  printf("Unsupported file format!\n");
  return;
 }

// Calculate size

 MAXX=header[12]|header[13]<<8;
 MAXY=header[14]|header[15]<<8;

 size=((MAXX+7)>>3)*MAXY;

// Check size limits

 if ((!MAXX)||(MAXX>512)||(!MAXY)||(MAXY>512))
 {
  printf("Unsupported size!");
  return;
 }

// Load image data

 for (y=MAXY-1;y>=0;y--)
  for (x=0;x3;y++)
    for (x=0;x<(MAXX+7)>>3;x++)
        for (j=0;j<8;j++)
        {
            // Generate alternatives
            unsigned char c1,c2;
            unsigned int bs = INT_MAX;
            unsigned char bp = 0, bc = 0;
            
            for (c1=1;c1<16;c1++)
                for (c2=c1+1;c2<16;c2++)
                {
                    unsigned int cs = 0;
                    unsigned int cp = 0;
                    for (i=0;i<8;i++)
                    {
                        int xx = (x<<3)|i;
                        int yy = (y<<3)|j;            

                        unsigned int mc1=0,mc2=0;
                                
                        xx = (DIR) ? (xx) : (MAXX - 1 - xx);
                        
                        for (k=0;k<3;k++) {
                            int  d1 = abs(palette[c1][k]-image[xx][yy][k]);
                            int  d2 = abs(palette[c2][k]-image[xx][yy][k]);
                            mc1+=d1*d1;
                            mc2+=d2*d2;
                        }
                        if (mc1>mc2) {
                            cp = (cp<<1) | (0x01);
                            cs += mc2;
                        }
                        else {
                            cp = (cp<<1) | (0x00);
                            cs += mc1;
                        }
                    }
                    if  (csmc2)    {   
                        cp = (cp<<1) | (0x01);  
                        for (k=0;k<3;k++) 
                            newpixel[k] = palette[bc2][k];
                    }
                    else    {   
                        cp = (cp<<1) | (0x00);  
                        for (k=0;k<3;k++) 
                            newpixel[k] = palette[bc1][k];
                    }

                    // compute the quantization error 
                    
                    for (k=0;k<3;k++)     
                        quant_error[k] = image[xx][yy][k] - newpixel[k];

                    // store the current point - now quantized
                        
                    for (k=0;k<3;k++)     
                        image[xx][yy][k] = newpixel[k];

                    // spread the quantization error 
                      
                    if (DIR){
                        if (xx+1<=MAXX-1)                    
                            for (k=0;k<3;k++)                         
                                image[xx+1][yy+0][k] =  clamp(image[xx+1][yy+0][k]+(7 * quant_error[k])/16);
    
                        if (yy+1<=MAXY-1) {
                        
                            for (k=0;k<3;k++)     
                                image[xx+0][yy+1][k] =  clamp(image[xx+0][yy+1][k]+(5 * quant_error[k])/16);
    
                            if (xx-1 >=0)
                                for (k=0;k<3;k++)                         
                                    image[xx-1][yy+1][k] = clamp(image[xx-1][yy+1][k]+(3 * quant_error[k])/16);
                                    
                            if (xx+1 <=MAXX-1)                          
                                for (k=0;k<3;k++)     
                                    image[xx+1][yy+1][k] = clamp(image[xx+1][yy+1][k]+(quant_error[k])/16);
                        }
                    }
                    else    {
                        if (xx-1>=0)                    
                            for (k=0;k<3;k++)                         
                                image[xx-1][yy+0][k] =  clamp(image[xx-1][yy+0][k]+(7 * quant_error[k])/16);

                        if (yy+1<=MAXY-1) {

                            for (k=0;k<3;k++)     
                                image[xx+0][yy+1][k] =  clamp(image[xx+0][yy+1][k]+(5 * quant_error[k])/16);
    
                            if (xx-1 >=0)
                                for (k=0;k<3;k++)                         
                                    image[xx-1][yy+1][k] = clamp(image[xx-1][yy+1][k]+( quant_error[k])/16);
                                    
                            if (xx+1 <=MAXX-1)                          
                                for (k=0;k<3;k++)     
                                    image[xx+1][yy+1][k] = clamp(image[xx+1][yy+1][k]+(3 * quant_error[k])/16);
                        }
                    }
                }
                // Forget the previous pattern not based on dithering
                bp = cp;            
            }
                
                
            // Save best pattern and colour combination
                fputc(bp,CHR);
                fputc(bc,CLR);

//            // Replace original image data with TMS result
//                n=bp;
//                for (i=0;i<8;i++)
//                {
//                    for (k=0;k<3;k++)
//                        image[x<<3|i][y<<3|j][k]=palette[n&0x80?bc>>4:bc&0x0f][k];
//                    n<<=1;
//                }

            // Update status counter
            
                if (done*100/size<(done+1)*100/size) 
                    printf("\b\b\b%2i%%",100*done/size);
                done++;
                total++;
        }    

// Conversion done

 printf("\b\b\bOk   \n");

// Generate new name

 name = malloc(0x100);
 argv[1][strlen(argv[1])-4]=0;
 strcpy(name,argv[1]);
 strcat(name,"_tms.tga");

// Save file header

 file=fopen(name,"wb");

 for (i=0;i<18;i++) fputc(header[i],file);

// Save image data

 for (y=MAXY-1;y>=0;y--)
  for (x=0;x		

Par ARTRAG

Enlighted (6862)

Portrait de ARTRAG

19-05-2007, 20:43

here the full package for who wants to test it
http://ragozini.googlepages.com/sc2conv.rar

Page 6/13
1 | 2 | 3 | 4 | 5 | | 7 | 8 | 9 | 10 | 11