Problem with type conversion and color

I have an integer j. I convert it to a character k, with value b. Then I want to fill a rectangle with color b by calling fill(k);

It (see below) does not work. Can anyone please tell me why?

char k;
color b = color(237.0, 116.0, 75.0); //45

void setup() {
  size(400, 400);


  noLoop();
}

void draw() {
  background(112);

  noStroke();

  //color
  int j = 98;
  k = char(j);
  //println(k);

  //fill(b);
  fill(k);
  rect(0, 0, 400, 400);
}

fill(k); takes the character ā€˜bā€™ but uses its numerical representation, which is 98. So itā€™s fill(98); which creates a dark grey fill. Technically the sketch is running as expected.

Iā€™m intrigued by what you expected to happen. My assumption is that you imagine that character ā€˜bā€™ to act as a reference to your color variable b and that the rect would have an orangey fill?

Iā€™m double-assuming that you eventually want to load in a String and then have each individual character generate a specific color? Thatā€™s definitely possible, but would require a different approach.

ā€“ ā€“ ā€“

No matter if I Iā€™m right or totally off about the goal of your sketch, Iā€™ll use this opportunity to plug one of my all-time favourite generative Text-to-Visual projects. Itā€™s the Poetry on the Road series of posters by Boris MĆ¼ller and they are excellent.

Yes, I want the fill to be color(b) so in my dreams fill(k) would have same result as fill(b).
My ultimate aim is to iterate through a number of colors. I can easily iterate through integers so I thought I would change the integer to a letter and then refer to the color.
I can do what I want with an array of colors and then the integer is an index number representing a position in the array. That works fine, but I didnā€™t want to give up on the type-conversion approach (yet). Is there any hope?

Will investigate Boris MĆ¼ller, thank you.

As @GoToLoop kindly pointed out my original post here was incorrect. I have edited this post since I donā€™t want readers to be misinformed. This post now correctly represents the situation as it applies to the Java language.

======================================================================

in this statement the first part color b declares a variable called b of data type color but Processing will convert this to int b.

In Processing colors are represent by 4 bytes representing the 4 channels ARGB (alpha, red, green, blue) and are collectively stored as an integer.

A char is represented by 2 bytes that are used to store Unicode characters. Characters with Unicode values in the range 0 to 255 represent the Extended ASCII set of which the values 0 to 127 represent the standard ASCII set.

Try the following code it should give an insight into what is happening -

color a = color(237.0, 116.0, 75.0);
char ch = (char)a;       // cast int value to char
int s = (int)ch;     // cast char value to short
byte b = (byte)ch;       // cast char value to byte

//                                                      OUTPUT
println("Color value of a = " + a);                  // -1215413
println("Printable value of  ch = '" + ch + "'");    // ē‘‹
println("Numeric value of ch = " + s);               // 29771
println("Byte value of ch  c = " + b);               // 75

In the statement char c = char(b); we are casting an integer to a short. Using a bit representation we are doing -

AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB   // 32 bit int representing a color ARGB
                 GGGGGGGGBBBBBBB   // after casting to a short
                         BBBBBBB   // after casting to a byte

This shows that a short or char cannot hold a full ARGB color value.

1 Like

OK. Very clear, thank you!
Is the following the best (only?) way to iterate through colors?

color[] colors = {
  color(236.0, 112.0, 83.0),
  color(237.0, 116.0, 75.0),
  color(236.0, 121.0, 67.0),
  color(236.0, 127.0, 60.0),
  color(230.0, 102.0, 105.0)
};


void setup() {
  size(400, 400);

  noLoop();
}

void draw() {
  for (int i = 0; i < colors.length; i++) {

    fill(colors[i]);

    rect(0, 0, 400, 400);

    saveFrame("data/"+i+".tif");
  }
}

maybe lerpColor is interesting

see reference lerpColor() / Reference / Processing.org


Example

// Demo for lerpColor

size(1100, 180);

color from = color(204, 102, 0);
color to = color(0, 102, 153);

for (int i=0; i <= 255; i=i+1) {
  // println(i);
  float amt = map( i, 0, 255, 0, 1 );
  color c = lerpColor (from, to, amt);
  fill(c);
  noStroke();
  rect(i*4, 0, 4, 12);
}// End for-loop

println("");
println("End.");

3 Likes

Some resources here:

I have a lot of fun with gradients!

:)

They are great resources, thank you. The closest to my project is your HSB Gradient Exploration.

The thing is, I am starting from Hues, then manipulating other values so, for example, the Luminosity and Chromaticity. Then after many lines of code, I want to save sample swatches. I wanted to go from beginning to end without saving the colours in an array.

So

iterate > modify some dimensions (not linear) > save swatches

rather than

iterate > modify some dimensions (not linear) > append to an array > save swatches

Iā€™ll look through the examples you have shared to see if there is an alternative to the array approach. And thank you again.

1 Like

That is so in languages such as C and C++, but not in Java!

Javaā€™s primitive datatype char is the same as short in its storage of 16 bits (2 bytes); but itā€™s the only unsigned type among the 8 primitive types, ranging from 0 to 65535:

The char type is mostly used to represent a 16-bit UNICODE (UTF16) character in Java.

Primitive datatype char has other special behaviors such as when we print its value, logging the corresponding ASCII/UNICODE character instead of its actual numerical value.

Also when itā€™s used on a concatenation expression, behaving as a string rather than a number.

2 Likes

@GoToLoop thanks for the correction.

In all my years of Java programming I have very, very rarely had the need to use the Java char and short data types. Thinking about it I rarely used them in C++ either. :relieved:

EDIT: I have corrected my previous post :+1:

2 Likes

Thereā€™s still a small oversight over the actual range of char, which isnā€™t the same as short!
char is the only unsigned primitive type in Java; so its range is 0 to 65535 instead:

1 Like

Adding some references to topic:
Primitive Data Types (The Javaā„¢ Tutorials > Learning the Java Language > Language Basics) < The true source!

Unsigned short in Java | Programming.Guide < Interesting!

I find that some sites do not list the char description the same as the Oracle website.

:)

1 Like

@GoToLoop thanks again for the new correction I have removed all references to the short data type as it didnā€™t add anything to this topic.

Messing about with my code above reminded me why I never bothered to use the short data type as doing any form of mathematics seems to be a nightmare. As for char itā€™s only use I have found for it is to check keyboard events and that extremely rarely. :grinning:

2 Likes

Storing in arrays or other containers smaller datatypes such as boolean, byte, short, char and float can lead to significant performance gain due to the way our modern CPUs transfer contiguous memory blocks to their cache ā€œpipelinesā€.

BtW, Iā€™ve asked Bing AI about it for more details:

Certainly! Letā€™s delve into how using different primitive types in arrays can impact CPU pipelines and performance:

CPU Pipelines and Data Sizes

  1. Instruction Pipelining: Modern CPUs use instruction pipelines to execute multiple instructions concurrently. Efficient use of the pipeline can be influenced by the size of the data being processed. Smaller data types like short, char, and float can help improve this efficiency.

  2. Memory Bandwidth: Smaller data types use less memory bandwidth, meaning that more data can be loaded into the cache or registers at once. This reduces the number of memory accesses required, leading to faster processing.

  3. Cache Utilization: Smaller data types can better utilize the CPU cache. For example, using short (2 bytes) instead of int (4 bytes) means that twice as many elements can fit into the same cache line. This reduces cache misses and increases the likelihood that the required data is already available in the cache.

Short/Char vs. Int Arrays

  1. Memory Savings: short and char are 2 bytes each, whereas int is 4 bytes. When using short or char arrays, you effectively halve the memory footprint compared to int arrays.
  2. Alignment and Padding: Smaller data types can lead to better memory alignment, reducing padding and improving memory access patterns. This can result in more efficient use of the CPU pipeline.

Float Arrays vs. Double Arrays

  1. Memory Usage: float is 4 bytes, while double is 8 bytes. Using float arrays instead of double arrays can result in significant memory savings.
  2. Precision Considerations: While float provides less precision than double, it is sufficient for many applications. The reduced precision can lead to faster computations due to the lower memory overhead.

Trade-offs

  • Precision: Using smaller data types like float instead of double may lead to loss of precision, which can be critical in certain applications such as scientific computations.
  • Overflow/Underflow: Smaller data types have lower range limits, increasing the risk of overflow or underflow in calculations.
  • Platform-Specific Optimizations: Some CPUs might have specific optimizations for certain data types. For example, some processors have more efficient floating-point units for double precision than for float.

In summary, using smaller primitive data types can lead to better CPU pipeline efficiency, improved cache utilization, and overall performance gains, especially in memory-constrained applications. However, itā€™s important to balance these benefits with potential trade-offs in precision and range.

3 Likes