Изменение количества цветов PCX-файла
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.173] |
|
|
Изменение количества цветов PCX-файла
|
Сообщ.
#1
,
|
|
|
|
Приветствую всех форумчан! Необходимо преобразовать 256-цветный PCX файл в 16-цветный BMP файл. Как это сделать из True Color PCX файла мне известно, код представлен ниже:
![]() ![]() //--------------------------------------------------------------------------- #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: ![]() ![]() 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 видно вообще один черный квадрат. Буду признателен любой помощи. Спасибо. |
|
Сообщ.
#2
,
|
|
|
|
Цитата glyc @ 256-цветный Это как? Есть отдельно палитра из 256-ти цветов, а каждый пиксел изображения - это один байт (индекс цвета в палитре)? Может тогда, сначала, преобразовать такой PCX-файл в True Color PCX, а уже потом, рабочим алгоритмом в желаемый BMP? |
|
Сообщ.
#3
,
|
|
|
|
В том-то и дело, что нужно именно 256-цветный файл преобразовать в 16-цветный. TrueColor тут вообще не нужен.
|
|
Сообщ.
#4
,
|
|
|
|
картинка маленькая, типа иконки ?
Описание формата PCX с примером программы на С Добавлено ОПИСАНИЕ ФОРМАТА PCX И НЕКОТОРЫХ УТИЛИТ PC PAINTBRUSH Добавлено хм... если ФотоШоп сделал каку, то IrfanView очень даже прилично справился |
|
Сообщ.
#5
,
|
|
|
|
Old, спасибо, но как это может помочь моей проблеме?
Согласен, IrfanView я сам пользуюсь и никогда ее на другое не променяю. |
|
Сообщ.
#6
,
|
|
|
|
Цитата Chow @ Может тогда, сначала, преобразовать такой PCX-файл в True Color PCX, а уже потом, рабочим алгоритмом в желаемый BMP? вот, уважаемый Chow дело предложил , ведь главное что ? решить вопрос, ИМХО ...а Вы, похоже, сами себе проблемы придумываете |
|
Сообщ.
#7
,
|
|
|
|
Ребята, вопрос поставлен конкретно! Это мое задание, именно это, а не другие методы, насколько бы они ни были адекватными.
|
|
Сообщ.
#8
,
|
|
|
|
это кто ж Вас так озадачил
... |
|
Сообщ.
#9
,
|
|
|
|
Озадачил преподаватель. Будут реальные советы?
Добавлено Не вижу смысла делать лишние преобразования. При MAXCOLOR16 эффект тот же - кракозябры. Здесь нужен иной подход к самому открытию файла. True Color PCX заметно отличается от 256 и 16- цветных PCX. |
|
Сообщ.
#10
,
|
|
|
|
Цитата glyc @ нужен иной подход вот и я о том же... а что, если: 1. 256 PCX в 256 ВМР 2. 256 БМР в 16 ВМР думаю, нареканий со стороны преподавателя это вызвать не должно и все же, реальный вопрос: а Вы предлагали оному преподавателю рассмотреть вариант с промежуточным преобразованием файла PCX в True Color PCX ? как вариант ? Добавлено Цитата glyc @ иной подход к самому открытию файла то есть ? а как Вы его открываете ? |
|
Сообщ.
#11
,
|
|
|
|
glyc, разбираться в приведенном вами коде что бы просто потом ткнуть носом "вот тут поменяй что-бы заработало" - никто не будет.
Если вы автор этого кода, и знаете (или ознакомились с форматом PCX из приведенных Old'ом ссылок) - то проблем внести необходимые изменения у вас быть не должно. Добавлено Давайте конкретней вопрос: что вы хотите? 1. готовый (иной) рабочий алгоритм преобразования 256-цветного PCX файла в 16-цветный BMP 2. что-бы кто-то разобрался и поправил приведенный вами алгоритм что-бы он корректно заработал 3. ваш вариант |
|
Сообщ.
#12
,
|
|
|
|
Chow Ввиду того, что язык С++ мне мало знаком, меня вполне устроит как первый так и второй вариант.
|
|
Сообщ.
#13
,
|
|
|
|
1 - ну надо уповать на то, что у кого-то есть и он поделится
2 - тогда вам в подработку |
|
Сообщ.
#14
,
|
|
|
|
Chow, Old, спасибо.
|
|
Сообщ.
#15
,
|
|
|
|
Цитата Зверь Ваш препод... BMP (Bitmap — .bmp, .dib и .rle) — формат, созданный Microsoft, за счет чего в свое получил широкое распространение. Максимальный размер изображения 65535×65535 пикселей. В настоящее время относится к вымирающим видам. К тому же виду относится и аналогичный формат PCX, разработанный еще в эпоху MS-DOS, и хорошо сжимающий лишь простые рисунки. |
|
Сообщ.
#16
,
|
|
|
|
Цитата Old @ Зверь Ваш препод... Судя по Цитата glyc @ #include <iostream.h> они еще на турбо си++ пишут. |