forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

[Code]Loading a PCX file

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Lua Player Development
View previous topic :: View next topic  
Author Message
Ferrero



Joined: 19 Dec 2005
Posts: 15

PostPosted: Fri Jan 06, 2006 2:03 am    Post subject: [Code]Loading a PCX file Reply with quote

Hi everybody, I've developped a little class to load and blit a PCX file.

The interest of this :

- You can have an image larger than 512x512 pixels.

Another thing :

- As a PCX file is an indexed color image file (compressed), finally you have an array of byte which you can fill with a picture editor. So in this file you can store a map to have a 2D tiled game, and this file is compressed.

Here's the class :
Code:

-------------------------------------------------------------------------------         
--
--   Author      :   Lepecq Michael (Ferrero)
--   Version      :   1.0
--   Copyright   :   2005 - 2006      
--
-------------------------------------------------------------------------------
--
--  This object is designed to manage PCX Files
--
--  Methods :
--
--      Public :
--         
--         load : load a PCX file
--
--      Private :
--
--         decodeHeader    : Decode the header of a pcx file
--         loadPalette256   : Load the 256 colors palette of the file
--         readPixel      : Read the Pixel of the file
--
--   Properties :
--   
--
--      Public :
--
--         BitsPerPixel       : The number of bits per pixel per plane in the image data.
--         MaxNumberOfColors    : The maximum number of colors allowed in the file
--         Palette            : Hold the different colors of the image
--         ImageWidth         : Width of the image in pixel
--         ImageHeight         : Hieght of the image in scanlines
--         BlitTo            : Blit the PCX to an image
--
--      Private :
--
--         XStart          : Left of the image
--         YStart          : Top of the image
--         XEnd          : Right of the image
--         YEnd          : Bottom of the image
--         NumBitPlanes   : Number of bit planes
--         BytesPerLine   : Length of an unencoded line in a plane
--         ScanLineLength   : Length of an unencoded line
--         Pixel         : Array of pixels [y][x]
--         LinePaddingSize : Padding of a scanline (end of a scan line)
--
-------------------------------------------------------------------------------

clsPCX =
{
    BitsPerPixel = 0,
    XStart       = 0,
    YStart       = 0,
    XEnd       = 0,
    YEnd       = 0,
    NumBitPlanes = 0,
    MaxNumberOfColors = 0,
    BytesPerLine = 0,
    Palette       = {},
    ImageWidth    = 0,
    ImageHeight  = 0,
    Pixel       = {},
    LinePaddingSize = 0
}

function clsPCX:new()
   mtbPCX = {};
   setmetatable(mtbPCX, self);
   self.__index = self;
   return mtbPCX;
end

function clsPCX:load(filename)
   
   local file     = assert(io.open(filename, "rb"));
    local header = file:read(128);
   
    -- Decoding the header
   
    assert(self:decodeHeader(header));
     
   -- Reading the Pixel
   
   assert(self:readPixel(file));
   
    -- Loading the palette
   
    if (self.MaxNumberOfColors == 256) then
       assert(self:loadPalette256(file));
   else   
      return nil, "This palette mode is not supported yet";
   end
   
   -- Closing the file
   
    assert(file:close());
   
    return true
   
end

function clsPCX:decodeHeader(header)
   
   if (string.byte(header, 1) == 10) then
      
      self.BitsPerPixel = string.byte(header, 4);
      self.XStart   = string.byte(header, 6) * 256 + string.byte(header, 5);
      self.YStart   = string.byte(header, 8) * 256 + string.byte(header, 7);
      self.XEnd   = string.byte(header, 10) * 256 + string.byte(header, 9);
      self.YEnd   = string.byte(header, 12) * 256 + string.byte(header, 11);
      self.NumBitPlanes = string.byte(header, 66);
      self.BytesPerLine = string.byte(header, 68) * 256 + string.byte(header, 67);
      
      self.MaxNumberOfColors = (2^self.BitsPerPixel * self.NumBitPlanes);
      self.ScanLineLength = self.NumBitPlanes * self.BytesPerLine;
      self.ImageWidth  = self.XEnd - self.XStart + 1;
      self.ImageHeight = self.YEnd - self.YStart + 1;
      self.LinePaddingSize = ((self.BytesPerLine * self.NumBitPlanes) * (8 / self.BitsPerPixel)) - ((self.XEnd - self.XStart) + 1);
   
   else
      return nil, "This is not a valid PCX file";
   end
   
   return true;
end

function clsPCX:loadPalette256(file)

    file:seek("end", -769);
    local CheckByte = file:read(1);
    local Palette   = file:read(768);
   local j=0;
   local i=0;   
   
    if (string.byte(CheckByte) == 12) then
       for i=1,768,3 do
          self.Palette[j] = Color.new(string.byte(Palette, i), string.byte(Palette, i+1), string.byte(Palette, i + 2));
          j = j + 1;
          
       end
   else
      return nil, "256 colors palette not found:"..CheckByte;
   end
   
    return true;
   
end

function clsPCX:readPixel(file)

   local y;
   local runcount;
   local byte;
   local x;
   local i;

   for y=0,self.ImageHeight-1 do
      self.Pixel[y] = {};
      x = 0;
      while (x<self.ScanLineLength) do
         
         byte = string.byte(file:read(1));
         if (byte >= 192) then
            runcount = byte - 192;
            byte = string.byte(file:read(1));
            for i=0, runcount do
               self.Pixel[y][x+i] = byte;
            end
            x = x + runcount;
            
         else
            
            self.Pixel[y][x] = byte;
            x = x + 1;
         end
         
      end
      
   end
   
    return true;
   
end

function clsPCX:blitTo(image_x, image_y, image, rect_left, rect_top, rect_right, rect_bottom)

   local line;
   local y;
   local x;
   local color;
   
   local ymin;
   local ymax;
   local xmin;
   local xmax;
   
   -- Computing the clipping
   
   if image_y < 0 then
      rect_top = rect_top - image_y;
      ymin = 0;
   else
      ymin = image_y;
   end
   
   if image_x < 0 then
      rect_left = rect_left - image_x;
      xmin = 0;
   else
      xmin = image_x;
   end
   
   if ymin + (rect_bottom - rect_top) >= image:height() then
      ymax = image:height() - 1;
   else
      ymax = ymin + (rect_bottom - rect_top);
   end
      
   if xmin + (rect_right - rect_left) >= image:width() then
      xmax = image:width() - 1;
   else
      xmax = xmin + (rect_right - rect_left);
   end
   
   if (xmax + rect_left >= self.ImageWidth) then
      xmax = self.ImageWidth - rect_left - 1;
   end
   
   if (ymax + rect_top >= self.ImageHeight) then
      ymax = self.ImageHeight - rect_top - 1;
   end
   
   -- Drawing the image
   
   for y=ymin,ymax do
      
      line = rect_top + y - image_y;
      
      for x=xmin, xmax do
         color = self.Palette[self.Pixel[line][rect_left + x - image_x]];
         image:pixel(x, y, color);
      end   
      
   end

    return true;
   
end


And how to use it :

Code:

map=clsPCX:new();
assert(map:load("..\\maps\\map1560.pcx"));

screen:clear();
map:blitTo(0,0,screen,0,0,480,272);
screen.flip();
control = Controls.read();

while control:start() == false do   
   control = Controls.read();
   screen.waitVblankStart();
end
Back to top
View user's profile Send private message Visit poster's website
LuMo



Joined: 21 Aug 2005
Posts: 410
Location: Austria

PostPosted: Fri Jan 06, 2006 3:43 am    Post subject: Reply with quote

how fast is it?
did you test it running compared to normal blit?
greets
lumo

PS: interesting!
_________________
"Good artists copy, great artists steal."
Pablo Picasso
go2lumo.com
Back to top
View user's profile Send private message Visit poster's website
Ferrero



Joined: 19 Dec 2005
Posts: 15

PostPosted: Fri Jan 06, 2006 6:17 pm    Post subject: Reply with quote

The blit is quite slow,

I use it like this :

First, I blit it to an 512*512 image and I use this image to blit onto the screen.
And when the image does not contain the needed datas I blit a portion of the image on itself to keep the datas I need, and then blit the portion of the PCX I need.
Back to top
View user's profile Send private message Visit poster's website
LuMo



Joined: 21 Aug 2005
Posts: 410
Location: Austria

PostPosted: Fri Jan 06, 2006 8:16 pm    Post subject: Reply with quote

only blit the really needed data, otherwise it really slows down...
480x272px more is never needed
greets
lumo
_________________
"Good artists copy, great artists steal."
Pablo Picasso
go2lumo.com
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Lua Player Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group