int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer){ IFFResourceMap *Map; bytestream b; unsigned i; if(ChunkInfo->Size < 20) return 0; set_bytestream(&b, Buffer, ChunkInfo->Size); ChunkInfo->FormattedData = calloc(1, sizeof(IFFResourceMap)); if(ChunkInfo->FormattedData == NULL) return 0; Map = ChunkInfo->FormattedData; Map->Reserved = read_uint32(&b); Map->Version = read_uint32(&b); memcpy(Map->MagicNumber, b.Buffer, 4); skipbytes(&b, 4); Map->IFFSize = read_uint32(&b); Map->TypeCount = read_uint32(&b); if(Map->Reserved != 0 || Map->Version > 1) return 0; Map->ResourceTypes = calloc(Map->TypeCount, sizeof(IFFResourceType)); if(Map->ResourceTypes == NULL) return 0; for(i=0; i<Map->TypeCount; i++){ IFFResourceType * Type = &Map->ResourceTypes[i]; unsigned j; if(b.Size < 8) return 0; memcpy(Type->Type, b.Buffer, 4); skipbytes(&b, 4); Type->ResourceCount = read_uint32(&b); Type->Resources = calloc(Type->ResourceCount, sizeof(IFFResource)); if(Type->Resources == NULL) return 0; for(j=0; j<Type->ResourceCount; j++){ IFFResource * Resource = &Type->Resources[j]; if(b.Size < ((Map->Version == 0) ? 9 : 11)) return 0; Resource->Offset = read_uint32(&b); Resource->ChunkID = (Map->Version == 0) ? read_uint16(&b) : read_uint32(&b); Resource->Flags = read_uint16(&b); if(Map->Version == 0){ if(!read_c_string(&b, &Resource->Label)) return 0; }else{ if(!read_pascal_string(&b, &Resource->Label)) return 0; } } } return 1; }
int iff_parse_tmpl(IFFChunk * ChunkInfo, const uint8_t * Buffer){ IFFTemplate *Template; bytestream b; const uint8_t * ptr = Buffer; unsigned Size = ChunkInfo->Size; unsigned FieldCount; unsigned i; if(Size == 0) return 1; /* Walk through a first-pass to find the total field count */ for(FieldCount=0; Size; FieldCount++){ unsigned length = *ptr; if(Size < 5 || length > Size-5) return 0; ptr += length+5; Size -= length+5; } ChunkInfo->FormattedData = calloc(1, sizeof(IFFTemplate)); if(ChunkInfo->FormattedData == NULL) return 0; Template = ChunkInfo->FormattedData; Template->FieldCount = FieldCount; Template->Fields = calloc(FieldCount, sizeof(IFFTemplateField)); if(Template->Fields == NULL) return 0; set_bytestream(&b, Buffer, ChunkInfo->Size); for(i=0; i<FieldCount; i++){ IFFTemplateField * Field = &Template->Fields[i]; if(!read_pascal_string(&b, &Field->Name)) return 0; memcpy(Field->Type, b.Buffer, 4); skipbytes(&b, 4); } return 1; }
Flex *flexReadBegin( char *filename, unsigned int *failID, int *failpos ) { FILE *fp = NULL; Flex *flex; Frame *frame = NULL; Layer *layer = NULL; unsigned int id, formsize, type, cksize; int rlen, nframes = 0, nlayers = 0; /* open the file */ fp = fopen( filename, "rb" ); if ( !fp ) return NULL; /* read the first 12 bytes */ set_flen( 0 ); id = getU4( fp ); formsize = getU4( fp ); type = getU4( fp ); if ( 12 != get_flen() ) { fclose( fp ); return NULL; } /* is this a flex image? */ if ( id != ID_FORM ) { fclose( fp ); if ( failpos ) *failpos = 12; return NULL; } if ( type != ID_FPBM ) { fclose( fp ); if ( failpos ) *failpos = 12; return NULL; } /* allocate a Flex */ flex = calloc( 1, sizeof( Flex )); if ( !flex ) goto Fail; /* get the first chunk header */ id = getU4( fp ); cksize = getU4( fp ); if ( 0 > get_flen() ) goto Fail; /* process chunks as they're encountered */ while ( 1 ) { set_flen( 0 ); switch ( id ) { case ID_FPHD: if(cksize==28) // Older file version { flex->hdr.width = getI2( fp ); flex->hdr.height = getI2( fp ); } else // cksize==32 { flex->hdr.width = getI4( fp ); flex->hdr.height = getI4( fp ); } flex->hdr.numLayers = getI2( fp ); flex->hdr.numFrames = getI2( fp ); flex->hdr.numBuffers = getI2( fp ); flex->hdr.flags = getI2( fp ); flex->hdr.srcLayerDepth = getI2( fp ); skipbytes( fp, 2 ); flex->hdr.pixelAspect = getF4( fp ); flex->hdr.pixelWidth = getF4( fp ); flex->hdr.framesPerSecond = getF4( fp ); frame = calloc( flex->hdr.numFrames, sizeof( Frame )); if ( !frame ) goto Fail; flex->frame = frame; break; case ID_FLEX: if ( !frame ) goto Fail; if ( nframes >= flex->hdr.numFrames ) goto Fail; nlayers = getI2( fp ); layer = calloc( nlayers, sizeof( Layer )); if ( !layer ) goto Fail; frame[ nframes ].layer = layer; frame[ nframes ].hdr.numLayers = nlayers; nlayers = 0; ++nframes; break; case ID_LYHD: if ( !layer ) goto Fail; if ( nlayers >= frame[ nframes - 1 ].hdr.numLayers ) goto Fail; layer[ nlayers ].w = flex->hdr.width; layer[ nlayers ].h = flex->hdr.height; layer[ nlayers ].hdr.flags = getI2( fp ); layer[ nlayers ].hdr.layerType = getI2( fp ); layer[ nlayers ].hdr.layerDepth = getI2( fp ); layer[ nlayers ].hdr.compression = getI2( fp ); layer[ nlayers ].hdr.blackPoint = getF4( fp ); layer[ nlayers ].hdr.whitePoint = getF4( fp ); layer[ nlayers ].hdr.gamma = getF4( fp ); break; case ID_LAYR: if ( !layer ) goto Fail; layer[ nlayers ].offset = ftell( fp ); layer[ nlayers ].size = cksize; ++nlayers; break; default: break; } /* error while reading current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > cksize ) goto Fail; /* skip unread parts of the current subchunk */ cksize += cksize & 1; if ( rlen < cksize ) fseek( fp, cksize - rlen, SEEK_CUR ); /* end of the file? */ if ( formsize <= ftell( fp ) - 8 ) break; /* get the next chunk header */ set_flen( 0 ); id = getU4( fp ); cksize = getU4( fp ); if ( 8 != get_flen() ) goto Fail; } flex->fp = fp; return flex; Fail: if ( failID ) *failID = id; if ( fp ) { if ( failpos ) *failpos = ftell( fp ); fclose( fp ); } flexFree( flex ); return NULL; }
int main(int argc, char **argv) { int y; FBIO *fbp; int xout, yout, n, m, xstart, xskip; if (!get_args(argc, argv)) { (void)fputs(usage, stderr); bu_exit(1, NULL); } /* autosize input? */ if (fileinput && autosize) { size_t w, h; if (fb_common_file_size(&w, &h, file_name, 3)) { file_width = w; file_height = h; } else { fprintf(stderr, "pix-fb: unable to autosize\n"); } } /* If screen size was not set, track the file size */ if (scr_width == 0) scr_width = file_width; if (scr_height == 0) scr_height = file_height; if ((fbp = fb_open(framebuffer, scr_width, scr_height)) == NULL) { bu_exit(12, NULL); } /* Get the screen size we were given */ scr_width = fb_getwidth(fbp); scr_height = fb_getheight(fbp); /* compute number of pixels to be output to screen */ if (scr_xoff < 0) { xout = scr_width + scr_xoff; xskip = (-scr_xoff); xstart = 0; } else { xout = scr_width - scr_xoff; xskip = 0; xstart = scr_xoff; } if (xout < 0) bu_exit(0, NULL); /* off screen */ if ((size_t)xout > (file_width-file_xoff)) xout = (file_width-file_xoff); scanpix = xout; /* # pixels on scanline */ if (inverse) scr_yoff = (-scr_yoff); yout = scr_height - scr_yoff; if (yout < 0) bu_exit(0, NULL); /* off screen */ if ((size_t)yout > (file_height-file_yoff)) yout = (file_height-file_yoff); /* Only in the simplest case use multi-line writes */ if (!one_line_only && multiple_lines > 0 && !inverse && !zoom && (size_t)xout == file_width && file_width <= (size_t)scr_width) { scanpix *= multiple_lines; } scanbytes = scanpix * sizeof(RGBpixel); if ((scanline = (unsigned char *)malloc(scanbytes)) == RGBPIXEL_NULL) { fprintf(stderr, "pix-fb: malloc(%d) failure for scanline buffer\n", scanbytes); bu_exit(2, NULL); } if (clear) { fb_clear(fbp, PIXEL_NULL); } if (zoom) { /* Zoom in, and center the display. Use square zoom. */ int zoomit; zoomit = scr_width/xout; if (scr_height/yout < zoomit) zoomit = scr_height/yout; if (inverse) { fb_view(fbp, scr_xoff+xout/2, scr_height-1-(scr_yoff+yout/2), zoomit, zoomit); } else { fb_view(fbp, scr_xoff+xout/2, scr_yoff+yout/2, zoomit, zoomit); } } if (file_yoff != 0) skipbytes(infd, (off_t)file_yoff*(off_t)file_width*sizeof(RGBpixel)); if (multiple_lines) { /* Bottom to top with multi-line reads & writes */ unsigned long height; for (y = scr_yoff; y < scr_yoff + yout; y += multiple_lines) { n = bu_mread(infd, (char *)scanline, scanbytes); if (n <= 0) break; height = multiple_lines; if (n != scanbytes) { height = (n/sizeof(RGBpixel)+xout-1)/xout; if (height <= 0) break; } /* Don't over-write */ if ((size_t)(y + height) > (size_t)(scr_yoff + yout)) height = scr_yoff + yout - y; if (height <= 0) break; m = fb_writerect(fbp, scr_xoff, y, file_width, height, scanline); if ((size_t)m != file_width*height) { fprintf(stderr, "pix-fb: fb_writerect(x=%d, y=%d, w=%lu, h=%lu) failure, ret=%d, s/b=%d\n", scr_xoff, y, (unsigned long)file_width, height, m, scanbytes); } } } else if (!inverse) { /* Normal way -- bottom to top */ for (y = scr_yoff; y < scr_yoff + yout; y++) { if (y < 0 || y > scr_height) { skipbytes(infd, (off_t)file_width*sizeof(RGBpixel)); continue; } if (file_xoff+xskip != 0) skipbytes(infd, (off_t)(file_xoff+xskip)*sizeof(RGBpixel)); n = bu_mread(infd, (char *)scanline, scanbytes); if (n <= 0) break; m = fb_write(fbp, xstart, y, scanline, xout); if (m != xout) { fprintf(stderr, "pix-fb: fb_write(x=%d, y=%d, npix=%d) ret=%d, s/b=%d\n", scr_xoff, y, xout, m, xout); } /* slop at the end of the line? */ if ((size_t)file_xoff+xskip+scanpix < file_width) skipbytes(infd, (off_t)(file_width-file_xoff-xskip-scanpix)*sizeof(RGBpixel)); } } else { /* Inverse -- top to bottom */ for (y = scr_height-1-scr_yoff; y >= scr_height-scr_yoff-yout; y--) { if (y < 0 || y >= scr_height) { skipbytes(infd, (off_t)file_width*sizeof(RGBpixel)); continue; } if (file_xoff+xskip != 0) skipbytes(infd, (off_t)(file_xoff+xskip)*sizeof(RGBpixel)); n = bu_mread(infd, (char *)scanline, scanbytes); if (n <= 0) break; m = fb_write(fbp, xstart, y, scanline, xout); if (m != xout) { fprintf(stderr, "pix-fb: fb_write(x=%d, y=%d, npix=%d) ret=%d, s/b=%d\n", scr_xoff, y, xout, m, xout); } /* slop at the end of the line? */ if ((size_t)file_xoff+xskip+scanpix < file_width) skipbytes(infd, (off_t)(file_width-file_xoff-xskip-scanpix)*sizeof(RGBpixel)); } } sleep(pause_sec); if (fb_close(fbp) < 0) { fprintf(stderr, "pix-fb: Warning: fb_close() error\n"); } return 0; }