Postprocessing – Do I lose information every time I add an adjustment layer to an 8-bit image in Photoshop?

The result may contain less color, yes. Each color channel in a pixel can only have one of 256 values ​​(2⁸). Each setting transforms these 256 values ​​into some other 256 values. However, there is one limitation: for each pair of two input values, the highest value of the two must remain the highest (otherwise you will get an effect called solarization). Using the curves means that your curve cannot go down from left to right.

Now consider a value somewhere in the middle, for example 128. Your adjustment shifts it to 140. The 128 values ​​under 128 are mapped to 128 new positions between 0 and 140 (this of course means that some values ​​under 140 are not available) 128 remaining values ​​(128 and higher) are now mapped to 116 values, so you started with 256 values ​​and now 128 + 116 = 244 values.

This can lead to a so-called hair comb histogram:

Enter image description here

The histogram above is a linear black-and-white gradient where I used curves 128 to move 140 to 140. The gaps on the left are the 12 values ​​that remain empty (128 after 140), while the teeth on the right are result values, which corresponds to two input values ​​(12 of them, 128 in 116).

Each such setting consumes some color. This is not visible at the beginning because you have three color channels and the missing values ​​do not apply to the three channels at the same time (sometimes you can even get more colors …), but in flat areas with uniform colors you will get visible bands.

c – 8-bit microcontroller Modbus implementation code

Hi Guys!

I have a small project. I use ESP32 with a component, eth, RTC module, etc. And I have omitted the pins. I would like to use an I / O expander, but this project is in my house and I want the expander to be able to work 15 to 20 meters away from the ESP. I2C is not good because with some pull-up resistors and capacitors I can make 2-2.5 meters. SPI is also not good because I need multiple I / O expander and everything needs a CS pin. So I started to implement a MODBUS RTU protocol on an 8-bit microcontroller called EFM8UB2. The thing is, I have not bought the chip yet and started to study it, and so on.

If there's someone willing to take a look at my Modbus RTU implementation and tell me if it's okay or if I should do it differently, I'd be very happy.

My understanding of Modbus:

Data comes from the master in bytes. I take all data coming from the master byte by byte. If there are no timeouts between bytes. If so, I assume that the message has ended. Then I look at the whole message, get the address, if the address is for that chip, then I look at the CRC bits. If it's okay, I look at the function code in it and based on that I do the things the data bits tell me. Then I create a response message based on the function code and the data and send it back to the master. (The chip address lies between the port bits p0.0 and p0.3.)

Since the chip is not yet in my hands, I hope an experienced programmer can see if it will work or not.

Thank you for your comprehension.

The full name of this chip is EFM8UB20F64G-B-QFP48R.

Here is the datasheet
And my code so far:



/* Supported function codes */
#define _READ_SINGLE_REGISTER   0x04
#define _SET_SINGLE_REGISTER    0x06

#define SYSCLK             12000000/8       // SYSCLK in Hz (12 MHz internal oscillator / 8) the internal oscillator has a tolerance of +/- 2%
#define TIMER_PRESCALER            48       // Based on Timer CKCON0 settings
#define TOGGLE_RATE                2        // toggle rate in milliseconds if TOGGLE_RATE = 1, It will trigger an interrupt in 1millisec.
// There are SYSCLK/TIMER_PRESCALER timer ticks per second, so
// SYSCLK/TIMER_PRESCALER/1000 timer ticks per millisecond.

// Note: TOGGLE_RATE*TIMER_TICKS_PER_MS should not exceed 65535 (0xFFFF)for the 16-bit timer
#define AUX2     -AUX1
#define AUX3     AUX2&0x00FF
#define AUX4     ((AUX2&0xFF00)>>8)

#define TIMER0_RELOAD_HIGH       AUX4       // Reload value for Timer0 high byte
#define TIMER0_RELOAD_LOW        AUX3       // Reload value for Timer0 low byte

uint8_t UART_Input_First;
uint8_t UART_Output_First;
uint8_t Register_Response;

char Chip_Address;

extern uint8_t UART_Buffer_Size;
extern uint8_t TX_Ready;
extern char Byte;

bool CrC_is_Error   = false;
bool IO_Toggled     = false;
bool IO_Status      = false;

void ReLoad_Timeout_Time(){
    TH0 = TIMER0_RELOAD_HIGH;               // Reinit Timer0 High register
    TL0 = TIMER0_RELOAD_LOW;                // Reinit Timer0 Low register

static void DO_Request_Message(uint8_t Address,uint8_t Code,uint8_t Data1,uint8_t Data2,uint8_t Crc1,uint8_t Crc2){
    // I have to do a requet message based on the things i do?
    int i = 0;
        CrC_is_Error = false;
        // CrC Error response message
    }else if(IO_Toggled){
        IO_Toggled = false;
        // GPIO Toggled message
        for(i = 0;i> 1) ^ 0xA001;
                crc = crc >> 1;
    return (crc << 8 | crc >> 8);

static int check_integrity(uint8_t *msg, uint8_t msg_length)
    uint16_t crc_calculated;
    uint16_t crc_received;
    if (msg_length < 2)
        return -1;
    crc_calculated = Crc_Check(msg, msg_length - 2);
    crc_received = (msg(msg_length - 2) << 8) | msg(msg_length - 1);
    /* Check CRC of msg */
    if (crc_calculated == crc_received) {
        return msg_length;
    } else {
        return -1;

static void Check_Message(){
    uint8_t Address,Code;
    uint8_t Data(2);
    uint8_t Crc(2);
    int k = 0;
    int i = 0;
    // Get the whole message in separate variables for further analization
    for(i = 0; i < UART_Input_First;i++){
        if (i < 1){
            Address = UART_Buffer(i);
        else if (i < 2){
            Code = UART_Buffer(i);
        else if (i <= 3){
            if(i < 3){
                Data(0) = UART_Buffer(i);
                Data(1) = UART_Buffer(i);
        }else if (i >= 4){
            Crc(k) = UART_Buffer(i);
    // Checking the separated variables
    if(Check_Chip_Address(Address) != -1){                  // Check if Message is ours.
        if(check_integrity(Crc,UART_Buffer_Size) != -1){    // Check if no errors on crc
            CrC_is_Error = false;
            if(Code == _READ_SINGLE_REGISTER){
                /** MASTER WANTS TO READ THE GPIOS **/
            }else if(Code == _SET_SINGLE_REGISTER){
                /** MASTER WANTS TO TOGGLE THE GPIOS **/
            CrC_is_Error = true;

SI_INTERRUPT(TIMER0_ISR, TIMER0_IRQn)       // Timer interrupt fired, data transfer end.
    Check_Message();                        // Get the whole message and brake it into pieces

// UART0 ISR Content goes here. Remember to clear flag bits:
// SCON0::RI (Receive Interrupt Flag)
// SCON0::TI (Transmit Interrupt Flag)
   if (SCON0_RI == 1)
      if( UART_Buffer_Size == 0){               // If new word is entered
         UART_Input_First = 0;
      SCON0_RI = 0;                             // Clear interrupt flag
      Byte = SBUF0;                             // Read a character from UART
      if (UART_Buffer_Size < UART_BUFFERSIZE)
         UART_Buffer(UART_Input_First) = Byte;  // Store in array
         UART_Buffer_Size++;                    // Update array's size
         UART_Input_First++;                    // Update counter

//                          ECHO BACK THE MESSAGE

   if (SCON0_TI == 1)                           // Check if transmit flag is set
      SCON0_TI = 0;                             // Clear interrupt flag
      if (UART_Buffer_Size != 1)                // If buffer not empty
         // If a new word is being output
         if ( UART_Buffer_Size == UART_Input_First ) {
              UART_Output_First = 0;  }
         // Store a character in the variable byte
         Byte = UART_Buffer(UART_Output_First);
         SBUF0 = Byte;                          // Transmit to Hyperterminal
         UART_Output_First++;                   // Update counter
         UART_Buffer_Size--;                    // Decrease array size
         UART_Buffer_Size = 0;                  // Set the array size to 0
         TX_Ready = 1;                          // Indicate transmission complete

unity – How can I extract texture data after a 16 * 8-bit pattern?

Is it possible to unpack texture data according to a specific bit-packing scheme?

I have read that texture data in HLSL can be read as 4 floating-point numbers of 32 bits each with a total of 128 bits. The packing scheme I want to use is 16 pack groups of 8 bits each. I'm having trouble figuring out how to unpack this data without loss because they are interpreted as a float.

iproute2 – tc filter … ht HANDLE … does not allow 8-bit buckets

TC-U32 man page states that HANDLE is:

HANDLE := { u12_hex_htid:(**u8_hex_hash:(u12_hex_nodeid)** | 0xu32_hex_value }

The size of the bucket should therefore be between 0x00 and 0xff because it is a u8 value.

The problem is that I can not create a bucket larger than 0x19 (five bits).
I have: RTNETLINK answers: Invalid argument
An error occurred while talking to the kernel

/sbin/tc filter add dev ifb0 parent 1:0 protocol ip prio 5 u32 ht 5:2: match ip src hashkey mask 0x000000ff at 12 link 100:

is OK

/sbin/tc filter add dev ifb0 parent 1:0 protocol ip prio 5 u32 ht 5:20: match ip src hashkey mask 0x000000ff at 12 link 100:

cries for error.


iproute2 version 4.3.0-1ubuntu3.16

Ubuntu 16.04.5 LTS

Any hints?


Software Recommendation – Is there a simple image processor that can reduce the color depth of the image (convert 24-bit RGB to indexed 2, 4, or 8-bit colors)?

On Ubuntu 18.04, I need a fast / simple image processing application that lets me view, crop, resize, and reduce the color depth / color mode (number of color bits per pixel) with and without dithering (24-bit). Bit JPG input images and export them as PNG. I want the option to reduce to 4, 16 or 256 colors (2, 4 or 8 bits per pixel).

GIMP has these options, but I'm looking for something less bulky.

In Windows (and OS / 2 before!) I was a longtime user of PMView, a fast viewer and processor. I can still use PMView on WINE (there's also an IrfanView app that works pretty much like WINE), but I'd prefer a Linux app.

I have tried a number of applications. I like the simplicity, cropping, resizing and even color manipulation of gThumb. However, with gThumb I can not save PNG files with less than 24 bits. Same problem with Shotwell and Mirage. I was not lucky enough to get usable results with Pinta.

How to convert the representation of 8-bit colors into corresponding Python curse colors?

I'm trying to display a low-resolution image in my Python-cursed Terminal App. I got rgb color from every pixel of the picture numpy, I changed each pixel with the following 8-bit color: Color = int ((r * 6/256) * 36 + (g * 6/256) * 6 + (b * 6/256) - 1) and use colour like New init_pair'Everything worked well except colors, they were not even similar. So my question is, is there any way to turn the representation of the 8-bit color into one of the 256 Python curse colors?

There is a part of my code:

def show_image (h, w, img_arr, window):
for y in the range (h):
for x in the range (w):
pix = img_arr[y][x]
            color = int ((pix[0]* 6/256) * 36 + (pix[1]* 6/256) * 6 + (pix[2]* 6/256) - 1)
curses.init_pair (color, color, color)
window.addch (10 + y, x + 1, "#", curses.color_pair (color))

Scanning – How to use Image Capture to scan more than 8-bit color?

Some of your previous answers have not been well received and you run the risk of being blocked from answering.

Please note the following notes exactly:

  • Please be sure answer the question, Enter details and share your research!

But avoid

  • Ask for help, clarification or answering other answers.
  • Make statements based on opinions; secure them with references or personal experiences.

For more information, see our tips for writing great answers.