# HG changeset patch # User Matti Hamalainen # Date 1551772607 -7200 # Node ID 4276b8c0fef05a6a7fde660ef314e62020639f9b # Parent d17512dbb4ef83e57e4681749064b1974ac878d0 Revamp how the DMImage palette system and color formats work, as preparation for future work on supporting non-indexed/paletted images. It is still messy. diff -r d17512dbb4ef -r 4276b8c0fef0 tools/64vw.c --- a/tools/64vw.c Thu Feb 28 12:32:07 2019 +0200 +++ b/tools/64vw.c Tue Mar 05 09:56:47 2019 +0200 @@ -220,16 +220,18 @@ bmap.pitch = surf->pitch; bmap.width = surf->w; bmap.height = surf->h; - bmap.ncolors = C64_NCOLORS; - bmap.constpal = TRUE; - bmap.pal = dmDefaultC64Palette; + + if ((ret = dmSetDefaultC64Palette(&bmap)) != DMERR_OK) + return ret; if (fmt->format->convertFrom != NULL) ret = fmt->format->convertFrom(&bmap, cimage, fmt, spec); else ret = dmC64ConvertGenericBMP2Image(&bmap, cimage, fmt, spec); - SDL_SetPaletteColors(surf->format->palette, (SDL_Color *) bmap.pal, 0, bmap.ncolors); + SDL_SetPaletteColors(surf->format->palette, (SDL_Color *) bmap.pal->colors, 0, bmap.pal->ncolors); + + dmPaletteFree(bmap.pal); return ret; } diff -r d17512dbb4ef -r 4276b8c0fef0 tools/gfxconv.c --- a/tools/gfxconv.c Thu Feb 28 12:32:07 2019 +0200 +++ b/tools/gfxconv.c Tue Mar 05 09:56:47 2019 +0200 @@ -1046,28 +1046,38 @@ int dmRemapImageColors(DMImage **pdst, const DMImage *src) { - DMColor *npal = dmCalloc(src->ncolors, sizeof(DMColor)); - int *mapping = dmMalloc(src->ncolors * sizeof(int)); - BOOL *mapped = dmMalloc(src->ncolors * sizeof(BOOL)); - BOOL *used = dmMalloc(src->ncolors * sizeof(BOOL)); - int n, index, xc, yc, ncolors; + DMPalette *npal = NULL; + int *mapping = dmMalloc(src->pal->ncolors * sizeof(int)); + BOOL *mapped = dmMalloc(src->pal->ncolors * sizeof(BOOL)); + BOOL *used = dmMalloc(src->pal->ncolors * sizeof(BOOL)); + int n, index, xc, yc, ncolors, res = DMERR_OK; DMImage *dst; + if ((res = dmPaletteAlloc(&npal, src->pal->ncolors, -1)) != DMERR_OK) + { + dmErrorMsg("Could not allocate memory for remap palette.\n"); + goto error; + } + if ((dst = *pdst = dmImageAlloc(src->width, src->height, src->format, src->bpp)) == NULL) { - return dmError(DMERR_MALLOC, + res = dmError(DMERR_MALLOC, "Could not allocate memory for remapped image.\n"); + goto error; } - dmMsg(1, "Remapping %d output image colors of %d colors.\n", optNRemapTable, src->ncolors); - if (npal == NULL || mapping == NULL || mapped == NULL || used == NULL) + if (mapping == NULL || mapped == NULL || used == NULL) { - return dmError(DMERR_MALLOC, + res = dmError(DMERR_MALLOC, "Could not allocate memory for reused palette.\n"); + goto error; } - for (index = 0; index < src->ncolors; index++) + dmMsg(1, "Remapping %d output image colors of %d colors.\n", + optNRemapTable, src->pal->ncolors); + + for (index = 0; index < src->pal->ncolors; index++) { mapping[index] = -1; mapped[index] = used[index] = FALSE; @@ -1081,7 +1091,7 @@ for (xc = 0; xc < src->width; xc++) { Uint8 col = dp[xc]; - if (col < src->ncolors && !used[col]) + if (col < src->pal->ncolors && !used[col]) { used[col] = TRUE; ncolors++; @@ -1097,9 +1107,9 @@ if (map->triplet) { BOOL found = FALSE; - for (n = 0; n < src->ncolors; n++) + for (n = 0; n < src->pal->ncolors; n++) { - if (dmCompareColor(&(src->pal[n]), &(map->color), map->alpha)) + if (dmCompareColor(&(src->pal->colors[n]), &(map->color), map->alpha)) { dmMsg(3, "RGBA match #%02x%02x%02x%02x: %d -> %d\n", map->color.r, map->color.g, map->color.b, map->color.a, @@ -1133,11 +1143,11 @@ if (optRemapRemove) dmMsg(2, "Removing unused colors.\n"); - for (index = 0; index < src->ncolors; index++) + for (index = 0; index < src->pal->ncolors; index++) if (mapping[index] < 0 && (!optRemapRemove || (optRemapRemove && used[index]))) { - for (n = 0; n < src->ncolors; n++) + for (n = 0; n < src->pal->ncolors; n++) if (!mapped[n]) { mapping[index] = n; @@ -1148,14 +1158,14 @@ // Calculate final number of palette colors ncolors = 0; - for (index = 0; index < src->ncolors; index++) + for (index = 0; index < src->pal->ncolors; index++) { if (mapping[index] + 1 > ncolors) ncolors = mapping[index] + 1; } // Copy palette entries - for (index = 0; index < src->ncolors; index++) + for (index = 0; index < src->pal->ncolors; index++) { if (mapping[index] >= 0) { @@ -1172,7 +1182,9 @@ for (xc = 0; xc < src->width; xc++) { Uint8 col = sp[xc]; - if (col < src->ncolors && mapping[col] >= 0 && mapping[col] < src->ncolors) + if (col < src->pal->ncolors && + mapping[col] >= 0 && + mapping[col] < src->pal->ncolors) dp[xc] = mapping[col]; else dp[xc] = 0; @@ -1180,13 +1192,18 @@ } // Set new palette, free memory - dst->pal = npal; - dst->ncolors = ncolors; + if ((res = dmPaletteCopy(&dst->pal, npal)) != DMERR_OK) + { + res = dmError(DMERR_MALLOC, + "Could not allocate memory for final remapped palette.\n"); + goto error; + } +error: dmFree(mapping); dmFree(mapped); dmFree(used); - return DMERR_OK; + return res; } @@ -1397,7 +1414,7 @@ // Perform color remapping DMImage *image = pimage; BOOL allocated = FALSE; - if (optRemapColors) + if (optRemapColors && pimage->format == DM_COLFMT_PALETTE) { if ((res = dmRemapImageColors(&image, pimage)) != DMERR_OK) return res; @@ -1411,7 +1428,7 @@ spec->nplanes = 0; for (int n = 8; n >= 0;) { - if ((image->ncolors - 1) & (1 << n)) + if ((image->pal->ncolors - 1) & (1 << n)) { spec->nplanes = n + 1; break; @@ -1787,7 +1804,11 @@ outImage = dmImageAlloc(outWidthPX * outIWidth, outIHeight * outHeight, DM_COLFMT_PALETTE, -1); } - dmSetDefaultC64Palette(outImage); + if ((err = dmSetDefaultC64Palette(outImage)) != DMERR_OK) + { + dmErrorMsg("Could not allocate C64 palette for output image: %d\n", err); + goto error; + } while (offs + outSize < dataSize && (optItemCount < 0 || itemCount < optItemCount)) { @@ -1795,7 +1816,7 @@ dataBuf + offs, outWidth, outHeight, optInMulticolor, optColorMap)) != DMERR_OK) { dmErrorMsg("Internal error in conversion of raw data to bitmap: %d.\n", err); - break; + goto error; } if (optSequential) diff -r d17512dbb4ef -r 4276b8c0fef0 tools/lib64gfx.c --- a/tools/lib64gfx.c Thu Feb 28 12:32:07 2019 +0200 +++ b/tools/lib64gfx.c Tue Mar 05 09:56:47 2019 +0200 @@ -108,19 +108,23 @@ } -void dmSetDefaultC64Palette(DMImage *img) +int dmSetDefaultC64Palette(DMImage *img) { - img->constpal = TRUE; - img->pal = dmDefaultC64Palette; - img->ncolors = C64_NCOLORS; - img->ctransp = 255; + int res; + if ((res = dmPaletteAlloc(&(img->pal), C64_NCOLORS, 255)) != DMERR_OK) + return res; + + memcpy(img->pal->colors, dmDefaultC64Palette, img->pal->ncolors * sizeof(DMColor)); + + return DMERR_OK; } -BOOL dmSetMixedColorC64Palette(DMImage *img) +int dmSetMixedColorC64Palette(DMImage *img) { - if (!dmImagePaletteAlloc(img, C64_NCOLORS * C64_NCOLORS, -1)) - return FALSE; + int res; + if ((res = dmPaletteAlloc(&(img->pal), C64_NCOLORS * C64_NCOLORS, -1)) != DMERR_OK) + return res; int n = 0; for (int n1 = 0; n1 < C64_NCOLORS; n1++) @@ -129,14 +133,14 @@ for (int n2 = 0; n2 < C64_NCOLORS; n2++) { const DMColor *col2 = &dmDefaultC64Palette[n2]; - img->pal[n].r = (col1->r + col2->r) / 2; - img->pal[n].g = (col1->g + col2->g) / 2; - img->pal[n].b = (col1->b + col2->b) / 2; + img->pal->colors[n].r = (col1->r + col2->r) / 2; + img->pal->colors[n].g = (col1->g + col2->g) / 2; + img->pal->colors[n].b = (col1->b + col2->b) / 2; n++; } } - return TRUE; + return DMERR_OK; } @@ -1401,9 +1405,8 @@ return DMERR_MALLOC; // Set partial palette information - dst->ncolors = C64_NCOLORS; - dst->constpal = TRUE; - dst->pal = dmDefaultC64Palette; + if ((res = dmSetDefaultC64Palette(dst)) != DMERR_OK) + return res; // Convert if (fmt->format->convertFrom != NULL) diff -r d17512dbb4ef -r 4276b8c0fef0 tools/lib64gfx.h --- a/tools/lib64gfx.h Thu Feb 28 12:32:07 2019 +0200 +++ b/tools/lib64gfx.h Tue Mar 05 09:56:47 2019 +0200 @@ -306,8 +306,8 @@ char * dmC64GetImageTypeString(char *buf, const size_t len, const int type, const BOOL lng); void dmC64ImageDump(FILE *fh, const DMC64Image *img, const DMC64ImageFormat *fmt, const char *indent); -void dmSetDefaultC64Palette(DMImage *img); -BOOL dmSetMixedColorC64Palette(DMImage *img); +int dmSetDefaultC64Palette(DMImage *img); +int dmSetMixedColorC64Palette(DMImage *img); BOOL dmCompareAddr16(const DMGrowBuf *buf, const size_t offs, const Uint16 addr); int dmC64ImageGetNumBanks(const DMC64ImageFormat *fmt); diff -r d17512dbb4ef -r 4276b8c0fef0 tools/libgfx.c --- a/tools/libgfx.c Thu Feb 28 12:32:07 2019 +0200 +++ b/tools/libgfx.c Tue Mar 05 09:56:47 2019 +0200 @@ -91,7 +91,7 @@ } -BOOL dmCompareColor(const DMColor *c1, const DMColor *c2, BOOL alpha) +BOOL dmCompareColor(const DMColor *c1, const DMColor *c2, const BOOL alpha) { if (c1->r == c2->r && c1->g == c2->g && @@ -133,7 +133,6 @@ img->bpp = (bpp <= 0) ? dmImageGetBitsPerPixel(format) : bpp; img->pitch = (width * img->bpp) / 8; img->size = img->pitch * img->height; - img->ctransp = -1; img->aspect = -1; if ((img->data = dmMalloc(img->size)) == NULL) @@ -151,63 +150,164 @@ if (img != NULL) { if (!img->constpal) - { - dmFree(img->pal); - } + dmPaletteFree(img->pal); + dmFree(img->data); dmFree(img); } } -BOOL dmPaletteAlloc(DMColor **ppal, int ncolors, int ctransp) +int dmPaletteAlloc(DMPalette **ppal, const int ncolors, const int ctransp) { + DMPalette *pal; if (ppal == NULL) - return FALSE; + return DMERR_NULLPTR; + + *ppal = NULL; + + // Allocate palette struct + if ((pal = dmMalloc0(sizeof(DMPalette))) == NULL) + return DMERR_MALLOC; + + pal->ncolors = ncolors; + pal->ctransp = ctransp; // Allocate desired amount of palette - if ((*ppal = dmCalloc(ncolors, sizeof(DMColor))) == NULL) - return FALSE; + if ((pal->colors = dmCalloc(pal->ncolors, sizeof(DMColor))) == NULL) + { + dmFree(pal); + return DMERR_MALLOC; + } // Set alpha values to max, except for transparent color - for (int i = 0; i < ncolors; i++) + for (int i = 0; i < pal->ncolors; i++) { - (*ppal)[i].a = (i == ctransp) ? 0x00 : 0xff; + pal->colors[i].a = (i == pal->ctransp) ? 0x00 : 0xff; } - return TRUE; + *ppal = pal; + + return DMERR_OK; } -BOOL dmImagePaletteAlloc(DMImage *img, int ncolors, int ctransp) +int dmPaletteResize(DMPalette **ppal, const int ncolors) +{ + DMPalette *pal; + + if (ppal == NULL) + return DMERR_NULLPTR; + + if (ncolors <= 0 || ncolors > 256) + return DMERR_INVALID_ARGS; + + if (*ppal == NULL) + return dmPaletteAlloc(ppal, ncolors, -1); + + pal = *ppal; + + if (pal->ncolors == ncolors) + return DMERR_OK; + + if ((pal->colors = dmRealloc(pal->colors, sizeof(DMColor) * ncolors)) == NULL) + return DMERR_MALLOC; + + if (ncolors - pal->ncolors > 0) + memset(&(pal->colors[pal->ncolors]), 0, sizeof(DMColor) * (ncolors - pal->ncolors)); + + return DMERR_OK; +} + + +int dmPaletteCopy(DMPalette **pdst, const DMPalette *src) { - if (img == NULL) - return FALSE; - - img->ncolors = ncolors; - img->ctransp = ctransp; - img->constpal = FALSE; - - return dmPaletteAlloc(&(img->pal), ncolors, ctransp); + DMPalette *pal; + if (pdst == NULL) + return DMERR_NULLPTR; + + *pdst = NULL; + + // Allocate palette struct + if ((pal = dmMalloc(sizeof(DMPalette))) == NULL) + return DMERR_MALLOC; + + memcpy(pal, src, sizeof(DMPalette)); + + // Allocate desired amount of palette + if ((pal->colors = dmCalloc(pal->ncolors, sizeof(DMColor))) == NULL) + { + dmFree(pal); + return DMERR_MALLOC; + } + + memcpy(pal->colors, src->colors, sizeof(DMColor) * pal->ncolors); + *pdst = pal; + + return DMERR_OK; } -static BOOL dmPaletteReadData(DMResource *fp, DMColor *pal, int ncolors) +void dmPaletteFree(DMPalette *pal) { + if (pal != NULL) + { + dmFree(pal->colors); + dmFree(pal); + } +} + + +static int dmPaletteReadData(DMResource *fp, DMPalette *pal, int ncolors) +{ + if (pal->ncolors < ncolors) + return DMERR_INVALID_ARGS; + for (int i = 0; i < ncolors; i++) { Uint8 colR, colG, colB; if (!dmf_read_byte(fp, &colR) || !dmf_read_byte(fp, &colG) || !dmf_read_byte(fp, &colB)) - return FALSE; - - pal[i].r = colR; - pal[i].g = colG; - pal[i].b = colB; + return DMERR_FREAD; + + pal->colors[i].r = colR; + pal->colors[i].g = colG; + pal->colors[i].b = colB; } - return TRUE; + return DMERR_OK; +} + + +static int dmPaletteWriteData(DMResource *fp, const DMPalette *pal, const int ncolors, const int npad) +{ + int i; + + if (pal == NULL || fp == NULL) + return DMERR_NULLPTR; + + if (pal->ncolors < ncolors) + return DMERR_INVALID_ARGS; + + for (i = 0; i < ncolors; i++) + { + DMColor *col = &pal->colors[i]; + if (!dmf_write_byte(fp, col->r) || + !dmf_write_byte(fp, col->g) || + !dmf_write_byte(fp, col->b)) + return DMERR_FWRITE; + } + + for (; i < npad; i++) + { + if (!dmf_write_byte(fp, 0) || + !dmf_write_byte(fp, 0) || + !dmf_write_byte(fp, 0)) + return DMERR_FWRITE; + } + + return DMERR_OK; } @@ -236,71 +336,143 @@ *ptr3 = ptr2 + rowWidth, *ptr4 = ptr3 + rowWidth; - for (x = 0; x < img->width; x++) + if (img->format == DM_COLFMT_PALETTE || + img->format == DM_COLFMT_GRAYSCALE) { - Uint8 c = img->data[(y * img->pitch) + (x * img->bpp) / 8], - qr, qg, qb, qa; - + for (x = 0; x < img->width; x++) + { + Uint8 c = img->data[(y * img->pitch) + (x * img->bpp) / 8], + qr, qg, qb, qa; + + if (c >= img->pal->ncolors) + { + res = DMERR_INVALID_DATA; + goto done; + } + + switch (spec->format) + { + case DM_COLFMT_PALETTE: + case DM_COLFMT_GRAYSCALE: + for (xscale = 0; xscale < spec->scaleX; xscale++) + *ptr1++ = c; + break; + + case DM_COLFMT_RGBA: + qr = img->pal->colors[c].r; + qg = img->pal->colors[c].g; + qb = img->pal->colors[c].b; + qa = img->pal->colors[c].a; + + if (spec->planar) + { + for (xscale = 0; xscale < spec->scaleX; xscale++) + { + *ptr1++ = qr; + *ptr2++ = qg; + *ptr3++ = qb; + *ptr4++ = qa; + } + } + else + { + for (xscale = 0; xscale < spec->scaleX; xscale++) + { + *ptr1++ = qr; + *ptr1++ = qg; + *ptr1++ = qb; + *ptr1++ = qa; + } + } + break; + + case DM_COLFMT_RGB: + qr = img->pal->colors[c].r; + qg = img->pal->colors[c].g; + qb = img->pal->colors[c].b; + + if (spec->planar) + { + for (xscale = 0; xscale < spec->scaleX; xscale++) + { + *ptr1++ = qr; + *ptr2++ = qg; + *ptr3++ = qb; + } + } + else + { + for (xscale = 0; xscale < spec->scaleX; xscale++) + { + *ptr1++ = qr; + *ptr1++ = qg; + *ptr1++ = qb; + } + } + break; + + default: + res = DMERR_NOT_SUPPORTED; + goto done; + } + } + } + else + if (img->format == DM_COLFMT_RGB || + img->format == DM_COLFMT_RGBA) + { + Uint8 *sp = img->data + (y * img->pitch); + + for (x = 0; x < img->width; x++, sp += img->bpp / 8) switch (spec->format) { - case DM_COLFMT_PALETTE: - case DM_COLFMT_GRAYSCALE: - for (xscale = 0; xscale < spec->scaleX; xscale++) - *ptr1++ = c; - break; - - case DM_COLFMT_RGBA: - qr = img->pal[c].r; - qg = img->pal[c].g; - qb = img->pal[c].b; - qa = img->pal[c].a; - + case DM_COLFMT_RGBA: if (spec->planar) { for (xscale = 0; xscale < spec->scaleX; xscale++) { - *ptr1++ = qr; - *ptr2++ = qg; - *ptr3++ = qb; - *ptr4++ = qa; + *ptr1++ = sp[0]; + *ptr2++ = sp[1]; + *ptr3++ = sp[2]; + *ptr4++ = sp[3]; } } else { for (xscale = 0; xscale < spec->scaleX; xscale++) { - *ptr1++ = qr; - *ptr1++ = qg; - *ptr1++ = qb; - *ptr1++ = qa; + *ptr1++ = sp[0]; + *ptr1++ = sp[1]; + *ptr1++ = sp[2]; + *ptr1++ = sp[3]; } } break; case DM_COLFMT_RGB: - qr = img->pal[c].r; - qg = img->pal[c].g; - qb = img->pal[c].b; - if (spec->planar) { for (xscale = 0; xscale < spec->scaleX; xscale++) { - *ptr1++ = qr; - *ptr2++ = qg; - *ptr3++ = qb; + *ptr1++ = sp[0]; + *ptr2++ = sp[1]; + *ptr3++ = sp[2]; } } else { for (xscale = 0; xscale < spec->scaleX; xscale++) { - *ptr1++ = qr; - *ptr1++ = qg; - *ptr1++ = qb; + *ptr1++ = sp[0]; + *ptr1++ = sp[1]; + *ptr1++ = sp[2]; } } break; + + default: + res = DMERR_NOT_SUPPORTED; + goto done; } } @@ -337,18 +509,18 @@ if (dmfprintf(fp, "%s_ncolors: dw.w %d\n" "%s_palette:\n", - prefix, img->ncolors, + prefix, img->pal->ncolors, prefix) < 0) return dmferror(fp); for (int i = 0; i < (1 << spec->nplanes); i++) { Uint32 color; - if (i < img->ncolors) + if (i < img->pal->ncolors) { - color = (DMCOL(img->pal[i].r) << 8) | - (DMCOL(img->pal[i].g) << 4) | - (DMCOL(img->pal[i].b)); + color = (DMCOL(img->pal->colors[i].r) << 8) | + (DMCOL(img->pal->colors[i].g) << 4) | + (DMCOL(img->pal->colors[i].b)); } else color = 0; @@ -584,7 +756,7 @@ case '5': itype = DM_COLFMT_GRAYSCALE; break; default: res = dmError(DMERR_NOT_SUPPORTED, - "PPM: Unsupported PPM/PGM subtype.\n"); + "PPM: Unsupported PPM/PNM/PGM subtype.\n"); goto error; } @@ -595,6 +767,9 @@ goto error; } + dmMsg(2, "PPM: %d x %d, type=%d\n", + width, height, itype); + if ((*pimg = img = dmImageAlloc(width, height, itype, -1)) == NULL) { res = dmError(DMERR_MALLOC, @@ -602,7 +777,7 @@ goto error; } - if (dmf_read_str(fp, img->data, img->size)) + if (!dmf_read_str(fp, img->data, img->size)) { res = dmError(DMERR_FREAD, "PPM: Could not read image data.\n"); @@ -755,14 +930,14 @@ dmMemset(palette, 0, PNG_MAX_PALETTE_LENGTH * sizeof(png_color)); - for (int i = 0; i < img->ncolors; i++) + for (int i = 0; i < img->pal->ncolors; i++) { - palette[i].red = img->pal[i].r; - palette[i].green = img->pal[i].g; - palette[i].blue = img->pal[i].b; + palette[i].red = img->pal->colors[i].r; + palette[i].green = img->pal->colors[i].g; + palette[i].blue = img->pal->colors[i].b; } - png_set_PLTE(png_ptr, info_ptr, palette, img->ncolors); + png_set_PLTE(png_ptr, info_ptr, palette, img->pal->ncolors); png_free(png_ptr, palette); } @@ -802,8 +977,7 @@ png_bytep *row_pointers = NULL; png_bytep trans = NULL; png_uint_32 width, height, res_x = 0, res_y = 0; - int i, itype, bit_depth, color_type, ncolors, ntrans, unit_type; - int res = DMERR_OK; + int res, itype, bit_depth, color_type, ncolors, ntrans, unit_type; DMImage *img; // Create PNG structures @@ -911,7 +1085,7 @@ if ((row_pointers = png_malloc(png_ptr, height * sizeof(png_bytep))) == NULL) goto error; - for (i = 0; i < img->height; i++) + for (int i = 0; i < img->height; i++) row_pointers[i] = img->data + (i * img->pitch); png_read_image(png_ptr, row_pointers); @@ -927,17 +1101,14 @@ { dmMsg(2, "PNG: Palette of %d colors found.\n", ncolors); - if (!dmImagePaletteAlloc(img, ncolors, -1)) - { - res = DMERR_MALLOC; + if ((res = dmPaletteAlloc(&(img->pal), ncolors, -1)) != DMERR_OK) goto error; - } - - for (i = 0; i < img->ncolors; i++) + + for (int i = 0; i < img->pal->ncolors; i++) { - img->pal[i].r = palette[i].red; - img->pal[i].g = palette[i].green; - img->pal[i].b = palette[i].blue; + img->pal->colors[i].r = palette[i].red; + img->pal->colors[i].g = palette[i].green; + img->pal->colors[i].b = palette[i].blue; } } @@ -945,15 +1116,17 @@ if (trans != NULL && ntrans > 0) { dmMsg(2, "PNG: %d transparent colors.\n", ntrans); - for (i = 0; i < img->ncolors && i < ntrans; i++) + for (int i = 0; i < img->pal->ncolors && i < ntrans; i++) { - img->pal[i].a = trans[i]; - if (img->ctransp < 0 && trans[i] == 0) - img->ctransp = i; + img->pal->colors[i].a = trans[i]; + if (img->pal->ctransp < 0 && trans[i] == 0) + img->pal->ctransp = i; } } } + res = DMERR_OK; + error: if (png_ptr != NULL && info_ptr != NULL) png_destroy_read_struct(&png_ptr, &info_ptr, NULL); @@ -1105,7 +1278,6 @@ return DMERR_FWRITE; } - return DMERR_OK; } @@ -1145,12 +1317,12 @@ if (spec.format == DM_COLFMT_PALETTE || spec.format == DM_COLFMT_GRAYSCALE) { - const int ncolors = img->ncolors > DMPCX_PAL_COLORS ? DMPCX_PAL_COLORS : img->ncolors; + const int ncolors = img->pal->ncolors > DMPCX_PAL_COLORS ? DMPCX_PAL_COLORS : img->pal->ncolors; for (int i = 0; i < ncolors; i++) { - hdr.colorMap[i].r = img->pal[i].r; - hdr.colorMap[i].g = img->pal[i].g; - hdr.colorMap[i].b = img->pal[i].b; + hdr.colorMap[i].r = img->pal->colors[i].r; + hdr.colorMap[i].g = img->pal->colors[i].g; + hdr.colorMap[i].b = img->pal->colors[i].b; } } hdr.manufacturer = 10; @@ -1246,34 +1418,15 @@ if (spec.format == DM_COLFMT_PALETTE || spec.format == DM_COLFMT_GRAYSCALE) { - int i; - dmMsg(2, "PCX: Writing palette of %d active entries.\n", img->ncolors); + dmMsg(2, "PCX: Writing palette of %d active entries.\n", img->pal->ncolors); dmf_write_byte(pcx.fp, 0x0C); - for (i = 0; i < img->ncolors; i++) + if ((res = dmPaletteWriteData(fp, img->pal, img->pal->ncolors, 256)) != DMERR_OK) { - if (!dmf_write_byte(pcx.fp, img->pal[i].r) || - !dmf_write_byte(pcx.fp, img->pal[i].g) || - !dmf_write_byte(pcx.fp, img->pal[i].b)) - { - res = dmError(DMERR_FWRITE, - "PCX: Could not write palette data.\n"); - goto error; - } - } - - // Pad the palette, if necessary - for (; i < 256; i++) - { - if (!dmf_write_byte(pcx.fp, 0) || - !dmf_write_byte(pcx.fp, 0) || - !dmf_write_byte(pcx.fp, 0)) - { - res = dmError(DMERR_FWRITE, - "PCX: Could not write palette data.\n"); - goto error; - } + res = dmError(DMERR_FWRITE, + "PCX: Could not write palette data.\n"); + goto error; } } @@ -1472,9 +1625,7 @@ // Decode bitplanes switch (hdr.bitsPerPlane) { - case 32: case 24: - case 16: case 8: { // Actually bytes and bits per plane per pixel .. @@ -1533,9 +1684,9 @@ ncolors = 256; } - if (!dmImagePaletteAlloc(img, ncolors, -1)) + if ((res = dmPaletteAlloc(&(img->pal), ncolors, -1)) != DMERR_OK) { - res = dmError(DMERR_MALLOC, + res = dmError(res, "PCX: Could not allocate palette data!\n"); goto error; } @@ -1544,23 +1695,25 @@ { // Okay, attempt to read the palette data dmMsg(2, "PCX: Reading palette of %d colors\n", ncolors); - if (!dmPaletteReadData(fp, img->pal, ncolors)) + if ((res = dmPaletteReadData(fp, img->pal, ncolors)) != DMERR_OK) { - res = dmError(DMERR_FREAD, - "PCX: Error reading palette.\n"); + dmErrorMsg("PCX: Error reading palette.\n"); goto error; } } else { + const int nmax = img->pal->ncolors > DMPCX_PAL_COLORS ? DMPCX_PAL_COLORS : img->pal->ncolors; + // If the extra palette is not available, copy the colors from // the header palette to our internal palette structure. - dmMsg(2, "PCX: Initializing palette from header of %d colors\n", ncolors); - for (int i = 0; i < (img->ncolors > DMPCX_PAL_COLORS ? DMPCX_PAL_COLORS : img->ncolors); i++) + dmMsg(2, "PCX: Initializing palette from header of %d colors (%d)\n", ncolors, nmax); + + for (int i = 0; i < nmax; i++) { - img->pal[i].r = hdr.colorMap[i].r; - img->pal[i].g = hdr.colorMap[i].g; - img->pal[i].b = hdr.colorMap[i].b; + img->pal->colors[i].r = hdr.colorMap[i].r; + img->pal->colors[i].g = hdr.colorMap[i].g; + img->pal->colors[i].b = hdr.colorMap[i].b; } } } @@ -1626,7 +1779,7 @@ DMIFFBMHD bmhd; Uint32 camg; int ncolors; - DMColor *pal; + DMPalette *pal; Uint32 idsig; char *idstr; } DMIFF; @@ -1896,7 +2049,7 @@ // Black out any pixels with mask bit 0 if (!data) - dp[xc] = img->ctransp < 0 ? 0 : img->ctransp; + dp[xc] = img->pal->ctransp < 0 ? 0 : img->pal->ctransp; } } } @@ -2036,16 +2189,16 @@ // Read palette if (iff.ncolors > 0) { - if (!dmPaletteAlloc(&iff.pal, iff.ncolors, - (iff.bmhd.masking == IFF_MASK_TRANSP) ? iff.bmhd.transp : -1)) + if ((res = dmPaletteAlloc(&iff.pal, iff.ncolors, + (iff.bmhd.masking == IFF_MASK_TRANSP) ? iff.bmhd.transp : -1)) != DMERR_OK) { - return dmError(DMERR_MALLOC, - "IFF: Could not allocate palette data.\n"); + dmErrorMsg("IFF: Could not allocate palette data.\n"); + return res; } - if (!dmPaletteReadData(fp, iff.pal, iff.ncolors)) + if ((res = dmPaletteReadData(fp, iff.pal, iff.ncolors)) != DMERR_OK) { - return dmError(DMERR_FREAD, - "IFF: Error reading CMAP.\n"); + dmErrorMsg("IFF: Error reading CMAP.\n"); + return res; } } @@ -2129,7 +2282,7 @@ if (*pimg != NULL && (*pimg)->format == DM_COLFMT_PALETTE) { // Check that we DO have a palette .. - if (iff.pal == NULL || iff.ncolors == 0) + if (iff.pal == NULL || iff.pal->ncolors == 0) { return dmError(DMERR_INVALID_DATA, "IFF: A paletted/indexed color image with no CMAP. Bailing out.\n"); @@ -2138,7 +2291,7 @@ // If halfbrite is used, duplicate the palette if (iff.camg & IFF_CAMG_HALFBRITE) { - void *ptmp; + int ncolors = iff.ncolors; if (iff.idsig != IFF_ID_ILBM) { dmErrorMsg("IFF: Non-planar PBM file with Halfbrite enabled! This might not work.\n"); @@ -2150,25 +2303,21 @@ "IFF: Halfbrite enabled, but ncolors > 128.\n"); } - if ((ptmp = dmRealloc(iff.pal, sizeof(DMColor) * iff.ncolors * 2)) == NULL) + if ((res = dmPaletteResize(&iff.pal, ncolors * 2)) != DMERR_OK) { - dmFree(iff.pal); - iff.pal = NULL; - return DMERR_MALLOC; + dmPaletteFree(iff.pal); + return res; } - else - iff.pal = ptmp; - - for (int i = 0; i < iff.ncolors; i++) + + for (int i = 0; i < ncolors; i++) { - int i2 = iff.ncolors + i; - iff.pal[i2].r = iff.pal[i].r / 2; - iff.pal[i2].g = iff.pal[i].g / 2; - iff.pal[i2].b = iff.pal[i].b / 2; + int i2 = ncolors + i; + iff.pal->colors[i2].r = iff.pal->colors[i].r / 2; + iff.pal->colors[i2].g = iff.pal->colors[i].g / 2; + iff.pal->colors[i2].b = iff.pal->colors[i].b / 2; } } - (*pimg)->ncolors = iff.ncolors; (*pimg)->pal = iff.pal; } @@ -2384,8 +2533,8 @@ iff.bmhd.yasp = 1; iff.camg = 0; // XXX TODO: when/if HAM support - iff.bmhd.masking = (img->ctransp < 0) ? IFF_MASK_NONE : spec->mask; - iff.bmhd.transp = (img->ctransp >= 0 && spec->mask == IFF_MASK_TRANSP) ? img->ctransp : 0xffff; + iff.bmhd.masking = (img->pal && img->pal->ctransp < 0) ? IFF_MASK_NONE : spec->mask; + iff.bmhd.transp = (img->pal && img->pal->ctransp >= 0 && spec->mask == IFF_MASK_TRANSP) ? img->pal->ctransp : 0xffff; iff.bmhd.nplanes = (iff.idsig == IFF_ID_PBM && spec->nplanes < 8) ? 8 : spec->nplanes; // Apparently ACBM can't/should not use compression .. even though @@ -2436,29 +2585,23 @@ // // CMAP // - if (img->ncolors > 0 && spec->format == DM_COLFMT_PALETTE) + if (img->pal->ncolors > 0 && spec->format == DM_COLFMT_PALETTE) { if ((res = dmWriteIFFChunkHdr(fp, &iff.chCMAP, IFF_ID_CMAP)) != DMERR_OK) goto out; - for (int i = 0; i < img->ncolors; i++) + if ((res = dmPaletteWriteData(fp, img->pal, img->pal->ncolors, -1)) != DMERR_OK) { - DMColor *col = &img->pal[i]; - if (!dmf_write_byte(fp, col->r) || - !dmf_write_byte(fp, col->g) || - !dmf_write_byte(fp, col->b)) - { - res = dmError(DMERR_FWRITE, - "IFF: Could not write CMAP palette entry #%d.\n", i); - goto out; - } + res = dmError(DMERR_FWRITE, + "IFF: Could not write CMAP palette.\n"); + goto out; } if ((res = dmWriteIFFChunkFinish(fp, &iff.chCMAP)) != DMERR_OK) goto out; dmMsg(2, "IFF: CMAP %d entries (%d bytes)\n", - img->ncolors, iff.chCMAP.size); + img->pal->ncolors, iff.chCMAP.size); } // @@ -2556,7 +2699,7 @@ dmMemset(buf, 0, bufLen); for (int xc = 0; xc < img->width * spec->scaleX; xc++) - buf[xc / 8] |= (sp[xc / spec->scaleX] == img->ctransp) << (7 - (xc & 7)); + buf[xc / 8] |= (sp[xc / spec->scaleX] == img->pal->ctransp) << (7 - (xc & 7)); if (!dmIFFWriteOneRow(fp, &iff, buf, bufLen)) { diff -r d17512dbb4ef -r 4276b8c0fef0 tools/libgfx.h --- a/tools/libgfx.h Thu Feb 28 12:32:07 2019 +0200 +++ b/tools/libgfx.h Tue Mar 05 09:56:47 2019 +0200 @@ -70,6 +70,14 @@ }; +typedef struct +{ + int ncolors; // number of colors in palette, if any + int ctransp; // transparency color index, -1 if none + DMColor *colors;// colors +} DMPalette; + + // Bitmapped image struct typedef struct { @@ -80,10 +88,8 @@ float aspect; // aspect ratio (vert / horiz), <= 0 if not set - int ncolors; // number of colors in palette, if any - int ctransp; // transparency color index BOOL constpal; // is the palette a const? - DMColor *pal; // pointer to palette struct, NULL if no palette + DMPalette *pal; // pointer to palette struct, NULL if no palette size_t size; Uint8 *data; @@ -124,9 +130,11 @@ int dmImageGetBitsPerPixel(const int format); int dmImageProbeGeneric(const Uint8 *buf, const size_t len, const DMImageFormat **fmt, int *index); -BOOL dmCompareColor(const DMColor *c1, const DMColor *c2, BOOL alpha); -BOOL dmPaletteAlloc(DMColor **ppal, int ncolors, int ctransp); -BOOL dmImagePaletteAlloc(DMImage *img, int ncolors, int ctransp); +BOOL dmCompareColor(const DMColor *c1, const DMColor *c2, const BOOL alpha); +int dmPaletteAlloc(DMPalette **ppal, const int ncolors, const int ctransp); +int dmPaletteResize(DMPalette **ppal, const int ncolors); +void dmPaletteFree(DMPalette *pal); +int dmPaletteCopy(DMPalette **pdst, const DMPalette *src); int dmWriteImageData(const DMImage *img, void *cbdata,