Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Куросовая по графике для почты.doc
Скачиваний:
2
Добавлен:
09.07.2019
Размер:
209.92 Кб
Скачать

Государственный комитет Российской Федерации по телекоммуникациям

Сибирский государственный университет

телекоммуникаций и информатики

Курсовая работа

По дисциплине

«Представление графической информации»

Вариант №3

Работу выполнил

студент 6 курса

группы ЗП - 61

Печенкин А. А.

Работу проверила

Перцев И. В.

Работа защищена

«___» __________2011г.

С оценкой «_______»

Новосибирск 2011

Содержание

Задание…………………………………………………………………………3

Требования к оформлению отчета................................................................3

Описание алгоритма ……………….………………………………………..3

1. Исходный текст программы……………………………………………...4

2. Скриншот программы…………………………………………………...12

3. Заключение………………………………………………………………..13

4. Список литературы………………………………………………………14

Задание Номер варианта контрольной работы определяется по последней цифре пароля

Ввиду отсутствия пароля задание было взято по последней цифре студенческого билета

Написать программу конвертор. Для уменьшения количества цветов выбираются наиболее часто встречаемые цвета в исходном изображении. Причем эти цвета не должны быть слишком похожими друг на друга. Для сравнения цветов вычисляются разности между RGB составляющими.

Delta=(R1-R2)2 + (G1-G2)2+ (B1-B2)2

Программа должны выводить изображение на экран до и после конвертирования.

  1. Преобразовать True Color PCX файл в 16-цветный PCX файл.

Требования к оформлению отчета

Необходимо представить следующее:

  1. Текст задания

  2. Текст программы (файл с расширением .сpp)

  3. Все файлы, относящиеся к проекту, в том числе EXE-файл

Описание алгоритма выполнения работы

Из файла считывается заголовок РСХ файла и на основании заголовка декодируется в растр графическая информация. Далее растр конвертируется из True Color в 16 цветом методом медианного сечения, выбираются максимальное значения в облаке и для сравнения цветов вычисляются разности между RGB составляющими. Delta=(R1-R2)2 + (G1-G2)2+ (B1-B2)2

Создается палитра и формируется растр с использованием сформированной палитры, далее растр кодируется и сохраняется в файл. Ввиду ограниченности информации по кодировнию, использовалось кодирование обратное ранее использованному декодированию. Так как существующие программы открывали файл некорректно, в программу добавлено декодирование РСХ файла 16 цветов. В результате работы программы на экран выводится 3 изображения – True Color, 16 цветов и считанное из файла 16 цветное изображение.

  1. Исходный текст программы

#define MAXCOLORTC

#include <stdio.h>

#include <windows.h>

#include <stdlib.h>

#include <io.h>

#include <math.h>

#include <iostream>

#include "wingraph.h"

#include <vector>

using namespace std;

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;

TPCXHeader PCXHeader, Header16;

typedef struct TRastrStruct//массив значений растра

{

int R;

int G;

int B;

} TRastr;

TRastr palet;

vector<TRastr> low, top, rastrTC, rastr16;

typedef struct TPalStruct//Массив "облака" цветов

{

vector<TRastr> pal;//вектор значений палитры

bool flag;

}Tpaltmp;

vector<Tpaltmp> paltemp; //массив облаков

typedef struct TRaitStruct//массив рейтинга цветов в облаке

{

int color;

int count;

}TRait;

vector<TRait> reit;

unsigned char imax;

int minR, minG, minB, maxR, maxG, maxB, maxreit;

//определение минимального и максимального значений цветов*************************

void minmax(vector<TRastr> color)

{

maxR = maxG = maxB = 0;

minR = minG = minB = 255;

for (int i = 0; i < (int)color.size(); i++)

{

if (color[i].R > maxR) maxR = color[i].R;

if (color[i].R < minR) minR = color[i].R;

if (color[i].G > maxG) maxG = color[i].G;

if (color[i].G < minG) minG = color[i].G;

if (color[i].B > maxB) maxB = color[i].B;

if (color[i].B < minB) minB = color[i].B;

}

}

//*********************************************************************************

void cloud (vector<TRastr> color)

{

//определяем наибольшую грань и делим пополам

int cl; // определяет по какому цвету будет считать

int size, mediana;// середина наибольшей грани

if ((maxR - minR) > (maxG - minG)){ size = maxR - minR;cl = 1;}

else if ((maxG - minG) > (maxB - minB)) {size = maxG - minG;cl =2;}

else {size = maxB - minB; cl =3;}

switch(cl)//делим наибольшую грань пополам по выбранному цвету

{

case 1:

{//делим красную грань пополам

for (int i = 0; i < (int)color.size(); i++)

{

mediana = minR + size/2;

if ((int)color[i].R > mediana) top.push_back(color[i]);

else low.push_back(color[i]);

}

break;

}

case 2:

{//делим зеленую грань пополам

for (int i = 0; i < (int)color.size(); i++)

{

mediana = minG + size/2;

if (color[i].G > mediana) top.push_back(color[i]);

else low.push_back(color[i]);

}

break;

}

case 3:

{//делим синюю грань пополам

for (int i = 0; i < (int)color.size(); i++)

{

mediana = minB + size/2;

if (color[i].B > mediana) top.push_back(color[i]);

else low.push_back(color[i]);

}

break;

}

default: break;

}

}

//добавление элемента****************************************************

void insvek(vector<TRastr> vek)//добавление облака во временную палитру

{

bool endin = true;

int i = 0;

while(endin)

{

if ((paltemp[i].pal.size() == NULL)||(paltemp[i].flag))

{

if (vek.size() != NULL)

{

paltemp[i].pal = vek;//добавляем облако

paltemp[i].flag = false;//устанавливаем запрет на изменение значений

break;

}

}

i++;

if (i > 15) endin = false;

}

}

//*********************************************************************************

void ColorReit(int c1)//типа гистограмма, рейтинг цветов

{

TRait temp;

if (reit.size() == NULL )//первое значение вектора

{

temp.color = c1;

temp.count = 1;

reit.push_back(temp);

}

else

{

for (int i =0; i < (int)reit.size(); i++)//цикл проверки частоты вхождения

{

if(reit[i].color == c1)//увеличиваем рейтинг при совпадении цвета

{

reit[i].count++;

if (reit[i].count > maxreit)

{

maxreit = reit[i].count;

imax = reit[i].color;

}

break;

}

else

{

if (i == reit.size()-1)//добавляем новый цвет для сравнения

{

temp.color = c1;

temp.count = 1;

reit.push_back(temp);

}

}

}

}

}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void main()

{

paltemp.resize(16);//задаем размер вектора палитры из облаков

FILE *f_in, *f_out;

int w_s, h_s, count;

f_in = NULL;

fopen_s(&f_in,"honda.pcx","r+b");

if (f_in == NULL) MessageBox(NULL,"Файл не найден!", "Ok", MB_OK);

else

{

fread(&PCXHeader, 1, sizeof(PCXHeader), f_in);//считываем заголовок РСХ файла

w_s = PCXHeader.XMax - PCXHeader.XMin + 1;

h_s = PCXHeader.YMax - PCXHeader.YMin + 1;

rastrTC.resize(h_s * w_s + 1);

unsigned char temp;

// читаем и декодируем растр

fseek(f_in,(long)128,0);//устанав указатель файла на начало графической информации

bool end_pic = true;

int indOne, sloy, h_r, w_r, k;

BYTE col;

k = indOne = sloy = h_r = w_r = 0;

while (end_pic)//цикл вывода графического файла

{

fread(&temp,1,1,f_in);//чтение первого байта графической информации

if(temp>=192)//проверка ьайта на наличие в нем информации о группе

{

indOne = h_r * w_s + w_r;

count = (int)(temp&63);//внесение количества повторений в переменную

fread(&temp,1,1,f_in);//чтение информации о группе

col = (int)temp;//считываем из файла информацию о цвете группы

for(int j = 0; j < count; j++)//цикл чтения группы массив растра

{

switch (sloy)//в соответ со счит слоем вносим данные в растр

{

case 0: {rastrTC[indOne + j].R = col; break;}

case 1: {rastrTC[indOne + j].G = col; break;}

case 2: {rastrTC[indOne + j].B = col; break;}

default:break;

}

}

w_r = w_r + count;//увеличиваем количество выведенных пикселей

}

else//чтение в массив растра одинчного цвета

{

col = (int)temp;

indOne = h_r * w_s + w_r;

switch (sloy)

{

case 0: {rastrTC[indOne].R = col; break;}

case 1: {rastrTC[indOne].G = col; break;}

case 2: {rastrTC[indOne].B = col; break;}

default: break;

}

w_r++;

}

if (w_r >= w_s)//проверка конца строки

{

w_r = 0;

sloy++;//изменяем значения слоя

if (sloy > 2)

{

sloy = 0;

h_r++;

if (h_r >= h_s)

{

break;

}

}

}

}

fclose(f_in);

//выделение палитры******************************************************

bool notfinal = true;//переменная окончания формирования массива основных цветов

int poz =0;

int maxvk, i;

paltemp[poz].pal = rastrTC;

paltemp[poz].flag = false;

//**********************************************************************

while (notfinal)

{

maxvk = k = 0;

while (k < 15)

{

if ((int)paltemp[k].pal.size() > maxvk)//опред максим длину вектора

{

maxvk = paltemp[k].pal.size();

poz = k;

}

k++;

if (paltemp[k].pal.size() == NULL) break;

}

minmax(paltemp[poz].pal);//определяем ширину граней облака

cloud(paltemp[poz].pal);//формируем из одного облака два новых

paltemp[poz].flag = true;

insvek(top);//добавляем облако

insvek(low);//добавляем облако

low.clear();//очищаем вектор

top.clear();//очищаем вектор

for(int i = 0; i < (int)paltemp.size(); i++ )//проверка на заполение

{

if (paltemp[i].flag == false) notfinal = false;

else notfinal = true;

}

}

// формирование палитры***************************************************************

for (poz = 0; poz < 16; poz++)//формируем плитру на основании рейтинга

{ // цветов в облаках

minmax(paltemp[poz].pal);

i = maxreit = imax = 0 ;

while (i < maxR - minR){ColorReit(paltemp[poz].pal[i+minR].R); i++;}

Header16.Palette[poz * 3] = imax;

i = maxreit = imax = 0;

while (i < maxG - minG){ColorReit(paltemp[poz].pal[i+minG].G); i++;}

Header16.Palette[(poz * 3) + 1] = imax;

i = maxreit = imax = 0;

while (i < maxB - minB){ColorReit(paltemp[poz].pal[i+minB].B); i++;}

Header16.Palette[(poz * 3) + 2] = imax;

}

//формирование растра16 ************************************************************

int j = 0, mind;

unsigned char jmin = 0;

int delta;

vector<unsigned char> rst16;

for (i = 0; i < (int)rastrTC.size(); i++)//формирование растра 16 цветов

{

mind = 10000000;

while(j < 16)

{//сравниваем значения созданой палитры с цветами в ТС растре

palet.R = Header16.Palette[j * 3];

palet.G = Header16.Palette[(j * 3) + 1];

palet.B = Header16.Palette[(j * 3) + 2];

delta = (palet.R - rastrTC[i].R) * (palet.R - rastrTC[i].R) +

(palet.G - rastrTC[i].G) * (palet.G - rastrTC[i].G) +

(palet.B - rastrTC[i].B) * (palet.B - rastrTC[i].B);

if (delta < mind )//если разница минимальна запоминаем значение

{

mind = delta;

jmin = j;

}

j++;

}

rst16.push_back(jmin);//добавляем значение палитры в растр

j = 0;

}

//кодирование и сохранение растра в файл***********************************************

Header16.ID = PCXHeader.ID;

Header16.Version = 2;

Header16.Coding = 1;

Header16.BitPerPixel = 4;

Header16.XMax = PCXHeader.XMax;

Header16.YMax = PCXHeader.YMax;

Header16.XMin = PCXHeader.XMin;

Header16.YMin = PCXHeader.YMin;

Header16.Planes = 1;

Header16.PaletteInfo = 1;

Header16.HRes = 0;

Header16.VRes = 0;

Header16.Reserved = 0;

Header16.BytePerLine = 300;

fopen_s(&f_out,"out16.pcx","w+b");

fwrite(&Header16,sizeof(Header16),1,f_out);

int pz = 0, povtor = 1, w16 = 0;

unsigned char tmp_w = 0;

while (pz <(int)rst16.size() - 1)

{

if ((rst16[pz] == rst16[pz + 1]) && (povtor < 63) && (w16 < (w_s - 1)))

{

povtor++;

pz++;

w16++;

}

else

{

if (povtor <= 1)//проверяем одиночный пиксель

{

tmp_w = rst16[pz];

fwrite(&tmp_w,1,1,f_out);//записываем

pz++;

if (w16 >= (w_s - 1)) w16 = 0; else w16++;

//проверка конца строки

povtor = 1;

}

else

{

tmp_w = povtor +192;//вносим данные о серии

fwrite(&tmp_w,1,1,f_out);//записываем информацию о серии

tmp_w = rst16[pz];//вносим данные о цвете

fwrite(&tmp_w,1,1,f_out);//записываем информацию о цвете

pz++;

if (w16 >= (w_s - 1)) w16 = 0; else w16++;

//проверка конца строки

povtor = 1;

}

}

}

fclose(f_out);

//чтение сохраненного файла*******************************************************

vector<unsigned char> r16;

unsigned char bait16;

fopen_s(&f_out,"out16.pcx", "r+b");

fread(&PCXHeader, 1, sizeof(PCXHeader), f_out);//считываем заголовок РСХ файла

w_s = PCXHeader.XMax - PCXHeader.XMin + 1;

h_s = PCXHeader.YMax - PCXHeader.YMin + 1;

r16.resize(w_s * h_s + 1);

w_r = h_r = 0;

while (end_pic)

{

fread(&bait16,1,1,f_out);

if(bait16 >= 192)//проверка ьайта на наличие в нем информации о группе

{

indOne = h_r * w_s + w_r;

count = (int)(bait16&63);//внес количества повторений в переменную

fread(&bait16,1,1,f_out);//чтение информации о группе

col = bait16;//считываем из файла информацию о цвете группы

for(int j = 0; j < count; j++)//цикл чтения группы массив растра

{

r16[indOne + j] = col;

}

w_r = w_r + count;//увеличиваем количество выведенных пикселей

}

else//чтение в массив растра одинчного цвета

{

col = bait16;

indOne = h_r * w_s + w_r;

r16[indOne] = col;

w_r++;

}

if (w_r >= w_s)//проверка конца строки

{

w_r = 0;

h_r++;

if (h_r >= h_s)

{

break;

}

}

}

fclose(f_out);

//*************************** Вывод растров и файла на экран ************************

int x = 3;

int y = 0;

int r = 0, g = 0, b = 0;

resize(3 * w_s+ x, h_s);

int idx;

for (int i = 0; i < h_s; i++)

{

for (int j = 0; j < w_s ; j++)

{

idx = i * w_s + j;

putpixel(j, i,RGB(rastrTC[idx].R,

rastrTC[idx].G,

rastrTC[idx].B) ) ;

putpixel(w_s + x + j, y + i,RGB(Header16.Palette[rst16[idx] * 3],

Header16.Palette[(rst16[idx] * 3) + 1],

Header16.Palette[(rst16[idx] * 3) + 2]) ) ;

putpixel(2 * w_s + 2 * x + j, y + i,RGB(Header16.Palette[r16[idx] * 3],

Header16.Palette[(r16[idx] * 3) + 1],

Header16.Palette[(r16[idx] * 3) + 2]) ) ;

}

}

}

return;

}