src/lib/cache.c
changeset 52 148a120ea7d5
parent 34 a387bc77ad52
child 53 8a3165c604f8
equal deleted inserted replaced
51:866eb1aad566 52:148a120ea7d5
   328     pt_cache_abort(cache);
   328     pt_cache_abort(cache);
   329 
   329 
   330     return err;
   330     return err;
   331 }
   331 }
   332 
   332 
   333 int pt_cache_update_png (struct pt_cache *cache, png_structp png, png_infop info)
   333 #define min(a, b) (((a) < (b)) ? (a) : (b))
       
   334 
       
   335 /**
       
   336  * Decode the PNG data directly to mmap() - not good for sparse backgrounds
       
   337  */
       
   338 static int decode_png_raw (struct pt_cache *cache, png_structp png, png_infop info)
       
   339 {
       
   340     // write out raw image data a row at a time
       
   341     for (size_t row = 0; row < cache->header->height; row++) {
       
   342         // read row data, non-interlaced
       
   343         png_read_row(png, cache->data + row * cache->header->row_bytes, NULL);
       
   344     }
       
   345 
       
   346     return 0;
       
   347 }
       
   348 
       
   349 static int decode_png_sparse (struct pt_cache *cache, png_structp png, png_infop info)
       
   350 {
       
   351     // one row of pixel data
       
   352     uint8_t *row_buf;
       
   353 
       
   354     // alloc
       
   355     if ((row_buf = malloc(cache->header->row_bytes)) == NULL)
       
   356         RETURN_ERROR(PT_ERR_MEM);
       
   357 
       
   358     // decode each row at a time
       
   359     for (size_t row = 0; row < cache->header->height; row++) {
       
   360         // read row data, non-interlaced
       
   361         png_read_row(png, row_buf, NULL);
       
   362         
       
   363         // skip background-colored regions to keep the cache file sparse
       
   364         // ...in blocks of PT_CACHE_BLOCK_SIZE bytes
       
   365         for (size_t col_base = 0; col_base < cache->header->width; ){
       
   366             // size of this block in bytes
       
   367             size_t block_size = min(PT_CACHE_BLOCK_SIZE * cache->header->col_bytes, cache->header->row_bytes - col_base);
       
   368 
       
   369             // ...each pixel
       
   370             for (
       
   371                     size_t col = col_base;
       
   372 
       
   373                     // BLOCK_SIZE * col_bytes wide, don't go over the edge
       
   374                     col < col_base + block_size; 
       
   375 
       
   376                     col += cache->header->col_bytes
       
   377             ) {
       
   378                 // test this pixel
       
   379                 if (bcmp(row_buf + col, cache->header->params.background_color, cache->header->col_bytes)) {
       
   380                     // differs
       
   381                     memcpy(
       
   382                             cache->data + row * cache->header->row_bytes + col_base, 
       
   383                             row_buf + col_base,
       
   384                             block_size
       
   385                     );
       
   386                     
       
   387                     // skip to next block
       
   388                     break;
       
   389                 }
       
   390             }
       
   391 
       
   392             // skip this block
       
   393             continue;
       
   394         }
       
   395     }
       
   396 
       
   397     return 0;
       
   398 }
       
   399 
       
   400 int pt_cache_update_png (struct pt_cache *cache, png_structp png, png_infop info, const struct pt_image_params *params)
   334 {
   401 {
   335     struct pt_cache_header header;
   402     struct pt_cache_header header;
   336     int err;
   403     int err;
   337     
   404     
   338     // XXX: check cache_mode
   405     // XXX: check cache_mode
   381         memcpy(&header.palette, palette, num_palette * sizeof(*palette));
   448         memcpy(&header.palette, palette, num_palette * sizeof(*palette));
   382         
   449         
   383         log_debug("num_palette=%u", num_palette);
   450         log_debug("num_palette=%u", num_palette);
   384     }
   451     }
   385 
   452 
       
   453     // any params
       
   454     if (params)
       
   455         header.params = *params;
       
   456 
   386     // create .tmp and write out header
   457     // create .tmp and write out header
   387     if ((err = pt_cache_create(cache, &header)))
   458     if ((err = pt_cache_create(cache, &header)))
   388         return err;
   459         return err;
   389 
   460     
   390 
   461     // decode
   391     // write out raw image data a row at a time
   462     if ((err = decode_png_sparse(cache, png, info)))
   392     for (size_t row = 0; row < header.height; row++) {
   463         return err;
   393         // read row data, non-interlaced
       
   394         png_read_row(png, cache->data + row * header.row_bytes, NULL);
       
   395     }
       
   396 
       
   397 
   464 
   398     // move from .tmp to .cache
   465     // move from .tmp to .cache
   399     if ((err = pt_cache_create_done(cache)))
   466     if ((err = pt_cache_create_done(cache)))
   400         // XXX: pt_cache_abort?
   467         // XXX: pt_cache_abort?
   401         return err;
   468         return err;