github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/image/rawp/librawp/src/rawp.cc (about)

     1  // Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  #include "rawp.h"
     6  #include "rawp_crc32.h"
     7  #include "rawp-snappy.h"
     8  
     9  #include <stdlib.h>
    10  #include <string.h>
    11  
    12  static bool rawpIsValidChannels(uint8_t channels) {
    13  	return channels == 1 || channels == 3 || channels == 4;
    14  }
    15  
    16  static bool rawpIsValidDepth(uint8_t depth) {
    17  	return depth == 8 || depth == 16 || depth == 32 || depth == 64;
    18  }
    19  
    20  static bool rawpIsValidDataType(uint8_t x) {
    21  	return x == kRawPDataType_UInt || x == kRawPDataType_Int || x == kRawPDataType_Float;
    22  }
    23  
    24  static bool rawpIsValidHeader(const RawPHeader* hdr) {
    25  	if(hdr->Sig[0] != 'R' || hdr->Sig[1] != 'a' || hdr->Sig[2] != 'w' || hdr->Sig[3] != 'P') {
    26  		return 0;
    27  	}
    28  	if(hdr->Magic != kRawPMagic) {
    29  		return 0;
    30  	}
    31  
    32  	if(hdr->Width <= 0 || hdr->Height <= 0) {
    33  		return 0;
    34  	}
    35  	if(!rawpIsValidChannels(hdr->Channels)) {
    36  		return 0;
    37  	}
    38  	if(!rawpIsValidDepth(hdr->Depth)) {
    39  		return 0;
    40  	}
    41  	if(!rawpIsValidDataType(hdr->DataType)) {
    42  		return 0;
    43  	}
    44  
    45  	if(hdr->UseSnappy != 0 && hdr->UseSnappy != 1) {
    46  		return 0;
    47  	}
    48  	if(hdr->DataSize <= 0) {
    49  		return 0;
    50  	}
    51  
    52  	// check type more ...
    53  	if(hdr->Depth == 8 || hdr->Depth == 16) {
    54  		if(hdr->DataType != kRawPDataType_UInt && hdr->DataType != kRawPDataType_Int) {
    55  			return 0;
    56  		}
    57  	}
    58  
    59  	// check data size more ...
    60  	if(hdr->UseSnappy) {
    61  		size_t result;
    62  		if(!rawp::snappy::GetUncompressedLength((const char*)hdr->Data, hdr->DataSize, &result)) {
    63  			return 0;
    64  		}
    65  		if(result != hdr->Width*hdr->Height*hdr->Channels*hdr->Depth/8) {
    66  			return 0;
    67  		}
    68  	} else {
    69  		if(hdr->DataSize != hdr->Width*hdr->Height*hdr->Channels*hdr->Depth/8) {
    70  			return 0;
    71  		}
    72  	}
    73  
    74  	// Avoid check crc32
    75  	return true;
    76  }
    77  
    78  static bool rwapCheckCRC32(const RawPHeader* hdr) {
    79  	return rawpHashCRC32((const char*)hdr->Data, hdr->DataSize) == hdr->DataCheckSum;
    80  }
    81  
    82  int rawpDecodeHeader(
    83  	const uint8_t* data, int data_size,
    84  	RawPHeader* hdr
    85  ) {
    86  	if(data == NULL || data_size < kRawPHeaderSize || hdr == NULL) {
    87  		return 0;
    88  	}
    89  	// reader header
    90  	memcpy(hdr, data, kRawPHeaderSize);
    91  	hdr->Data = (uint8_t*)data + kRawPHeaderSize;
    92  
    93  	// check header
    94  	if(!rawpIsValidHeader(hdr)) {
    95  		memset(hdr, 0, sizeof(*hdr));
    96  		return 0;
    97  	}
    98  	return 1;
    99  }
   100  
   101  int rawpDecode(
   102  	const uint8_t* data, int data_size,
   103  	uint8_t* output, int output_size,
   104  	RawPHeader* hdr
   105  ) {
   106  	if(data == NULL || data_size < kRawPHeaderSize) {
   107  		return 0;
   108  	}
   109  	if(output == NULL || output_size <= 0) {
   110  		return 0;
   111  	}
   112  	if(hdr == NULL) {
   113  		return 0;
   114  	}
   115  
   116  	if(!rawpDecodeHeader(data, data_size, hdr)) {
   117  		return 0;
   118  	}
   119  	if(data_size < (kRawPHeaderSize+int(hdr->DataSize))) {
   120  		return 0;
   121  	}
   122  	if(output_size < hdr->Width*hdr->Height*hdr->Channels*hdr->Depth/8) {
   123  		return 0;
   124  	}
   125  	if(!rwapCheckCRC32(hdr)) {
   126  		return 0;
   127  	}
   128  
   129  	if(hdr->UseSnappy) {
   130  		if(!rawp::snappy::RawUncompress((const char*)hdr->Data, (size_t)hdr->DataSize, (char*)output)) {
   131  			return 0;
   132  		}
   133  	} else {
   134  		memcpy(output, hdr->Data, hdr->Width*hdr->Height*hdr->Channels*hdr->Depth/8);
   135  	}
   136  	return 1;
   137  }
   138  
   139  int rawpEncodeInit(
   140  	const uint8_t* pix, int width, int height,
   141  	int channels, int depth, int data_type,
   142  	const RawPEncodeOptions* opt,
   143  	RawPEncodeContext* ctx
   144  ) {
   145  	if(pix == NULL || width <= 0 || height <= 0) {
   146  		return 0;
   147  	}
   148  	if(channels <= 0 || !rawpIsValidDepth(depth) || !rawpIsValidDataType(data_type)) {
   149  		return 0;
   150  	}
   151  	if(ctx == NULL) {
   152  		return 0;
   153  	}
   154  
   155  	if(opt != NULL) {
   156  		if(opt->UseSnappy != 0 && opt->UseSnappy != 1) {
   157  			return 0;
   158  		}
   159  	}
   160  
   161  	memset(ctx, 0, sizeof(*ctx));
   162  
   163  	ctx->Header.Sig[0] = 'R'; // RawP
   164  	ctx->Header.Sig[1] = 'a';
   165  	ctx->Header.Sig[2] = 'w';
   166  	ctx->Header.Sig[3] = 'P';
   167  	ctx->Header.Magic = kRawPMagic;
   168  	ctx->Header.Width = width;
   169  	ctx->Header.Height = height;
   170  	ctx->Header.Channels = channels;
   171  	ctx->Header.Depth = depth;
   172  	ctx->Header.DataType = data_type;
   173  	ctx->Header.UseSnappy = (opt != NULL)? opt->UseSnappy: 0;
   174  	ctx->Header.DataSize = width*height*channels*depth/8;
   175  
   176  	ctx->Pix = (uint8_t*)pix;
   177  	ctx->MaxEncodedLength = kRawPHeaderSize + (
   178  		ctx->Header.UseSnappy? rawp::snappy::MaxCompressedLength(ctx->Header.DataSize):
   179  		ctx->Header.DataSize
   180  	);
   181  
   182  	return 1;
   183  }
   184  
   185  size_t rawpEncode(
   186  	RawPEncodeContext* ctx,
   187  	uint8_t* output
   188  ) {
   189  	if(ctx == NULL || output == NULL) {
   190  		return 0;
   191  	}
   192  	RawPHeader* hdr = &(ctx->Header);
   193  
   194  	// write data
   195  	uint8_t* pData = output + kRawPHeaderSize;
   196  	if(hdr->UseSnappy) {
   197  		size_t output_length;
   198  		rawp::snappy::RawCompress(
   199  			(const char*)ctx->Pix, hdr->Width*hdr->Height*hdr->Channels*hdr->Depth/8,
   200  			(char*)pData, &output_length
   201  		);
   202  		hdr->DataSize = output_length;
   203  	} else {
   204  		ctx->Header.DataSize = hdr->Width*hdr->Height*hdr->Channels*hdr->Depth/8;
   205  		memcpy(pData, ctx->Pix, hdr->DataSize);
   206  	}
   207  
   208  	// write crc32
   209  	hdr->DataCheckSum = rawpHashCRC32((const char*)pData, hdr->DataSize);
   210  
   211  	// write header
   212  	memcpy(output, hdr, kRawPHeaderSize);
   213  
   214  	// OK
   215  	return size_t(kRawPHeaderSize+hdr->DataSize);
   216  }
   217