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