Отправляет email-рассылки с помощью сервиса Sendsay

Одинокий программист

  Все выпуски  

Одинокий программист


Информационный Канал Subscribe.Ru


Одинокий программист

Thanks, www.subscribe.ru

GIF файлы.(Условно!) #4

www.sandsc.narod.ru
e-mail:bigking@mail.ru, Седельников Александр

   Здравствуйте, это снова я! Теперь я попытаюсь рассказать о файлах GIF. По своей “натуре” его легко понять и довольно сложно написать. В принципе декодер “простой”. Хотя, что это я вам сразу про декодер! В самом начале файла, как у практически всех файлов есть заголовок. Он не большой. Включает в себя сам ID т.е. строку состоящую из 3 символов “GIF”; версия, состоящая из 3 символов, сразу следует за ID, она может принимать строки: “87a” и “89a”, вроде больше нет других, хотя за это время все может случиться, вдруг вышел давно другой GIF! Ну, ладно, их всего лишь два, не больше и не меньше. Различия составляет только добавленные комментарии в GIF89a, а принцип кодировки тот же самый что и у GIF87a. GIF – это упакованные графические файлы. В отличии от файлов JPEG, GIF не теряет качества изображения, но может работать с цветовой гаммой не превышающий 256 цветов. Так, я отвлекся! Хочу предупредить, что полностью рабочий пример я опубликовывать не буду! Так как, насколько я помню, LZW метод упаковки(именно он применяется к упаковке данных в GIF) запатентован, а значит, могут быть не приятные последствия! Но общий принцип я расскажу, а распаковка не сложная, ее можно найти даже в Интернете! Вот так. После определения версии файла, идут размеры картинки по ширине и высоте. Затем информация о самой картинки: использование локальных данных или глобальных, интерлейсный режим и т.д. Далее идет информация о разрешении, вычисляется : (PixelAspectRatio+16)/64 (точно не помню). И после всего этого, находится глобальная карта цветов, размером size=(1<<((информация о самой картинки AND 7)+1)). Практически ту же самую структуру имеют и локальные данные. После чего идет сама распаковка. Еще что нужно сказать о конце файла. Он всегда заканчивается символом терминатором(выходом, емусоответствует символ точка с запятой), так же нужно сказать о интерлейсном режиме, он сделан специально, чтобы картинка не загружалась вся сразу, а по строкам. Это хорошо для Net’a. А теперь я скажу, почему я назвал GIF(Условно!), да потому, что он не работает. Нужна функция LZWdecoder, которая при каждом вызове возвращала распакованный пиксел.

#ifndef __GIF_H__
#define __GIF_H__

#define RGB16(r,g,b) (((r&0x3F)<<11)|((g&0x3F)<<5)|(b&0x3F))
// #define TRUE 0
// #define FALSE 1 //(Others)
#define MAX_LWZ_BITS 12

#define max(a,b)        (((a) > (b)) ? (a) : (b))
#define min(a,b)        (((a) < (b)) ? (a) : (b))

typedef unsigned char   BYTE;
typedef signed short    SHORT;
typedef unsigned short  WORD;
typedef signed long     LONG;
typedef unsigned long   DWORD;

struct Color{
 char r,g,b;
};

struct GIFHeader
{
    char        ID[3];
    char        Version[3];
    unsigned short   Width;
    unsigned short   Height;
    char        PackedField;
    char        ColorIndex;
    char        AspectRatio;
    Color       glbColor[256];
}gifhead;

struct GIFImgDesc
{
    WORD        ImageLeft;
    WORD        ImageTop;
    WORD        ImageWidth;
    WORD        ImageHeight;
    char        PackedField;
    Color       locColor[256];
}gifImgDesk;

int ReadGIFImgDesk(FILE *fp,GIFImgDesc *gid)
{
 register int cx=0;
 int tableSize=0;
 fread(gid,sizeof(GIFImgDesc)-769,1,fp);
 if(ferror(fp))
  return 1;
 return 0;
}

void GIFReadColorMap(FILE *fp,int size,Color *cls)
{
 for(int cx=0;cx=lastbit)
 {
  if(done&&curbit>=lastbit)
     return -1;
  buf[0]=buf[last_byte-2];
  buf[1]=buf[last_byte-1];

  if((count=ReadDataBlock(fp,&buf[2]))==0)
   done=1;
  last_byte=2+count;
  curbit=(curbit-lastbit)+16;
  lastbit=(2+count)*8;
 }
 ret=0;
 for(i=curbit,j=0;j=0);
   return;
 }
  while((v=GIFLZWReadByte(fp,0,c))>=0)
  {
   *(buf+ypos*len+xpos)=(unsigned short)
    (RGB16((unsigned char)cmap[v].r,
     (unsigned char)cmap[v].g,
     (unsigned char)cmap[v].b));
   xpos++;
   if(xpos==len)
   {
    xpos=0;
    if(interlace)
    {
     switch(pass)
     {
      case 0:
      case 1:
       ypos+=8; break;
      case 2:
       ypos+=4; break;
      case 3:
       ypos+=2; break;
     }
    if (ypos>=height)
    {
     ++pass;
     switch (pass)
     {
      case 1:
       ypos = 4; break;
      case 2:
       ypos = 2; break;
      case 3:
       ypos = 1; break;
      default:
      goto __finit__;
   }
  }
  }else{++ypos;}
   }
   if(ypos>=height)
    break;
  }

__finit__:
//  if (LZWReadByte(fp,0,c)>=0)
//   warning!
  GIFLZWReadByte(fp,0,c);
}
//
// Main function:
// Usage:
//
// int w=0,h=0;
//
// ReadGIFto16bBuffer
//
int ReadGIFto16bBuffer(char *fn,int &w,int &h,long &bufAddress)
{
 FILE *fp=fopen(fn,"rb");
 if(fp==NULL)
  return 1;
 int sz=sizeof(GIFHeader)-769;
 fread(&gifhead,sz,1,fp);
 if(strncmp(gifhead.ID,"GIF",3)) return 2;
 if(strncmp(gifhead.Version,"87a",3)) return 3;
 w=gifhead.Width;
 h=gifhead.Height;
 unsigned short *buffer=new unsigned short[w*h];
 unsigned short *ptr=buffer;
 int tableSize=0,cx;
 if(gifhead.PackedField&0x80)
 {
  tableSize = (WORD) (1L << ((gifhead.PackedField & 0x07) + 1));
  GIFReadColorMap(fp,tableSize,gifhead.glbColor);
 }
 int i=0;
while(1)
{
 i=(int)fgetc(fp);
 if(i==0x3B)
 {
   fclose(fp);
   bufAddress=(long)buffer;
   return 0;
 }
 if(i!=',')
  continue;
 ReadGIFImgDesk(fp,&gifImgDesk);
 tableSize = (WORD) (1L << ((gifImgDesk.PackedField & 0x07) + 1));
 if(gifImgDesk.PackedField&0x80)
 {
  GIFReadColorMap(fp,tableSize,gifImgDesk.locColor);
  DecodeImage(fp,
   gifImgDesk.ImageWidth,
   gifImgDesk.ImageHeight,
   gifImgDesk.locColor,
   gifImgDesk.PackedField&0x40,
   0,
   buffer
  );
 }
 else
 {
  DecodeImage(fp,
   gifImgDesk.ImageWidth,
   gifImgDesk.ImageHeight,
   gifhead.glbColor,
   gifImgDesk.PackedField&0x40,
   0,
   buffer
  );
 }
}
 fclose(fp);
 bufAddress=(long)buffer;
 return 0;
}


Одинокий программист

Thanks, www.subscribe.ru

GIF файлы.(Условно!) #4

www.sandsc.narod.ru
e-mail:bigking@mail.ru, Седельников Александр

   Здравствуйте, это снова я! Теперь я попытаюсь рассказать о файлах GIF. По своей “натуре” его легко понять и довольно сложно написать. В принципе декодер “простой”. Хотя, что это я вам сразу про декодер! В самом начале файла, как у практически всех файлов есть заголовок. Он не большой. Включает в себя сам ID т.е. строку состоящую из 3 символов “GIF”; версия, состоящая из 3 символов, сразу следует за ID, она может принимать строки: “87a” и “89a”, вроде больше нет других, хотя за это время все может случиться, вдруг вышел давно другой GIF! Ну, ладно, их всего лишь два, не больше и не меньше. Различия составляет только добавленные комментарии в GIF89a, а принцип кодировки тот же самый что и у GIF87a. GIF – это упакованные графические файлы. В отличии от файлов JPEG, GIF не теряет качества изображения, но может работать с цветовой гаммой не превышающий 256 цветов. Так, я отвлекся! Хочу предупредить, что полностью рабочий пример я опубликовывать не буду! Так как, насколько я помню, LZW метод упаковки(именно он применяется к упаковке данных в GIF) запатентован, а значит, могут быть не приятные последствия! Но общий принцип я расскажу, а распаковка не сложная, ее можно найти даже в Интернете! Вот так. После определения версии файла, идут размеры картинки по ширине и высоте. Затем информация о самой картинки: использование локальных данных или глобальных, интерлейсный режим и т.д. Далее идет информация о разрешении, вычисляется : (PixelAspectRatio+16)/64 (точно не помню). И после всего этого, находится глобальная карта цветов, размером size=(1<<((информация о самой картинки&7)+1)). Практически ту же самую структуру имеют и локальные данные. После чего идет сама распаковка. Еще что нужно сказать о конце файла. Он всегда заканчивается символом терминатором(выходом, емусоответствует символ точка с запятой), так же нужно сказать о интерлейсном режиме, он сделан специально, чтобы картинка не загружалась вся сразу, а по строкам. Это хорошо для Net’a. А теперь я скажу, почему я назвал GIF(Условно!), да потому, что он не работает. Нужна функция LZWdecoder, которая при каждом вызове возвращала распакованный пиксел.

#ifndef __GIF_H__
#define __GIF_H__

#define RGB16(r,g,b) (((r&0x3F)<<11)|((g&0x3F)<<5)|(b&0x3F))
// #define TRUE 0
// #define FALSE 1 //(Others)
#define MAX_LWZ_BITS 12

#define max(a,b)        (((a) > (b)) ? (a) : (b))
#define min(a,b)        (((a) < (b)) ? (a) : (b))

typedef unsigned char   BYTE;
typedef signed short    SHORT;
typedef unsigned short  WORD;
typedef signed long     LONG;
typedef unsigned long   DWORD;

struct Color{
 char r,g,b;
};

struct GIFHeader
{
    char        ID[3];
    char        Version[3];
    unsigned short   Width;
    unsigned short   Height;
    char        PackedField;
    char        ColorIndex;
    char        AspectRatio;
    Color       glbColor[256];
}gifhead;

struct GIFImgDesc
{
    WORD        ImageLeft;
    WORD        ImageTop;
    WORD        ImageWidth;
    WORD        ImageHeight;
    char        PackedField;
    Color       locColor[256];
}gifImgDesk;

int ReadGIFImgDesk(FILE *fp,GIFImgDesc *gid)
{
 register int cx=0;
 int tableSize=0;
 fread(gid,sizeof(GIFImgDesc)-769,1,fp);
 if(ferror(fp))
  return 1;
 return 0;
}

void GIFReadColorMap(FILE *fp,int size,Color *cls)
{
 for(int cx=0;cx=lastbit)
 {
  if(done&&curbit>=lastbit)
     return -1;
  buf[0]=buf[last_byte-2];
  buf[1]=buf[last_byte-1];

  if((count=ReadDataBlock(fp,&buf[2]))==0)
   done=1;
  last_byte=2+count;
  curbit=(curbit-lastbit)+16;
  lastbit=(2+count)*8;
 }
 ret=0;
 for(i=curbit,j=0;j=0);
   return;
 }
  while((v=GIFLZWReadByte(fp,0,c))>=0)
  {
   *(buf+ypos*len+xpos)=(unsigned short)
    (RGB16((unsigned char)cmap[v].r,
     (unsigned char)cmap[v].g,
     (unsigned char)cmap[v].b));
   xpos++;
   if(xpos==len)
   {
    xpos=0;
    if(interlace)
    {
     switch(pass)
     {
      case 0:
      case 1:
       ypos+=8; break;
      case 2:
       ypos+=4; break;
      case 3:
       ypos+=2; break;
     }
    if (ypos>=height)
    {
     ++pass;
     switch (pass)
     {
      case 1:
       ypos = 4; break;
      case 2:
       ypos = 2; break;
      case 3:
       ypos = 1; break;
      default:
      goto __finit__;
   }
  }
  }else{++ypos;}
   }
   if(ypos>=height)
    break;
  }

__finit__:
//  if (LZWReadByte(fp,0,c)>=0)
//   warning!
  GIFLZWReadByte(fp,0,c);
}
//
// Main function:
// Usage:
//
// int w=0,h=0;
//
// ReadGIFto16bBuffer
//
int ReadGIFto16bBuffer(char *fn,int &w,int &h,long &bufAddress)
{
 FILE *fp=fopen(fn,"rb");
 if(fp==NULL)
  return 1;
 int sz=sizeof(GIFHeader)-769;
 fread(&gifhead,sz,1,fp);
 if(strncmp(gifhead.ID,"GIF",3)) return 2;
 if(strncmp(gifhead.Version,"87a",3)) return 3;
 w=gifhead.Width;
 h=gifhead.Height;
 unsigned short *buffer=new unsigned short[w*h];
 unsigned short *ptr=buffer;
 int tableSize=0,cx;
 if(gifhead.PackedField&0x80)
 {
  tableSize = (WORD) (1L << ((gifhead.PackedField & 0x07) + 1));
  GIFReadColorMap(fp,tableSize,gifhead.glbColor);
 }
 int i=0;
while(1)
{
 i=(int)fgetc(fp);
 if(i==0x3B)
 {
   fclose(fp);
   bufAddress=(long)buffer;
   return 0;
 }
 if(i!=',')
  continue;
 ReadGIFImgDesk(fp,&gifImgDesk);
 tableSize = (WORD) (1L << ((gifImgDesk.PackedField & 0x07) + 1));
 if(gifImgDesk.PackedField&0x80)
 {
  GIFReadColorMap(fp,tableSize,gifImgDesk.locColor);
  DecodeImage(fp,
   gifImgDesk.ImageWidth,
   gifImgDesk.ImageHeight,
   gifImgDesk.locColor,
   gifImgDesk.PackedField&0x40,
   0,
   buffer
  );
 }
 else
 {
  DecodeImage(fp,
   gifImgDesk.ImageWidth,
   gifImgDesk.ImageHeight,
   gifhead.glbColor,
   gifImgDesk.PackedField&0x40,
   0,
   buffer
  );
 }
}
 fclose(fp);
 bufAddress=(long)buffer;
 return 0;
}



http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное