| 3433 | } |
| 3434 | |
| 3435 | static psl_indexed_image_t psl_makecolormap (struct PSL_CTRL *PSL, unsigned char *buffer, int nx, int ny, int nbits) { |
| 3436 | /* When image consists of less than PSL_MAX_COLORS colors, the image can be |
| 3437 | * indexed to safe a significant amount of space. |
| 3438 | * The image and colormap are returned as a struct psl_indexed_image_t. |
| 3439 | * |
| 3440 | * It is important that the first RGB tuple is mapped to index 0. |
| 3441 | * This is used for color masked images. |
| 3442 | */ |
| 3443 | size_t i, j, npixels; /* Need 64-bit ints to avoid overflow of int */ |
| 3444 | psl_colormap_t colormap; |
| 3445 | psl_indexed_image_t image; |
| 3446 | |
| 3447 | if (abs (nbits) != 24) return (NULL); /* We only index into the RGB colorspace. */ |
| 3448 | |
| 3449 | npixels = ((size_t)abs (nx)) * ((size_t)ny); |
| 3450 | |
| 3451 | colormap = psl_memory (PSL, NULL, 1U, sizeof (*colormap)); |
| 3452 | colormap->ncolors = 0; |
| 3453 | image = psl_memory (PSL, NULL, 1U, sizeof (*image)); |
| 3454 | image->buffer = psl_memory (PSL, NULL, npixels+8, sizeof (*image->buffer)); /* Add 8 to avoid overflow access in psl_bitreduce() */ |
| 3455 | image->colormap = colormap; |
| 3456 | |
| 3457 | if (nx < 0) { |
| 3458 | /* Copy the colour mask value into index 0 */ |
| 3459 | colormap->colors[0][0] = buffer[0]; |
| 3460 | colormap->colors[0][1] = buffer[1]; |
| 3461 | colormap->colors[0][2] = buffer[2]; |
| 3462 | colormap->ncolors++; |
| 3463 | buffer += 3; /* Skip to start of image */ |
| 3464 | } |
| 3465 | |
| 3466 | for (i = 0; i < npixels; i++) { |
| 3467 | for (j = 0; j < colormap->ncolors; j++) |
| 3468 | if (colormap->colors[j][0] == buffer[0] && colormap->colors[j][1] == buffer[1] && colormap->colors[j][2] == buffer[2]) { |
| 3469 | image->buffer[i] = (unsigned char)j; |
| 3470 | break; |
| 3471 | } |
| 3472 | |
| 3473 | if (j == colormap->ncolors) { |
| 3474 | if (colormap->ncolors == PSL_MAX_COLORS) { /* Too many colors to index. */ |
| 3475 | PSL_free (image->buffer); |
| 3476 | PSL_free (image); |
| 3477 | PSL_free (colormap); |
| 3478 | PSL_message (PSL, PSL_MSG_INFORMATION, "Too many colors to make colormap - using 24-bit direct color instead.\n"); |
| 3479 | return (NULL); |
| 3480 | } |
| 3481 | image->buffer[i] = (unsigned char)j; |
| 3482 | colormap->colors[j][0] = buffer[0]; |
| 3483 | colormap->colors[j][1] = buffer[1]; |
| 3484 | colormap->colors[j][2] = buffer[2]; |
| 3485 | colormap->ncolors++; |
| 3486 | } |
| 3487 | buffer += 3; |
| 3488 | } |
| 3489 | |
| 3490 | /* There's no need for a color map when the number of colors is the same as the number of pixels. |
| 3491 | Then you're better off with a compressed 24-bit color image instead. */ |
| 3492 | if (colormap->ncolors >= npixels) { |
no test coverage detected