Страница 1 из 1

преобразование HSV в RGB

Добавлено: Ср янв 04, 2017 21:29:23
FreshMan
доброго времени суток
если кто делал подобное, подскажите пожалуйста
согласно вики https://ru.wikipedia.org/wiki/HSV_(%D1% ... %BB%D1%8C)
Изображение
написал ф-цию преобразования
http://dpaste.com/2VQG4WC
но выдает она мягко говоря не то что надо
подскажите пожалуйста, как правильно написать

Re: преобразование HSV в RGB

Добавлено: Ср янв 04, 2017 22:07:02
ARV
попробуйте вот это - я накорябал сам на основе тех ссылок, которые вам рекомендовал. думаю, разберетесь...

Код: Выделить всё

/** \file rgb.c
 * \par \author ARV \par
 * \n \date	25 дек. 2016 г.
 * Copyright 2015 © ARV. All rights reserved.
 * \par
 * Для компиляции требуется:\n
 * 	-# Atmel Toolchain 3.4.5 или более новая версия
 */

#include <avr/io.h>
#include <avr_helper.h>

/// если этот макрос есть, оттенок (HUE для HSV-модели цвета) будет в градусах
/// иначе в условных единицах от 0 до 255
//#define HUE_SMOOTH

#if defined(HUE_SMOOTH)
#define hue_t	uint16_t
#define HUE_MAX	360
#else
#define hue_t	uint8_t
#define HUE_MAX	256
#endif

#define HUE_QUADRANT	((HUE_MAX + 5)/ 6)

typedef struct{
	uint8_t		r;
	uint8_t		g;
	uint8_t		b;
} color_rgb_t;

typedef struct{
	hue_t		h;
	uint8_t		s;
	uint8_t		v;
} color_hsv_t;

void hsv_to_rgb(const color_hsv_t *hsv, color_rgb_t *rgb);
void rgb_to_hsv(const color_rgb_t *rgb, color_hsv_t *hsv);

void hsv_to_rgb(const color_hsv_t *hsv, color_rgb_t *rgb){
	uint8_t region, fpart, p, q, t;

	if(hsv->s == 0) {
		/* color is grayscale */
		rgb->r = rgb->g = rgb->b = hsv->v;
		return;
	}

	/* make hue 0-5 */
	region = hsv->h / HUE_QUADRANT;
	/* find remainder part, make it from 0-255 */
	fpart = (hsv->h - (region * HUE_QUADRANT)) * 6;

	/* calculate temp vars, doing integer multiplication */
	p = (hsv->v * (255 - hsv->s)) >> 8;
	q = (hsv->v * (255 - ((hsv->s * fpart) >> 8))) >> 8;
	t = (hsv->v * (255 - ((hsv->s * (255 - fpart)) >> 8))) >> 8;

	/* assign temp vars based on color cone region */
	switch(region) {
		case 0:
			rgb->r = hsv->v; rgb->g = t; rgb->b = p; break;
		case 1:
			rgb->r = q; rgb->g = hsv->v; rgb->b = p; break;
		case 2:
			rgb->r = p; rgb->g = hsv->v; rgb->b = t; break;
		case 3:
			rgb->r = p; rgb->g = q; rgb->b = hsv->v; break;
		case 4:
			rgb->r = t; rgb->g = p; rgb->b = hsv->v; break;
		default:
			rgb->r = hsv->v; rgb->g = p; rgb->b = q; break;
	}
}

#define MIN(x,y)	((x) < (y))?(x):(y)
#define MAX(x,y)	((x) > (y))?(x):(y)

void rgb_to_hsv(const color_rgb_t *rgb, color_hsv_t *hsv){
	uint8_t min, max, delta;
	int16_t hsvh;

	min = MIN(rgb->r, MIN(rgb->g, rgb->b));
	max = MAX(rgb->r, MAX(rgb->g, rgb->b));

	hsv->v = max;                // v, 0..255
	delta = max - min;                      // 0..255, < v

	if(max != 0)
		hsv->s = (int)(delta)*255 / max;        // s, 0..255
	else {
		// r = g = b = 0        // s = 0, v is undefined
		hsv->s = 0;
		hsv->h = 0;
		return;
	}

	if(rgb->r == max)
		hsvh = (rgb->g - rgb->b)*HUE_QUADRANT/delta;        // between yellow & magenta
	else if(rgb->g == max)
		hsvh = (HUE_QUADRANT*2) + (rgb->b - rgb->r)*HUE_QUADRANT/delta;    // between cyan & yellow
	else
		hsvh = (HUE_QUADRANT*4) + (rgb->r - rgb->g)*HUE_QUADRANT/delta;    // between magenta & cyan

	if(hsvh < 0) hsvh += HUE_MAX;

	hsv->h = hsvh;
}

Re: преобразование HSV в RGB

Добавлено: Чт янв 05, 2017 12:06:09
FreshMan

Код: Выделить всё

const color_hsv_t *hsv
из каких соображений вы указатель сделали константой ?
значения получаются в процентах

Re: преобразование HSV в RGB

Добавлено: Чт янв 05, 2017 16:42:20
ARV
не указатель, а структуру, на которые он указывает - чтобы оптимизатор мог воспользоваться, если пожелает, тем фактом, что данные в этой струтуре меняться в функции не будут.
FreshMan писал(а):значения получаются в процентах
мне казалось, в моем коде значения должны получаться в пределах от 0 до 255. хотя сам-то я и не проверял - на вас надеюсь :)))

Re: преобразование HSV в RGB

Добавлено: Чт фев 02, 2017 21:12:43
FreshMan
после долгих поисков была найдена оптимальная ф-ция преобразования HSV в RGB для AVR которая выдает оптимальный результат :)
Спойлер

Код: Выделить всё

void hsv_to_rgb(volatile uint8_t *r, volatile uint8_t *g, volatile uint8_t *b, uint16_t h, uint8_t s, uint8_t v){
	uint8_t hi,fr, p, q, t;
	volatile uint8_t h_pr;

	    if(s == 0) {
	        /* color is grayscale */
	        *r = *g = *b = v;
	        return;
	    }

	    hi = h / 60;

	    switch(hi) {
	        case 0: h_pr = h;       break;
	        case 1: h_pr = h - 60;  break;
	        case 2: h_pr = h - 120; break;
	        case 3: h_pr = h - 180; break;
	        case 4: h_pr = h - 240; break;
	        case 5: h_pr = h - 300; break;

	    }

	    fr = ( h_pr * 255 ) / 60;
	    p  = v * ( 255 - s ) / 255;
	    q  = v * ( 255 - ( ( s * fr ) / 255 ) ) / 255;
	    t  = v * ( 255 - ( s * ( 255 - fr ) / 255 ) ) / 255;

	    switch(hi) {
	        case 0: *r = v; *g = t; *b = p; break;
	        case 1: *r = q; *g = v; *b = p; break;
	        case 2: *r = p; *g = v; *b = t; break;
	        case 3: *r = p; *g = q; *b = v; break;
	        case 4: *r = t; *g = p; *b = v; break;
	        case 5: *r = v; *g = p; *b = q; break;
	    }

	}
алгоритм
Изображение
пользуйтесь, на здоровье :))
первоисточник http://radiolaba.ru/microcotrollers/tsv ... mment-1790