comparison tools/libgfx.c @ 2064:3617ef01c1de

Separate ILBM and PBM subformats of IFF images.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 05 Dec 2018 13:31:59 +0200
parents bd109c0a7b88
children 451980580189
comparison
equal deleted inserted replaced
2063:bd109c0a7b88 2064:3617ef01c1de
1499 DMIFFBMHD bmhd; 1499 DMIFFBMHD bmhd;
1500 Uint32 camg; 1500 Uint32 camg;
1501 int ncolors; 1501 int ncolors;
1502 DMColor *pal; 1502 DMColor *pal;
1503 Uint32 idsig; 1503 Uint32 idsig;
1504 char *idstr;
1504 } DMIFF; 1505 } DMIFF;
1505 1506
1506 1507
1507 static int fmtProbeIFF(const Uint8 *buf, const size_t len) 1508 static int fmtProbeIFF(const Uint8 *buf, const size_t len)
1508 { 1509 {
1800 return dmError(DMERR_INVALID_DATA, 1801 return dmError(DMERR_INVALID_DATA,
1801 "IFF: Not a IFF ILBM/PBM/ACBM file.\n"); 1802 "IFF: Not a IFF ILBM/PBM/ACBM file.\n");
1802 } 1803 }
1803 1804
1804 dmMsg(3, "IFF: FORM is %s format image, with size %d bytes.\n", 1805 dmMsg(3, "IFF: FORM is %s format image, with size %d bytes.\n",
1805 iff.idsig == IFF_ID_ILBM ? "ILBM" : (iff.idsig == IFF_ID_PBM ? "PBM" : "ACBM"), 1806 iff.idsig == IFF_ID_ILBM ? "ILBM" :
1807 (iff.idsig == IFF_ID_PBM ? "PBM" : "ACBM"),
1806 chunk.size); 1808 chunk.size);
1807 1809
1808 while (!parsed && !dmfeof(fp)) 1810 while (!parsed && !dmfeof(fp))
1809 { 1811 {
1810 // Read chunk header 1812 // Read chunk header
2189 else 2191 else
2190 return dmf_write_str(fp, buf, bufLen); 2192 return dmf_write_str(fp, buf, bufLen);
2191 } 2193 }
2192 2194
2193 2195
2194 int dmWriteIFFImage(DMResource *fp, const DMImage *img, const DMImageConvSpec *cpspec) 2196 int dmWriteIFFImage(DMResource *fp, const DMImage *img, const DMImageConvSpec *spec)
2195 { 2197 {
2196 DMIFF iff; 2198 DMIFF iff;
2197 Uint8 *buf = NULL; 2199 Uint8 *buf = NULL;
2198 size_t bufLen; 2200 size_t bufLen;
2199 int res = DMERR_OK; 2201 int res = DMERR_OK;
2200 DMImageConvSpec pspec, *spec = &pspec; 2202 //DMImageConvSpec pspec, *spec = &pspec;
2201 2203
2202 memcpy(&pspec, cpspec, sizeof(DMImageConvSpec)); 2204 //memcpy(&pspec, cpspec, sizeof(DMImageConvSpec));
2203 2205
2204 // XXX: Non-paletted ILBM not supported! 2206 // XXX: Non-paletted IFF not supported!
2205 if (!spec->paletted) 2207 if (!spec->paletted)
2206 { 2208 {
2207 return dmError(DMERR_NOT_SUPPORTED, 2209 return dmError(DMERR_NOT_SUPPORTED,
2208 "Non-paletted IFF is not supported.\n"); 2210 "Non-paletted IFF is not supported.\n");
2209 } 2211 }
2210 2212
2211 if (!spec->planar && spec->nplanes < 8) 2213 switch (spec->format)
2212 spec->nplanes = 8; 2214 {
2215 case DM_IMGFMT_IFF_ILBM: iff.idsig = IFF_ID_ILBM; iff.idstr = "ILBM"; break;
2216 case DM_IMGFMT_IFF_PBM : iff.idsig = IFF_ID_PBM; iff.idstr = "PBM"; break;
2217 case DM_IMGFMT_IFF_ACBM: iff.idsig = IFF_ID_ACBM; iff.idstr = "ACBM"; break;
2218 }
2213 2219
2214 // Setup headers 2220 // Setup headers
2215 iff.bmhd.x = 0; 2221 iff.bmhd.x = 0;
2216 iff.bmhd.y = 0; 2222 iff.bmhd.y = 0;
2217 iff.bmhd.w = img->width * spec->scaleX; 2223 iff.bmhd.w = img->width * spec->scaleX;
2224 2230
2225 iff.camg = 0; // XXX TODO: when/if HAM support 2231 iff.camg = 0; // XXX TODO: when/if HAM support
2226 iff.bmhd.masking = (img->ctransp < 0) ? IFF_MASK_NONE : spec->mask; 2232 iff.bmhd.masking = (img->ctransp < 0) ? IFF_MASK_NONE : spec->mask;
2227 iff.bmhd.compression = spec->compression ? IFF_COMP_BYTERUN1 : IFF_COMP_NONE; 2233 iff.bmhd.compression = spec->compression ? IFF_COMP_BYTERUN1 : IFF_COMP_NONE;
2228 iff.bmhd.transp = (img->ctransp >= 0 && spec->mask == IFF_MASK_TRANSP) ? img->ctransp : 0xffff; 2234 iff.bmhd.transp = (img->ctransp >= 0 && spec->mask == IFF_MASK_TRANSP) ? img->ctransp : 0xffff;
2229 iff.bmhd.nplanes = spec->nplanes; 2235 iff.bmhd.nplanes = (iff.idsig == IFF_ID_PBM && spec->nplanes < 8) ? 8 : spec->nplanes;
2230 iff.idsig = spec->planar ? IFF_ID_ILBM : IFF_ID_PBM;
2231 2236
2232 dmMsg(2, "IFF: nplanes=%d, comp=%d, mask=%d\n", 2237 dmMsg(2, "IFF: nplanes=%d, comp=%d, mask=%d\n",
2233 iff.bmhd.nplanes, iff.bmhd.compression, iff.bmhd.masking); 2238 iff.bmhd.nplanes, iff.bmhd.compression, iff.bmhd.masking);
2234 2239
2235 // Write IFF FORM header 2240 // Write IFF FORM header
2239 // Write IFF ILBM/PBM signature 2244 // Write IFF ILBM/PBM signature
2240 if (!dmf_write_be32(fp, iff.idsig)) 2245 if (!dmf_write_be32(fp, iff.idsig))
2241 { 2246 {
2242 res = dmError(DMERR_FWRITE, 2247 res = dmError(DMERR_FWRITE,
2243 "IFF: Error writing %s signature.\n", 2248 "IFF: Error writing %s signature.\n",
2244 spec->planar ? "ILBM" : "PBM"); 2249 iff.idstr);
2245 goto out; 2250 goto out;
2246 } 2251 }
2247 2252
2248 // Write BMHD chunk and data 2253 // Write BMHD chunk and data
2249 if ((res = dmWriteIFFChunkHdr(fp, &iff.chBMHD, IFF_ID_BMHD)) != DMERR_OK || 2254 if ((res = dmWriteIFFChunkHdr(fp, &iff.chBMHD, IFF_ID_BMHD)) != DMERR_OK ||
2317 // Encode the body 2322 // Encode the body
2318 // 2323 //
2319 if ((res = dmWriteIFFChunkHdr(fp, &iff.chBODY, IFF_ID_BODY)) != DMERR_OK) 2324 if ((res = dmWriteIFFChunkHdr(fp, &iff.chBODY, IFF_ID_BODY)) != DMERR_OK)
2320 goto out; 2325 goto out;
2321 2326
2322
2323 // Allocate encoding buffer 2327 // Allocate encoding buffer
2324 if (spec->planar) 2328 if (iff.idsig == IFF_ID_ILBM)
2325 bufLen = (((img->width * spec->scaleX) + 15) / 16) * 2; 2329 bufLen = (((img->width * spec->scaleX) + 15) / 16) * 2;
2326 else 2330 else
2327 bufLen = img->width * spec->scaleX; 2331 bufLen = img->width * spec->scaleX;
2328 2332
2329 dmMsg(2, "IFF: Line/plane row size %d bytes.\n", bufLen); 2333 dmMsg(2, "IFF: Line/plane row size %d bytes.\n", bufLen);
2330 2334
2331 if ((buf = dmMalloc(bufLen)) == NULL) 2335 if ((buf = dmMalloc(bufLen)) == NULL)
2332 return DMERR_MALLOC; 2336 return DMERR_MALLOC;
2333 2337
2334 // Encode the body 2338 // Encode the body
2335 for (int yc = 0; yc < img->height; yc++) 2339 {
2336 for (int yscale = 0; yscale < spec->scaleY; yscale++) 2340 for (int yc = 0; yc < img->height; yc++)
2337 { 2341 for (int yscale = 0; yscale < spec->scaleY; yscale++)
2338 const Uint8 *sp = img->data + (yc * img->pitch); 2342 {
2339 2343 const Uint8 *sp = img->data + (yc * img->pitch);
2340 if (spec->planar) 2344
2341 { 2345 if (iff.idsig == IFF_ID_ILBM)
2342 for (int plane = 0; plane < spec->nplanes; plane++) 2346 {
2343 { 2347 for (int plane = 0; plane < spec->nplanes; plane++)
2344 // Encode bitplane 2348 {
2345 dmMemset(buf, 0, bufLen); 2349 // Encode bitplane
2346 2350 dmMemset(buf, 0, bufLen);
2351
2352 for (int xc = 0; xc < img->width * spec->scaleX; xc++)
2353 buf[xc / 8] |= ((sp[xc / spec->scaleX] >> plane) & 1) << (7 - (xc & 7));
2354
2355 // Compress / write data
2356 if (!dmIFFWriteOneRow(fp, &iff, buf, bufLen))
2357 {
2358 res = dmError(DMERR_FWRITE,
2359 "IFF: Error writing ILBM image plane #%d @ row %d.\n",
2360 plane, yc);
2361 goto out;
2362 }
2363 }
2364
2365 // Write mask data, if any
2366 if (iff.bmhd.masking == IFF_MASK_HAS_MASK)
2367 {
2368 dmMemset(buf, 0, bufLen);
2369
2370 for (int xc = 0; xc < img->width * spec->scaleX; xc++)
2371 buf[xc / 8] |= (sp[xc / spec->scaleX] == img->ctransp) << (7 - (xc & 7));
2372
2373 if (!dmIFFWriteOneRow(fp, &iff, buf, bufLen))
2374 {
2375 res = dmError(DMERR_FWRITE,
2376 "IFF: Error writing ILBM mask plane %d.\n", yc);
2377 goto out;
2378 }
2379 }
2380 }
2381 else
2382 {
2347 for (int xc = 0; xc < img->width * spec->scaleX; xc++) 2383 for (int xc = 0; xc < img->width * spec->scaleX; xc++)
2348 buf[xc / 8] |= ((sp[xc / spec->scaleX] >> plane) & 1) << (7 - (xc & 7)); 2384 buf[xc] = sp[xc / spec->scaleX];
2349 2385
2350 // Compress / write data
2351 if (!dmIFFWriteOneRow(fp, &iff, buf, bufLen)) 2386 if (!dmIFFWriteOneRow(fp, &iff, buf, bufLen))
2352 { 2387 {
2353 res = dmError(DMERR_FWRITE, 2388 res = dmError(DMERR_FWRITE,
2354 "IFF: Error writing image plane #%d @ %d.\n", 2389 "IFF: Error writing PBM image row #%d.\n", yc);
2355 plane, yc);
2356 goto out; 2390 goto out;
2357 } 2391 }
2358 }
2359
2360 // Write mask data, if any
2361 if (iff.bmhd.masking == IFF_MASK_HAS_MASK)
2362 {
2363 dmMemset(buf, 0, bufLen);
2364
2365 for (int xc = 0; xc < img->width * spec->scaleX; xc++)
2366 buf[xc / 8] |= (sp[xc / spec->scaleX] == img->ctransp) << (7 - (xc & 7));
2367
2368 if (!dmIFFWriteOneRow(fp, &iff, buf, bufLen))
2369 {
2370 res = dmError(DMERR_FWRITE,
2371 "IFF: Error writing mask plane %d.\n", yc);
2372 goto out;
2373 }
2374 }
2375 }
2376 else
2377 {
2378 for (int xc = 0; xc < img->width * spec->scaleX; xc++)
2379 buf[xc] = sp[xc / spec->scaleX];
2380
2381 if (!dmIFFWriteOneRow(fp, &iff, buf, bufLen))
2382 {
2383 res = dmError(DMERR_FWRITE,
2384 "IFF: Error writing PBM image row #%d.\n", yc);
2385 goto out;
2386 } 2392 }
2387 } 2393 }
2388 } 2394 }
2389 2395
2390 if ((res = dmWriteIFFChunkFinish(fp, &iff.chBODY)) != DMERR_OK) 2396 if ((res = dmWriteIFFChunkFinish(fp, &iff.chBODY)) != DMERR_OK)
2421 "pcx", "Z-Soft Paintbrush", 2427 "pcx", "Z-Soft Paintbrush",
2422 DM_IMGFMT_PCX, DM_FMT_RDWR, 2428 DM_IMGFMT_PCX, DM_FMT_RDWR,
2423 fmtProbePCX, dmReadPCXImage, dmWritePCXImage, 2429 fmtProbePCX, dmReadPCXImage, dmWritePCXImage,
2424 }, 2430 },
2425 { 2431 {
2426 "iff", "IFF ILBM/PBM/ACBM", 2432 "lbm", "IFF ILBM (interleaved/old DP)",
2427 DM_IMGFMT_IFF, DM_FMT_RDWR, 2433 DM_IMGFMT_IFF_ILBM, DM_FMT_RDWR,
2434 fmtProbeIFF, dmReadIFFImage, dmWriteIFFImage,
2435 },
2436 {
2437 "pbm", "IFF PBM (DP2e)",
2438 DM_IMGFMT_IFF_PBM, DM_FMT_RDWR,
2439 fmtProbeIFF, dmReadIFFImage, dmWriteIFFImage,
2428 fmtProbeIFF, dmReadIFFImage, dmWriteIFFImage, 2440 fmtProbeIFF, dmReadIFFImage, dmWriteIFFImage,
2429 }, 2441 },
2430 { 2442 {
2431 "raw", "Plain bitplaned (planar or non-planar) RAW", 2443 "raw", "Plain bitplaned (planar or non-planar) RAW",
2432 DM_IMGFMT_RAW, DM_FMT_WR, 2444 DM_IMGFMT_RAW, DM_FMT_WR,