www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Convert a hex color string into r,g,b components.

reply "Marcin Szymczak" <m_szymczak o2.pl> writes:
When programming i have encountered a simple ( i think ) problem, 
yet i can't get my head around it. I am trying to convert a 
string ( like "#FF00FF" for magenta ) into a color. I figured out 
that i need to skip the first character '#' and then using 
"chunks" range convert each pair of 2 chars into a number and 
assign it to specific component. The snippet looks like this

	Color color;
	auto chunk = chunks( str[1..$], 2 );
	color.r = to!ubyte( chunk.front, 16 ); chunk.popFront;
	color.g = to!ubyte( chunk.front, 16 ); chunk.popFront;
	color.b = to!ubyte( chunk.front, 16 ); chunk.popFront;

But the compilation fails, stating

/usr/include/dlang/dmd/std/conv.d(295): Error: template 
std.conv.toImpl cannot deduce function from argument types 
!(ubyte)(Take!string, int), candidates are:
/usr/include/dlang/dmd/std/conv.d(361):        std.conv.toImpl(T, 
S)(S value) if (isImplicitlyConvertible!(S, T) && 
!isEnumStrToStr!(S, T) && !isNullToStr!(S, T))
/usr/include/dlang/dmd/std/conv.d(475):        std.conv.toImpl(T, 
S)(ref S s) if (isRawStaticArray!S)
/usr/include/dlang/dmd/std/conv.d(491):        std.conv.toImpl(T, 
S)(S value) if (!isImplicitlyConvertible!(S, T) && 
is(typeof(S.init.opCast!T()) : T) && !isExactSomeString!T && 
!is(typeof(T(value))))
/usr/include/dlang/dmd/std/conv.d(542):        std.conv.toImpl(T, 
S)(S value) if (!isImplicitlyConvertible!(S, T) && is(T == 
struct) && is(typeof(T(value))))
/usr/include/dlang/dmd/std/conv.d(591):        std.conv.toImpl(T, 
S)(S value) if (!isImplicitlyConvertible!(S, T) && is(T == class) 
&& is(typeof(new T(value))))
/usr/include/dlang/dmd/std/conv.d(295):        ... (9 more, -v to 
show) ...
source/engine/graphics/core.d(43): Error: template instance 
std.conv.to!ubyte.to!(Take!string, int) error instantiating

I would really love to solve this problem using ranges, because i 
am learning how to use them. Unfortunately even such a simple 
task seems so hard for me ;(
Aug 11 2015
next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Tuesday, 11 August 2015 at 22:11:51 UTC, Marcin Szymczak wrote:
 /usr/include/dlang/dmd/std/conv.d(295): Error: template 
 std.conv.toImpl cannot deduce function from argument types 
 !(ubyte)(Take!string, int), candidates are:
I don't think to! with the base given works on the chunked ranges, it just works on regular strings.
 I would really love to solve this problem using ranges, because 
 i am learning how to use them. Unfortunately even such a simple 
 task seems so hard for me ;(
meh, I'd just slice the string.
Aug 11 2015
prev sibling parent "wobbles" <grogan.colin gmail.com> writes:
On Tuesday, 11 August 2015 at 22:11:51 UTC, Marcin Szymczak wrote:

 I would really love to solve this problem using ranges, because 
 i am learning how to use them. Unfortunately even such a simple 
 task seems so hard for me ;(
I think writing a simple function to parse a string into a Color would be best here. Color parseRGBString(string theString){ if(theString.length != 7) throw new Exception("Error. Cannot parse to color: " ~ theString); return Color( to!ubyte(theString[1..3], 16), to!ubyte(theString[3..5], 16), to!ubyte(theString[5..7], 16) ); } I could probably do more to ensure that the string actually does represent a color (e.g. Check if no char is > F etc). Also, using ranges isn't always required, theres no such thing as a "too simple" solution, as long as it works! You can use this in a range then, e.g. say the user passes in lots of strings to your program, you can listOfColors.map!(a => a.parseRGBString); // and now you have a lazily evaluated list of Color objects.
Aug 12 2015