| 409 | | |
|---|
| 410 | | /************************************************************************/ |
|---|
| 411 | | /* LoadScanline() */ |
|---|
| 412 | | /************************************************************************/ |
|---|
| 413 | | |
|---|
| 414 | | CPLErr PNGDataset::LoadScanline( int nLine ) |
|---|
| 415 | | |
|---|
| 416 | | { |
|---|
| 417 | | int i; |
|---|
| 418 | | int nPixelOffset; |
|---|
| 419 | | |
|---|
| 420 | | CPLAssert( nLine >= 0 && nLine < GetRasterYSize() ); |
|---|
| 421 | | |
|---|
| 422 | | if( nLine >= nBufferStartLine && nLine < nBufferStartLine + nBufferLines) |
|---|
| 423 | | return CE_None; |
|---|
| | 410 | /************************************************************************/ |
|---|
| | 411 | /* LoadInterlacedChunk() */ |
|---|
| | 412 | /************************************************************************/ |
|---|
| | 413 | |
|---|
| | 414 | CPLErr PNGDataset::LoadInterlacedChunk( int iLine ) |
|---|
| | 415 | |
|---|
| | 416 | { |
|---|
| | 417 | int nPixelOffset; |
|---|
| 430 | | if( setjmp( sSetJmpContext ) != 0 ) |
|---|
| 431 | | return CE_Failure; |
|---|
| 432 | | |
|---|
| 433 | | /* -------------------------------------------------------------------- */ |
|---|
| 434 | | /* If the file is interlaced, we will load the entire image */ |
|---|
| 435 | | /* into memory using the high level API. */ |
|---|
| 436 | | /* -------------------------------------------------------------------- */ |
|---|
| 437 | | if( bInterlaced ) |
|---|
| 438 | | { |
|---|
| 439 | | png_bytep *png_rows; |
|---|
| 440 | | |
|---|
| 441 | | CPLAssert( pabyBuffer == NULL ); |
|---|
| 442 | | |
|---|
| 443 | | if( nLastLineRead != -1 ) |
|---|
| 444 | | { |
|---|
| 445 | | Restart(); |
|---|
| 446 | | if( setjmp( sSetJmpContext ) != 0 ) |
|---|
| 447 | | return CE_Failure; |
|---|
| 448 | | } |
|---|
| 449 | | |
|---|
| 450 | | nBufferStartLine = 0; |
|---|
| 451 | | nBufferLines = GetRasterYSize(); |
|---|
| | 424 | /* -------------------------------------------------------------------- */ |
|---|
| | 425 | /* Was is the biggest chunk we can safely operate on? */ |
|---|
| | 426 | /* -------------------------------------------------------------------- */ |
|---|
| | 427 | #define MAX_PNG_CHUNK_BYTES 100000000 |
|---|
| | 428 | |
|---|
| | 429 | int nMaxChunkLines = |
|---|
| | 430 | MAX(1,MAX_PNG_CHUNK_BYTES / (nPixelOffset * GetRasterXSize())); |
|---|
| | 431 | png_bytep *png_rows; |
|---|
| | 432 | |
|---|
| | 433 | if( nMaxChunkLines > GetRasterYSize() ) |
|---|
| | 434 | nMaxChunkLines = GetRasterYSize(); |
|---|
| | 435 | |
|---|
| | 436 | /* -------------------------------------------------------------------- */ |
|---|
| | 437 | /* Allocate chunk buffer, if we don't already have it from a */ |
|---|
| | 438 | /* previous request. */ |
|---|
| | 439 | /* -------------------------------------------------------------------- */ |
|---|
| | 440 | nBufferLines = nMaxChunkLines; |
|---|
| | 441 | if( nMaxChunkLines + iLine > GetRasterYSize() ) |
|---|
| | 442 | nBufferStartLine = GetRasterYSize() - nMaxChunkLines; |
|---|
| | 443 | else |
|---|
| | 444 | nBufferStartLine = iLine; |
|---|
| | 445 | |
|---|
| | 446 | if( pabyBuffer == NULL ) |
|---|
| | 447 | { |
|---|
| 463 | | |
|---|
| 464 | | png_rows = (png_bytep*)CPLMalloc(sizeof(png_bytep) * GetRasterYSize()); |
|---|
| 465 | | for( i = 0; i < GetRasterYSize(); i++ ) |
|---|
| 466 | | png_rows[i] = pabyBuffer + i * nPixelOffset * GetRasterXSize(); |
|---|
| 467 | | |
|---|
| 468 | | png_read_image( hPNG, png_rows ); |
|---|
| 469 | | |
|---|
| 470 | | CPLFree( png_rows ); |
|---|
| 471 | | |
|---|
| 472 | | nLastLineRead = GetRasterYSize() - 1; |
|---|
| 473 | | |
|---|
| | 459 | #ifdef notdef |
|---|
| | 460 | if( nMaxChunkLines < GetRasterYSize() ) |
|---|
| | 461 | CPLDebug( "PNG", |
|---|
| | 462 | "Interlaced file being handled in %d line chunks.\n" |
|---|
| | 463 | "Performance is likely to be quite poor.", |
|---|
| | 464 | nMaxChunkLines ); |
|---|
| | 465 | #endif |
|---|
| | 466 | } |
|---|
| | 467 | |
|---|
| | 468 | /* -------------------------------------------------------------------- */ |
|---|
| | 469 | /* Do we need to restart reading? We do this if we aren't on */ |
|---|
| | 470 | /* the first attempt to read the image. */ |
|---|
| | 471 | /* -------------------------------------------------------------------- */ |
|---|
| | 472 | if( nLastLineRead != -1 ) |
|---|
| | 473 | { |
|---|
| | 474 | Restart(); |
|---|
| | 475 | if( setjmp( sSetJmpContext ) != 0 ) |
|---|
| | 476 | return CE_Failure; |
|---|
| | 477 | } |
|---|
| | 478 | |
|---|
| | 479 | /* -------------------------------------------------------------------- */ |
|---|
| | 480 | /* Allocate and populate rows array. We create a row for each */ |
|---|
| | 481 | /* row in the image, but use our dummy line for rows not in the */ |
|---|
| | 482 | /* target window. */ |
|---|
| | 483 | /* -------------------------------------------------------------------- */ |
|---|
| | 484 | int i; |
|---|
| | 485 | png_bytep dummy_row = (png_bytep)CPLMalloc(nPixelOffset*GetRasterXSize()); |
|---|
| | 486 | png_rows = (png_bytep*)CPLMalloc(sizeof(png_bytep) * GetRasterYSize()); |
|---|
| | 487 | |
|---|
| | 488 | for( i = 0; i < GetRasterYSize(); i++ ) |
|---|
| | 489 | { |
|---|
| | 490 | if( i >= nBufferStartLine && i < nBufferStartLine + nBufferLines ) |
|---|
| | 491 | png_rows[i] = pabyBuffer |
|---|
| | 492 | + (i-nBufferStartLine) * nPixelOffset * GetRasterXSize(); |
|---|
| | 493 | else |
|---|
| | 494 | png_rows[i] = dummy_row; |
|---|
| | 495 | } |
|---|
| | 496 | |
|---|
| | 497 | png_read_image( hPNG, png_rows ); |
|---|
| | 498 | |
|---|
| | 499 | CPLFree( png_rows ); |
|---|
| | 500 | CPLFree( dummy_row ); |
|---|
| | 501 | |
|---|
| | 502 | nLastLineRead = nBufferStartLine + nBufferLines - 1; |
|---|
| | 503 | |
|---|
| | 504 | return CE_None; |
|---|
| | 505 | } |
|---|
| | 506 | |
|---|
| | 507 | /************************************************************************/ |
|---|
| | 508 | /* LoadScanline() */ |
|---|
| | 509 | /************************************************************************/ |
|---|
| | 510 | |
|---|
| | 511 | CPLErr PNGDataset::LoadScanline( int nLine ) |
|---|
| | 512 | |
|---|
| | 513 | { |
|---|
| | 514 | int nPixelOffset; |
|---|
| | 515 | |
|---|
| | 516 | CPLAssert( nLine >= 0 && nLine < GetRasterYSize() ); |
|---|
| | 517 | |
|---|
| | 518 | if( nLine >= nBufferStartLine && nLine < nBufferStartLine + nBufferLines) |
|---|
| 475 | | } |
|---|
| | 520 | |
|---|
| | 521 | if( nBitDepth == 16 ) |
|---|
| | 522 | nPixelOffset = 2 * GetRasterCount(); |
|---|
| | 523 | else |
|---|
| | 524 | nPixelOffset = 1 * GetRasterCount(); |
|---|
| | 525 | |
|---|
| | 526 | if( setjmp( sSetJmpContext ) != 0 ) |
|---|
| | 527 | return CE_Failure; |
|---|
| | 528 | |
|---|
| | 529 | /* -------------------------------------------------------------------- */ |
|---|
| | 530 | /* If the file is interlaced, we will load the entire image */ |
|---|
| | 531 | /* into memory using the high level API. */ |
|---|
| | 532 | /* -------------------------------------------------------------------- */ |
|---|
| | 533 | if( bInterlaced ) |
|---|
| | 534 | return LoadInterlacedChunk( nLine ); |
|---|