nuclear@0: #include nuclear@0: #include nuclear@1: #include nuclear@2: #include nuclear@1: #include nuclear@0: #include "image.h" nuclear@0: nuclear@1: /* hammer dump format (input) nuclear@1: * byte order: little endian nuclear@1: * nuclear@1: * 4 bytes: palette changes per scanline (cps) nuclear@1: * 256 * cps * 2 bytes: [ idx | r | g | b ] nuclear@1: * 320 * 256 bytes: linear HAM pixels nuclear@1: */ nuclear@1: nuclear@1: /* interleaved ham format (output) nuclear@1: * byte order: big endian nuclear@1: * nuclear@1: * 4 bytes: magic: "HAAM" nuclear@1: * 2 bytes: width nuclear@1: * 2 bytes: height nuclear@1: * 1 byte: number of bitplanes nuclear@1: * 1 byte: padding nuclear@1: * 2 bytes: number of palette change descriptors (nchg) nuclear@1: * 16 * 2 bytes: initial palette [ x | r | g | b ] nuclear@1: * nchg * 4 bytes: [ scanline ] [ idx | r | g | b ] nuclear@1: * width * height / 8 * bitplanes bytes: pixels interleaved scanlines nuclear@1: * [ row0 bpl0 ] ... [ row0 bplN ] [ row1 bpl0 ] ... [ row1 bplN ] ... nuclear@1: */ nuclear@1: nuclear@0: struct ham_image *load_hammer(const char *fname); nuclear@0: int save_ham(struct ham_image *img, const char *fname); nuclear@1: void free_image(struct ham_image *img); nuclear@0: nuclear@0: int main(int argc, char **argv) nuclear@0: { nuclear@1: int i; nuclear@1: struct ham_image *img; nuclear@1: char *name, *dot; nuclear@1: nuclear@1: for(i=1; i> 8) | (x << 8); } nuclear@2: nuclear@1: struct ham_image *load_hammer(const char *fname) nuclear@1: { nuclear@2: int i, x, y, pstart, numpix = 320 * 256; nuclear@2: FILE *fp = 0; nuclear@2: uint32_t cps, npalent; nuclear@2: struct ham_image *img = 0; nuclear@2: struct palchange *tail = 0; nuclear@2: unsigned char *inpixels = 0; nuclear@2: unsigned char *srcptr, *destptr; nuclear@2: uint16_t endtest = 0xaabb; nuclear@2: uint16_t (*letohs)(uint16_t); nuclear@2: nuclear@2: letohs = (*(unsigned char*)&endtest == 0xaa) ? swaps : nops; nuclear@2: nuclear@2: if(!(fp = fopen(fname, "rb"))) { nuclear@2: fprintf(stderr, "failed to open %s: %s\n", fname, strerror(errno)); nuclear@2: return 0; nuclear@2: } nuclear@2: nuclear@2: if(!(img = malloc(sizeof *img))) { nuclear@2: perror("failed to allocate image"); nuclear@2: goto err; nuclear@2: } nuclear@2: img->width = 320; nuclear@2: img->height = 256; nuclear@2: img->nbitplanes = 6; nuclear@2: img->chglist = 0; nuclear@2: nuclear@2: if(!(img->pixels = malloc(img->width * img->height / 8 * img->nbitplanes))) { nuclear@2: perror("failed to allocate pixels"); nuclear@2: goto err; nuclear@2: } nuclear@2: nuclear@2: if(fread(&cps, 4, 1, fp) < 1) goto err; nuclear@2: cps = letohs(cps); nuclear@2: if(cps <= 0 || cps > 16) { nuclear@2: fprintf(stderr, "invalid changes-per-line value: %u\n", (unsigned int)cps); nuclear@2: goto err; nuclear@2: } nuclear@2: nuclear@2: /* read palette changes and palette */ nuclear@2: nuclear@2: npalent = cps * 256; nuclear@2: pstart = npalent - 16; nuclear@2: nuclear@2: for(i=0; iline = i / cps; nuclear@2: chg->entry = palent; nuclear@2: chg->next = 0; nuclear@2: if(tail) { nuclear@2: tail->next = chg; nuclear@2: tail = chg; nuclear@2: } else { nuclear@2: img->chglist = tail = chg; nuclear@2: } nuclear@2: nuclear@2: if(i >= pstart) { nuclear@2: img->palette[i - pstart] = palent & 0xfff; nuclear@2: } nuclear@2: } nuclear@2: nuclear@2: /* read pixels */ nuclear@2: if(!(inpixels = malloc(numpix))) { nuclear@2: perror("failed to allocate pixel buffer"); nuclear@2: goto err; nuclear@2: } nuclear@2: if(fread(inpixels, 1, numpix, fp) < numpix) { nuclear@2: perror("unexpected end of file while reading pixels"); nuclear@2: goto err; nuclear@2: } nuclear@2: nuclear@2: for(i=0; inbitplanes; i++) { nuclear@2: srcptr = inpixels; nuclear@2: destptr = img->pixels + i * img->width / 8; nuclear@2: for(y=0; yheight; y++) { nuclear@2: unsigned char pixval = 0; nuclear@2: for(x=0; xwidth; x++) { nuclear@2: pixval = (pixval << 1) | ((*srcptr++ >> i) & 1); nuclear@2: if((x & 7) == 7) { nuclear@2: *destptr++ = pixval; nuclear@2: pixval = 0; nuclear@2: } nuclear@2: } nuclear@2: destptr += img->width / 8 * (img->nbitplanes - 1); nuclear@2: } nuclear@2: } nuclear@2: nuclear@3: free(inpixels); nuclear@3: fclose(fp); nuclear@2: return img; nuclear@2: nuclear@2: err: nuclear@2: free(inpixels); nuclear@2: if(img) { nuclear@2: while(img->chglist) { nuclear@2: void *tmp = img->chglist; nuclear@2: img->chglist = img->chglist->next; nuclear@2: free(tmp); nuclear@2: } nuclear@2: free(img->pixels); nuclear@2: free(img); nuclear@2: } nuclear@2: if(fp) fclose(fp); nuclear@2: return 0; nuclear@1: } nuclear@1: nuclear@1: int save_ham(struct ham_image *img, const char *fname) nuclear@1: { nuclear@2: int i, num; nuclear@2: unsigned char c, *pptr; nuclear@1: uint16_t val; nuclear@1: FILE *fp; nuclear@2: struct palchange *chg; nuclear@1: nuclear@1: if(!(fp = fopen(fname, "wb"))) { nuclear@1: fprintf(stderr, "failed to open %s for writing: %s\n", fname, strerror(errno)); nuclear@1: return -1; nuclear@1: } nuclear@1: fprintf(fp, "HAAM"); nuclear@1: nuclear@1: val = htons(img->width); nuclear@2: fwrite(&val, 2, 1, fp); nuclear@1: val = htons(img->height); nuclear@2: fwrite(&val, 2, 1, fp); nuclear@2: c = img->nbitplanes; nuclear@2: fwrite(&c, 1, 1, fp); nuclear@2: fwrite(&c, 1, 1, fp); /* padding */ nuclear@2: nuclear@2: num = 0; nuclear@2: chg = img->chglist; nuclear@2: while(chg) { nuclear@2: ++num; nuclear@2: chg = chg->next; nuclear@2: } nuclear@2: num = htons(num); nuclear@2: fwrite(&num, 2, 1, fp); nuclear@2: nuclear@3: for(i=0; i<16; i++) { nuclear@3: val = htons(img->palette[i]); nuclear@3: fwrite(&val, 2, 1, fp); nuclear@3: } nuclear@3: nuclear@2: chg = img->chglist; nuclear@2: while(chg) { nuclear@2: val = htons(chg->line); nuclear@2: fwrite(&val, 2, 1, fp); nuclear@2: val = htons(chg->entry); nuclear@2: fwrite(&val, 2, 1, fp); nuclear@2: chg = chg->next; nuclear@2: } nuclear@2: nuclear@2: pptr = img->pixels; nuclear@2: num = img->width * img->height / 8 * img->nbitplanes; nuclear@2: for(i=0; ipixels); nuclear@1: while(img->chglist) { nuclear@1: void *tmp = img->chglist; nuclear@1: img->chglist = img->chglist->next; nuclear@1: free(tmp); nuclear@1: } nuclear@1: free(img); nuclear@1: } nuclear@1: }