На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Изменение количества цветов PCX-файла
    Приветствую всех форумчан! Необходимо преобразовать 256-цветный PCX файл в 16-цветный BMP файл. Как это сделать из True Color PCX файла мне известно, код представлен ниже:
    ExpandedWrap disabled
      //---------------------------------------------------------------------------
      #define MAXCOLORTC
       
      #include "wingraph.h"
      #include "graphfmts.h"
      #include <iostream.h>
      #include <fstream.h>
       
      #define inFileName "inpic.pcx"
      #define outFileName "outpic79.bmp"
      //---------------------------------------------------------------------------
       
       
      //---------------------------------------------------------------------------
       
      void drawImage(int x, int y, int w, int h, TPaletteStruct * pal, char * buf){
         for (int i=0; i<h; i++){
            for (int j=0; j<w; j++){
               int index=(i*w+j);
               DWORD c=0;
               if (pal==NULL){
                  index*=3;
                  c=RGB(buf[index], buf[index+1], buf[index+2]);
               }else{
                  c=RGB(pal[buf[index]].Red, pal[buf[index]].Green, pal[buf[index]].Blue);
               }
               putpixel(x+j, y+i,c);
            }
         }
      }
      //---------------------------------------------------------------------------
      void decodePcx(char * srcBuff, int srcBuffSz, char ** img, int * imgSz){
         TPCXHeader *h=(TPCXHeader *)srcBuff;
         srcBuff+=sizeof(TPCXHeader)-1;
         srcBuffSz-=sizeof(TPCXHeader)+1;
         int nPlanes=3;//h->Planes;
       
         int xn=h->XMax - h->XMin + 1;
         int yn=h->YMax - h->YMin + 1;
         *imgSz=xn * yn * nPlanes;
         *img=new char[*imgSz];
         char count=0;
         int lines=0;
         char src;
         char curPlane=-1;
         char * curDst=0;
         char * lineDst=*img;
         int p=0;
         int i=0;
         int srcCount=0;
         char * maxImg=*img+*imgSz;
         while((lines<yn) && (i<srcBuffSz) && (curDst<maxImg)){
            if (p==0){
               p=xn;
               curPlane++;
               if (curPlane<nPlanes){
                  curDst=lineDst+curPlane;
               }else{
                  lines++;
                  curDst++;
                  lineDst=curDst-3;
                  curPlane=0;
                  count=0;
               }
            }
            if (lines<(yn) && (curDst<maxImg)){
               if (count>0){
                    *curDst=src;
                    curDst=curDst+nPlanes;
                    p--;
                    count--;
                }else{
                   src=srcBuff[i];
                   i++;
                   srcCount++;
                   if ((src & 0xC0)!=0xC0){
                      *curDst=src;
                      curDst=curDst+nPlanes;
                      p--;
                   }else{
                      count=src & 0x3F;
                      src=srcBuff[i];
                      i++;
                      srcCount++;
                   }
                }
             }
         }
         int q=0;
      }
      //---------------------------------------------------------------------------
      bool cmpColors(TPaletteStruct c1, TPaletteStruct c2){
         c1.Red=c1.Red & 0xC0;
         c2.Red=c2.Red & 0xC0;
         c1.Blue=c1.Blue & 0xC0;
         c2.Blue=c2.Blue & 0xC0;
         c1.Green=c1.Green & 0xE0;
         c2.Green=c2.Green & 0xE0;
         return ( (c1.Red==c2.Red) && (c1.Green == c2.Green) && (c1.Blue == c2.Blue) );
      }
       
      long getColorDif(TPaletteStruct c1, TPaletteStruct c2){
         return ( (c1.Red-c2.Red)*(c1.Red-c2.Red) + (c1.Green - c2.Green)*(c1.Green - c2.Green) + (c1.Blue - c2.Blue)*(c1.Blue - c2.Blue) );
      }
       
      long getColorDif2(TPaletteStruct c1, TPaletteStruct c2){
         long const n=2;
         long dif=0;
         long difR=(c1.Red-c2.Red)*(c1.Red-c2.Red);
         long difG=(c1.Green - c2.Green)*(c1.Green - c2.Green);
         long difB=(c1.Blue - c2.Blue)*(c1.Blue - c2.Blue);
         if ( (difB > ((difR+difG)*n)) || (difG > ((difB+difR)*n)) || (difR > ((difB+difG)*n)) )
            dif=0xFFFFFF;
         else
            dif=difR+difB+difG;
         return dif;
      }
       
      //---------------------------------------------------------------------------
       
      void reduceColor(char * src, int srcSz, char ** dst, int * dstSz, TPaletteStruct * pal){
         float rate[16]; //rating
         for (int i=0; i<16; i++){
           pal[i].Red=0;
           pal[i].Green=0;
           pal[i].Blue=0;
           rate[i]=0;
         }
         float r1=3/(float)srcSz;
         float maxR=-1;
         float minR=0;
         int colsAdded=0;
         for (int i=0; i<srcSz; i+=3){
            TPaletteStruct c =  *((TPaletteStruct*)&src[i]);
            bool cont=false;
            for (int j=0; j<16; j++){
               if (cmpColors(pal[j], c)){
                  cont=true;
                  break;
               }
            }
            if (cont)
               continue;
            float r=0;
            //calc color count
            for (int k=i; k<srcSz; k+=3){
              if (cmpColors(c, *((TPaletteStruct*)&src[k])))
                  r+=r1;
            }
            if (r > maxR)
               maxR = r;
            if (colsAdded==0)
               minR = r;
            if (colsAdded < 16) {
              if (r<minR)
                  minR = r;
              pal[colsAdded]=c;
              colsAdded++;
            }else{
               if (r>minR){
                  int palIndex=0;
                  float minDif=0;
                  for (int j=0; j<16; j++){
                     if (rate[j]<r){
                        long dif=getColorDif(c, pal[j]);
                        if ( (j==0) || (dif<minDif) ){
                           minDif=dif;
                           palIndex=j;
                        }
                     }
                  }
                  pal[palIndex]=c;
       
                  float minRc=0;
                  if (rate[palIndex]==minR){
                     rate[palIndex]=r;
                     for (int j=0; j<16; j++){
                        if ((rate[j]<minRc) || (j==0)){
                           minRc=rate[j];
                        }
                     }
                  }else
                     rate[palIndex]=r;
       
              }
            }
         }
         //create paletted image
         *dstSz=srcSz/3;
         *dst=new char[*dstSz];
         char * dstP=*dst;
         for (int i=0; i<*dstSz; i++){
            char c2=0;
            TPaletteStruct c =  *((TPaletteStruct*)&src[i*3]);
            char palIndex=0;
            long minDif=0;
            for (int j=0; j<16; j++){
               float dif=getColorDif(c, pal[j]);
               if ( (j==0) || (dif<minDif) ){
                  minDif=dif;
                  palIndex=j;
               }
            }
            *dstP=palIndex;
            dstP++;
         }
      }
       
       
      //-----------------------------------------------------------------------
      void main(){
              TPCXHeader * pcxH;
              FILE * f;
              char * img;
              int w=0,h=0;
              char * wf;
              try{
                      f=fopen(inFileName, "r+");
                      fseek(f, 0, SEEK_END);
                      int sz=ftell(f);
                      fseek(f, 0, SEEK_SET);
                      wf=new char[sz];
                      int q2=sizeof(char);
                      int re=fread(wf, sizeof(char), sz, f);
                      if (*wf==0x0A){
                           int imgSz=0;
                           decodePcx(wf, sz, &img, &imgSz);
       
                           pcxH=(TPCXHeader *)wf;
                           w= pcxH->XMax - pcxH->XMin + 1;
                           h= pcxH->YMax - pcxH->YMin + 1;
                           resize(w*2+20, h+20);
                           drawImage(5,5,w,h, NULL ,img);
       
                           //---------------------------------
                           char * img16;
                           int img16Sz;
                           TPaletteStruct pal16[16];
                           reduceColor(img, imgSz, &img16, &img16Sz, pal16);
                           drawImage(15+w, 5, w, h, pal16, img16);
       
                      }
              }
              __finally{
                      fclose(f);
                      delete[] img;
                      delete[] wf;
              }
       
      }

    Листинг библиотеки graphfmts.h:
    ExpandedWrap disabled
      typedef struct TPCXHeaderStruct
       {
        unsigned char ID;
        unsigned char Version;
        unsigned char Coding;
        unsigned char BitPerPixel;
        unsigned short  XMin;
        unsigned short  YMin;
        unsigned short  XMax;
        unsigned short  YMax;
        unsigned short  HRes;
        unsigned short  VRes;
        unsigned char Palette[48];
        unsigned char Reserved;
        unsigned char Planes;
        unsigned short  BytePerLine;
        unsigned short  PaletteInfo;
        unsigned short  HScreenSize;
        unsigned short  VScreenSize;
        unsigned char Filler[54];
       } TPCXHeader;
       
      typedef struct TPaletteStruct
       {
        unsigned char Red;
        unsigned char Green;
        unsigned char Blue;
       } TPalette;
       
       
      struct  TBMPHeaderStruct {
              short bftype;
              long  bfsize;
              short rez1, rez2;
              long  bfoffbits;
              long  bisize;
              long  biwidth;
              long  biheight;
              short biplanes;
              short bibitcount;
              long  bicompression;
              long  bisizeimage;
              long  bix;
              long  biy;
              long  biclrused;
              long  biclrimp;
      } TBMPHeader;

    Но вот скормить программе 256-цветный PCX-файл никак не получается.
    Если подсунуть этому коду не TrueColor а 256-цветный файл, то получаются кракозябры, изображение еле-еле можно угадать. При замене MAXCOLORTC на MAXCOLOR256 видно вообще один черный квадрат. Буду признателен любой помощи. Спасибо.
      Цитата glyc @
      256-цветный

      Это как?
      Есть отдельно палитра из 256-ти цветов, а каждый пиксел изображения - это один байт (индекс цвета в палитре)?
      Может тогда, сначала, преобразовать такой PCX-файл в True Color PCX, а уже потом, рабочим алгоритмом в желаемый BMP?
        В том-то и дело, что нужно именно 256-цветный файл преобразовать в 16-цветный. TrueColor тут вообще не нужен.
          картинка маленькая, типа иконки ?
          Описание формата PCX с примером программы на С

          Добавлено
          ОПИСАНИЕ ФОРМАТА PCX И НЕКОТОРЫХ УТИЛИТ PC PAINTBRUSH

          Добавлено
          хм... если ФотоШоп сделал каку, то IrfanView очень даже прилично справился :)
          Сообщение отредактировано: Old -
            Old, спасибо, но как это может помочь моей проблеме?
            Согласен, IrfanView я сам пользуюсь и никогда ее на другое не променяю.
              Цитата Chow @
              Может тогда, сначала, преобразовать такой PCX-файл в True Color PCX, а уже потом, рабочим алгоритмом в желаемый BMP?

              вот, уважаемый Chow дело предложил :) , ведь главное что ? решить вопрос, ИМХО ...
              а Вы, похоже, сами себе проблемы придумываете :jokingly:
                Ребята, вопрос поставлен конкретно! Это мое задание, именно это, а не другие методы, насколько бы они ни были адекватными.
                  это кто ж Вас так озадачил :scratch: ...
                    Озадачил преподаватель. Будут реальные советы?

                    Добавлено
                    Не вижу смысла делать лишние преобразования. При MAXCOLOR16 эффект тот же - кракозябры. Здесь нужен иной подход к самому открытию файла. True Color PCX заметно отличается от 256 и 16- цветных PCX.
                      Цитата glyc @
                      нужен иной подход

                      вот и я о том же...
                      а что, если:
                      1. 256 PCX в 256 ВМР
                      2. 256 БМР в 16 ВМР
                      думаю, нареканий со стороны преподавателя это вызвать не должно
                      и все же, реальный вопрос: а Вы предлагали оному преподавателю рассмотреть вариант с промежуточным преобразованием файла PCX в True Color PCX ? как вариант :) ?

                      Добавлено
                      Цитата glyc @
                      иной подход к самому открытию файла

                      то есть ? а как Вы его открываете ?
                        glyc, разбираться в приведенном вами коде что бы просто потом ткнуть носом "вот тут поменяй что-бы заработало" - никто не будет.
                        Если вы автор этого кода, и знаете (или ознакомились с форматом PCX из приведенных Old'ом ссылок) - то проблем внести необходимые изменения у вас быть не должно.

                        Добавлено
                        Давайте конкретней вопрос: что вы хотите?
                        1. готовый (иной) рабочий алгоритм преобразования 256-цветного PCX файла в 16-цветный BMP
                        2. что-бы кто-то разобрался и поправил приведенный вами алгоритм что-бы он корректно заработал
                        3. ваш вариант
                          Chow Ввиду того, что язык С++ мне мало знаком, меня вполне устроит как первый так и второй вариант.
                            1 - ну надо уповать на то, что у кого-то есть и он поделится
                            2 - тогда вам в подработку
                              Chow, Old, спасибо.
                                Цитата
                                BMP (Bitmap — .bmp, .dib и .rle) — формат, созданный Microsoft, за счет чего в свое получил широкое распространение. Максимальный размер изображения 65535×65535 пикселей. В настоящее время относится к вымирающим видам. К тому же виду относится и аналогичный формат PCX, разработанный еще в эпоху MS-DOS, и хорошо сжимающий лишь простые рисунки.
                                Зверь Ваш препод...
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,1592 ]   [ 16 queries used ]   [ Generated: 27.11.25, 22:46 GMT ]