Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/FreeImage/PSDParser.cpp  view on Meta::CPAN

				FreeImage_Unload(bitmap);
				SAFE_DELETE_ARRAY(line_start);
				throw std::bad_alloc();
			}	
			
			io->read_proc(rleLineSizeList, 2, nChannels * nHeight, handle);
			
			WORD largestRLELine = 0;
			for(unsigned ch = 0; ch < nChannels; ++ch) {
				for(unsigned h = 0; h < nHeight; ++h) {
					const unsigned index = ch * nHeight + h;

#ifndef FREEIMAGE_BIGENDIAN 
					SwapShort(&rleLineSizeList[index]);
#endif
					if(largestRLELine < rleLineSizeList[index]) {
						largestRLELine = rleLineSizeList[index];
					}
				}
			}

			BYTE* rle_line_start = new (std::nothrow) BYTE[largestRLELine];
			if(!rle_line_start) {
				FreeImage_Unload(bitmap);
				SAFE_DELETE_ARRAY(line_start);
				SAFE_DELETE_ARRAY(rleLineSizeList);
				throw std::bad_alloc();
			}
			
			// Read the RLE data (assume 8-bit)
			
			const BYTE* const line_end = line_start + lineSize;

			for (unsigned ch = 0; ch < nChannels; ch++) {
				const unsigned channelOffset = ch * bytes;
				
				BYTE* dst_line_start = dst_first_line;
				for(unsigned h = 0; h < nHeight; ++h, dst_line_start -= dstLineSize) {//<*** flipped
					const unsigned index = ch * nHeight + h;
					
					// - read and uncompress line -
					
					const WORD rleLineSize = rleLineSizeList[index];
					
					io->read_proc(rle_line_start, rleLineSize, 1, handle);
					
					for (BYTE* rle_line = rle_line_start, *line = line_start; 
						rle_line < rle_line_start + rleLineSize, line < line_end;) {

						int len = *rle_line++;
						
						// NOTE len is signed byte in PackBits RLE
						
						if ( len < 128 ) { //<- MSB is not set
							// uncompressed packet
							
							// (len + 1) bytes of data are copied
							
							++len;
							
							// assert we don't write beyound eol
							memcpy(line, rle_line, line + len > line_end ? line_end - line : len);
							line += len;
							rle_line += len;
						}
						else if ( len > 128 ) { //< MSB is set
						
							// RLE compressed packet
							
							// One byte of data is repeated (–len + 1) times
							
							len ^= 0xFF; // same as (-len + 1) & 0xFF 
							len += 2;    //

							// assert we don't write beyound eol
							memset(line, *rle_line++, line + len > line_end ? line_end - line : len);							
							line += len;

						}
						else if ( 128 == len ) {
							// Do nothing
						}
					}//< rle_line
					
					// - write line to destination -
					
					if(ch >= dstChannels) {
						// @todo write to extra channels
						break; 
					}
						
					// byte by byte copy a single channel to pixel
					for (BYTE *line = line_start, *dst_line = dst_line_start; line < line_start + lineSize; 
						line += bytes, dst_line += dstBpp) {

#ifdef FREEIMAGE_BIGENDIAN
							memcpy(dst_line + channelOffset, line, bytes);
#else
							// reverse copy bytes
							for (unsigned b = 0; b < bytes; ++b) {
								dst_line[channelOffset + b] = line[(bytes-1) - b];							
							}
#endif // FREEIMAGE_BIGENDIAN
					}	
				}//< h
			}//< ch
			
			SAFE_DELETE_ARRAY(line_start);
			SAFE_DELETE_ARRAY(rleLineSizeList);
			SAFE_DELETE_ARRAY(rle_line_start);
		}
		break;
		
		case 2: // ZIP without prediction, no specification
			break;
			
		case 3: // ZIP with prediction, no specification
			break;
			
		default: // Unknown format
			break;
		
	}
	
	// --- Further process the bitmap ---
	
	if((mode == PSDP_CMYK || mode == PSDP_MULTICHANNEL)) {	
		// CMYK values are "inverted", invert them back		

		if(mode == PSDP_MULTICHANNEL) {
			invertColor(bitmap);
		} else {
			FreeImage_Invert(bitmap);
		}



( run in 1.942 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )