bool ImageOutputWrap::write_tiles_bt (int xbegin, int xend, int ybegin, int yend, int zbegin, int zend, TypeDesc::BASETYPE format, object &buffer, stride_t xstride, stride_t ystride, stride_t zstride) { return write_tiles (xbegin, xend, ybegin, yend, zbegin, zend, format, buffer, xstride, ystride, zstride); }
bool OpenEXROutput::write_tile (int x, int y, int z, TypeDesc format, const void *data, stride_t xstride, stride_t ystride, stride_t zstride) { return write_tiles (x, std::min (x+m_spec.tile_width, m_spec.x+m_spec.width), y, std::min (y+m_spec.tile_height, m_spec.y+m_spec.height), z, std::min (z+m_spec.tile_depth, m_spec.z+m_spec.depth), format, data, xstride, ystride, zstride); }
bool VoxelsIOPlugin::save(const QString &formatName, const QString &fileName, MeshModel &m, const int mask,const RichParameterSet & par, vcg::CallBackPos *cb, QWidget *parent) { // TODO Add error messages vcg::tri::UpdatePosition< CMeshO >::Scale ( m.cm, static_cast< CMeshO::ScalarType >( rasterization_scale ) ); vcg::tri::UpdateBounding< CMeshO >::Box( m.cm ); init_voxmap_size( m ); QScopedArrayPointer< unsigned char > voxels( rasterize( this, m ) ); QString nrrd; if( !voxels || (nrrd = write_nrrd( voxels.data() )).isEmpty() || !(voxels.reset( resample( nrrd )), voxels) || !write_tiles( voxels.data(), fileName ) ) return false; QFile header( fileName.endsWith( ".voxels" ) ? fileName.left( fileName.length() - QString( ".voxels" ).length() ) : fileName + ".header" ); if( !header.open( QIODevice::WriteOnly ) ) return false; QTextStream str( &header ); str << ";;; -*- lisp -*-\n(size " << voxmap_size.X() << " " << voxmap_size.Y() << " " << voxmap_size.Z() << ")\n(voxels . \"" << fileName << "\")\n"; return true; }
bool ImageOutput::write_image (TypeDesc format, const void *data, stride_t xstride, stride_t ystride, stride_t zstride, ProgressCallback progress_callback, void *progress_callback_data) { bool native = (format == TypeDesc::UNKNOWN); stride_t pixel_bytes = native ? (stride_t) m_spec.pixel_bytes (native) : format.size() * m_spec.nchannels; if (xstride == AutoStride) xstride = pixel_bytes; m_spec.auto_stride (xstride, ystride, zstride, format, m_spec.nchannels, m_spec.width, m_spec.height); if (supports ("rectangles")) { // Use a rectangle if we can return write_rectangle (0, m_spec.width, 0, m_spec.height, 0, m_spec.depth, format, data, xstride, ystride, zstride); } bool ok = true; if (progress_callback && progress_callback (progress_callback_data, 0.0f)) return ok; if (m_spec.tile_width && supports ("tiles")) { // Tiled image for (int z = 0; z < m_spec.depth; z += m_spec.tile_depth) { int zend = std::min (z+m_spec.z+m_spec.tile_depth, m_spec.z+m_spec.depth); for (int y = 0; y < m_spec.height; y += m_spec.tile_height) { int yend = std::min (y+m_spec.y+m_spec.tile_height, m_spec.y+m_spec.height); const char *d = (const char *)data + z*zstride + y*ystride; ok &= write_tiles (m_spec.x, m_spec.x+m_spec.width, y+m_spec.y, yend, z+m_spec.z, zend, format, d, xstride, ystride, zstride); if (progress_callback && progress_callback (progress_callback_data, (float)(z*m_spec.height+y)/(m_spec.height*m_spec.depth))) return ok; } } } else { // Scanline image const int chunk = 256; for (int z = 0; z < m_spec.depth; ++z) for (int y = 0; y < m_spec.height && ok; y += chunk) { int yend = std::min (y+m_spec.y+chunk, m_spec.y+m_spec.height); const char *d = (const char *)data + z*zstride + y*ystride; ok &= write_scanlines (y+m_spec.y, yend, z+m_spec.z, format, d, xstride, ystride); if (progress_callback && progress_callback (progress_callback_data, (float)(z*m_spec.height+y)/(m_spec.height*m_spec.depth))) return ok; } } if (progress_callback) progress_callback (progress_callback_data, 1.0f); return ok; }
/** * Program entrypoint. */ int main(int argc, char **argv) { QApplication app(argc, argv); QWidget window; unsigned char *raw_data; unsigned char *buf; int *color_freqs; int *unique_pals; int unique_pals_count; int *pal_indexes; unsigned char *pal_data; int *pal_sizes; unsigned char *tile_data; int tile_data_sz; unsigned char *attrib_data; int attrib_data_sz; const char *input_filename = 0; const char *chr_output_filename = 0; const char *pal_output_filename = 0; const char *attrib_output_filename = 0; int width = -1; int height = -1; /* Process arguments. */ if (!process_args(argv, &input_filename, &chr_output_filename, &pal_output_filename, &attrib_output_filename, &width, &height)) { return(-1); } /* check arguments */ if (!input_filename) { fprintf(stderr, "img2nes: no filename given\n"); return(-1); } #if 0 if (width == -1 || height == -1) { fprintf(stderr, "img2nes: please specify width and height of image\n"); return(-1); } if (width % 16 || height % 16) { fprintf(stderr, "img2nes: width and height must be multiples of 16\n"); return(-1); } #endif QImage originalImage = QImage(input_filename).convertToFormat(QImage::Format_RGB32); if (originalImage.isNull()) { fprintf(stderr, "img2nes: unable to read image '%s'\n", input_filename); return(-1); } width = originalImage.width(); height = originalImage.height(); /* allocate some buffers */ raw_data = (unsigned char *)malloc(width * height * 3); buf = (unsigned char *)malloc(width * height); tile_data_sz = (height / 8) * (width / 8) * 16 * sizeof(unsigned char); tile_data = (unsigned char *)malloc(tile_data_sz); if (!raw_data || !buf || !tile_data) { fprintf(stderr, "img2nes: failed to allocate memory for image data\n"); return(0); } #if 0 /* read input image */ if (!read_image(input_filename, width, height, /*has_alpha=*/0, raw_data)) return(-1); #endif /* convert raw RGB to nes palette indices */ convert_to_nes_colors(originalImage.bits(), width, height, /*has_alpha=*/1, buf); QImage originalNesImage = to_qimage(buf, width, height); QImage reducedColorsImage; QImage reducedPalettesImage; /* that was the easy part */ { int i, j; int cw = width / 16; int ch = height / 16; color_freqs = (int*)calloc(cw * ch, 64 * sizeof(int)); pal_data = (unsigned char *)malloc(cw * ch * 4 * sizeof(unsigned char)); pal_sizes = (int*)malloc(cw * ch * sizeof(int)); /* process all 16x16 blocks */ for (i = 0; i < ch; ++i) { for (j = 0; j < cw; ++j) { int num_colors; unsigned char pal[64]; int *f = &color_freqs[(i*cw+j)*64]; /* count frequency of colors */ count_nes_color_frequencies(&buf[i*16*width+(j*16)], 16, 16, width, f); f[0x0F] = INT_MAX; /* record the colors that are actually used */ nes_palette_from_color_frequencies(f, pal, &num_colors); #if 0 { printf("palette: "); for (int k = 0; k < num_colors; ++k) { printf("%.2X ", pal[k]); } printf("\n"); } #endif /* reduce number of colors if necessary */ reduce_colors(&buf[i*16*width+(j*16)], 16, 16, width, f, pal, &num_colors); /* sort the palette so that different palettes can be easily compared */ qsort(pal, num_colors, sizeof(unsigned char), compare_nes_colors); #if 0 { printf("sorted palette: "); for (int k = 0; k < num_colors; ++k) { printf("%.2X ", pal[k]); } printf("\n"); } #endif /* store the final palette for this 16x16 block */ assert(num_colors <= 4); memcpy(&pal_data[(i*cw+j)*4], pal, num_colors * sizeof(unsigned char)); pal_sizes[i*cw+j] = num_colors; } } reducedColorsImage = to_qimage(buf, width, height); /* now each 16x16 block uses max 4 unique colors the next step is to reduce the number of 4-color palettes, if necessary */ unique_pals = (int*)malloc(cw * ch * sizeof(int)); unique_pals_count = 0; pal_indexes = (int*)malloc(cw * ch * sizeof(int)); /* find unique palettes and record their usage */ find_unique_palettes(pal_data, cw * ch, pal_sizes, unique_pals, &unique_pals_count, pal_indexes); /* printf("unique palettes: %d\n", unique_pals_count); */ /* reduce number of palettes used if necessary */ reduce_palettes(buf, width, height, pal_data, pal_sizes, unique_pals, &unique_pals_count, pal_indexes); reducedPalettesImage = to_qimage(buf, width, height); /* encode tiles */ encode_nes_tiles(buf, width, height, pal_data, pal_sizes, unique_pals, pal_indexes, tile_data); /* write tiles */ write_tiles(chr_output_filename, tile_data, tile_data_sz); /* write palette data */ write_palettes(pal_output_filename, pal_data, pal_sizes, unique_pals, unique_pals_count); /* encode attribute data */ attrib_data_sz = (cw/2)*(ch/2); attrib_data = (unsigned char *)malloc(attrib_data_sz); encode_nes_attributes(cw, ch, pal_indexes, attrib_data); /* write attribute data */ write_attributes(attrib_output_filename, attrib_data, attrib_data_sz); } QHBoxLayout *box = new QHBoxLayout(&window); box->addWidget(create_label(originalImage)); box->addWidget(create_label(originalNesImage)); box->addWidget(create_label(reducedColorsImage)); box->addWidget(create_label(reducedPalettesImage)); window.show(); app.exec(); /* Cleanup */ free(raw_data); free(buf); free(tile_data); free(pal_data); free(pal_sizes); free(unique_pals); free(pal_indexes); free(color_freqs); free(attrib_data); /* All done. */ return 0; }