Archived

This topic is now archived and is closed to further replies.

Cirian

Help? Anyone?

Recommended Posts

This is one of the "I am new and my code takes six years to run; I also like jelly"-type posts, but I really need help. The code shown below is a *very* simple method of compacting animations (a bit like RLE). It was designed more as a test than anything else, but it would certainly help alot if I could increase the speed.
  

bool MASICi9::CreateDGR(String file,short frames,String output,bool prepend)
{
 ofstream loge("DGREncode.txt") // log file

 if (prepend){TBuffA->LoadFromFile(file + "0000.bmp");}
 else{TBuffA->LoadFromFile(file + "0.bmp");} //Load the source bitmap into a Graphics::TBitmap object.

 i2 = TBuffA->Height;
 i1 = TBuffA->Width;
 h = i1*i2;    
 w = h*frames;
 loge << "DGR Encoder (1.6) -- MASICi9" << endl << "Writing DGR V.2 (adv)" << endl << "Pixels per image = " << h << endl << "Total number of pixels = " << w << endl;
 x = h;
 output += ".dgr"; //add extention to name of output file

 ofstream out(output.c_str(),ios::binary); //open an output file stream

 loge << "Writing header....";
 out.put(''D''); //signature and version

 out.put(''G'');
 out.put(''R'');
 out.put(''2'');
 out.write((char *)(&frames),2); //frames

 out.write((char *)(&i1),4); //width

 out.write((char *)(&i2),4); //height

 loge << "done: " << frames << " frames, " << i1 << " width " << i2 << " height." << endl << "Writing first frame....";
 h = 0;
 for (int bc = 0; bc<i2; bc++)
 {
  for (int ac = 0; ac<i1; ac++)
  {
   T = TBuffA->Canvas->Pixels[ac][bc]; //store the 32 bit pixel data from the bitmap canvas in a TColor object.

   out.write((char *)(&T),sizeof(T)); //write the TColor object to the file

   h++; //log data

  }
 }
 w = 4*h;
 loge << "done: " << w << " bytes, forming " << h << " pixels." << endl;
 s = 9+w;
 for (int i = 1; i<=frames; i++) //for frames 2->n

 {
  loge << "Writing frame " << i+1 << ".....";
  //read the source frame, and the previous frame (TBuffA is the previous, TBuffG is the current frame).

  if (prepend)
  {
   if (i < 10)
   {
    TBuffA->LoadFromFile(file+ "000" + String(i-1)+".bmp");
    TBuffG->LoadFromFile(file+ "000" + String(i)+".bmp");
   }
   else if (i < 100)
   {
    if (i == 10){TBuffA->LoadFromFile(file+ "000" + String(i-1)+".bmp");}
    else {TBuffA->LoadFromFile(file+ "00" + String(i-1)+".bmp");}
    TBuffG->LoadFromFile(file+ "00" + String(i)+".bmp");
   }
   else if (i < 1000)
   {
    if (i == 100){TBuffA->LoadFromFile(file+ "00" + String(i-1)+".bmp");}
    else {TBuffA->LoadFromFile(file+ "0" + String(i-1)+".bmp");}
    TBuffG->LoadFromFile(file+ "0" + String(i)+".bmp");
   }
  }
  else
  {
   TBuffA->LoadFromFile(file+String(i-1)+".bmp");
   TBuffG->LoadFromFile(file+String(i)+".bmp");
  }
  h = 0;
  w = 0;
  m = 0;
  if (TBuffG->Height == i2 && TBuffG->Width == i1)
  {
   i3 = 0;
   s4 = 0;
   for (int bc = 0; bc<i2; bc++)
   {
    for (int ac = 0; ac<i1; ac++) 
    {
     m++;
     FG = TBuffA->Canvas->Pixels[ac][bc]; //save pixels as a TColor

     BG = TBuffG->Canvas->Pixels[ac][bc];
     if (FG == BG) //if they are the same, increment the counter, and discard the pixels

     {
      i3++;
      w++;
     }
     if (FG != BG) //otherwise.....

     {
      if (i3 != 0) //if the counter is greater than zero, write the number of skipped pixels (includes a signature "//").

      {
       out.put(''/'');
       out.put(''/'');
       out.write((char *)(&i3),sizeof(i3));
       i3 = 0;
       s4++;
      }
      out.write((char *)(&BG),sizeof(BG)); //write the new pixel

      h++;
     }
    }
   }
   if (i3 != 0)
   {
    out.put(''/'');
    out.put(''/'');
    out.write((char *)(&i3),sizeof(i3)); //write the number of skipped pixels at the end of the current frame (if any)

    s4++;
   }
  }
  else
  {
   return false;
  }
  loge << "done: " << m << " pixels, " << h << " were unique, and " << w << " were copies -- " << (h*4) + (6*s4) << " bytes." << endl;
  x += h;
  s += (h*4) + (6*s4);
 }
 loge << "DGR Encoding complete." << endl << "DGR Size: " << s << " bytes." << endl << "Source bitmap size: " << (i1*i2*frames*4)+(54*frames) << " bytes.";
 out.close();
 loge.close(); //close the file streams

 return true;
}

  
I said it was pretty basic, but it does what I want. The pixels (although really 24 bit) seem to include a padding block to align them to the 32 bit memory thingie.... though that top level byte seems critical (removal results in bad stuff happening....). and now the decoder..... this is where the problem is. If any more than about 15,000 pixels change in a single frame, everthing gets horrifically jerky.
  
bool MASICi9::DrawDGR(String file,int x,int y,TCanvas* surface)
{
 ifstream in(file.c_str(),ios::binary); //open file

 if (in.get() == ''D'') //check signature

 {
  if (in.get() == ''G'')
  {
   if (in.get() == ''R'')
   {
    test = false; //set default version

    c1 = in.get();
    if (c1 == ''2'')//check actual version

    {test = true;}
    //the next lines read the header, frames, width and height

    if (!test)
    {
     in.read((char *)(&s4),2);
     in.read((char *)(&s1),2);
     in.read((char *)(&s2),2);
     i1 = s1;
     i2 = s2;
    }
    else
    {
     in.read((char *)(&s4),2);
     in.read((char *)(&i1),sizeof(i1));
     in.read((char *)(&i2),sizeof(i2));
    }
    TBuffG->Height = i2; //set bitmap height

    TBuffG->Width = i1; //set bitmap width

    for (int bc = 0; bc<i2; bc++)
    {
     for (int ac = 0; ac<i1; ac++) 
     {
      in.read((char *)(&FG),sizeof(FG)); //read the pixel from the file;

      TBuffG->Canvas->Pixels[ac][bc] = FG; //store pixel to temporary bitmap

     }
    }
    surface->Draw(x,y,TBuffG); //draw bitmap to window

    for (int i = 1; i<=s4; i++) //read compressed frames

    {
     i3 = 0;
     m = 0;
     for (int bc = 0; bc<i2; bc++)
     {
      for (int ac = 0; ac<i1; ac++) 
      {
       if (i3 == 0) //if skipped pixel counter is zero

       {
        if (in.peek()==''/'') //search for skip signature

        {
         in.get();
         if (in.peek()==''/'')
         {
          in.get();
          if (test){in.read((char *)(&i3),sizeof(i3));} //read 4 bytes of skipped pixels if version 2

          else{in.read((char *)(&s3),sizeof(s3));i3=s3;} //read 2 bytes if version 1

          bc--;
         }
         else
         {
          c1 = ''/'';
          c2 = in.get();
          c3 = in.get();
          c4 = in.get();
          FG = (c1<<24) + (c2<<16) + (c3<<8) + c4;
          TBuffG->Canvas->Pixels[ac][bc] = FG; //on mistake (ie: pixel has a value of "/" in it -- untested, never actually happened), form a pixel from known data and store to canvas.

         }
        }
        else
        {
         in.read((char *)(&FG),sizeof(FG)); //if no signature found, read a pixel and store to canvas.

         TBuffG->Canvas->Pixels[ac][bc] = FG;
        }
       }
       else
       {
        i3--; //if skipped pixels > 0, count down.

       }
      }
     }
     App->ProcessMessages(); //check the windows message pump

     if (!DGRPlayOK) //if told to stop playing, exit

     {return false;}
     surface->Draw(x,y,TBuffG); //draw frame to canvas

    }
   }
  }
 }
 in.close(); //close file stream

 return true;
}

  
Please help -- as a newbie programmer there are probably millions of ways to optimise that I can''t see. If you''ve looked at this and thought "freaky code" or somesuch, it''s because I''m using Borland C++ Builder 5, which handles all the DCs and thingies. Probably a mixed blessing, since my code has to go through even more layes of processing, but it suits my needs (apart from speed). --Cirian

Share this post


Link to post
Share on other sites
If looks like you are reading the file every frame, which is really really slow, especially since you are reading it in tiny chunks at a time. Usually you want to read everthing in and store it in memory, then just draw the appropriate sprite from memory. If you wanted to speed up the file decoding (its still not going to be fast enough to do every frame) read the whole file into memory at once, and work on it there.

Share this post


Link to post
Share on other sites
Thanks invective -- I now have one that makes an array of chars, then loads the file at the start in 64 bit chunks. Playback is about 8 times faster.... now on to optimising the file loading sequence......

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Yay! After a while of tinkering and messing with other peoples code, it''s now running at about 800% speed, but only a 1 sec / 7meg loading pause... w00t.

Share this post


Link to post
Share on other sites