github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/image/jxr/jxrlib/src/jxr_encode.c (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 "jxr.h"
     6  #include "jxr_private.h"
     7  
     8  struct jxr_encoder_t {
     9  	const void*       pType;
    10  	PKFactory*        pFactory;
    11  	PKImageEncode*    pEncoder;
    12  	struct WMPStream* pStream;
    13  	CWMIStrCodecParam wmiSCP;
    14  	const char*       data;
    15  	int               dataSize;
    16  	int               stride;
    17  	int               width;
    18  	int               height;
    19  	int               channels;
    20  	int               depth;
    21  	int               quality;
    22  	jxr_data_type_t   dataType;
    23  	size_t            destSize;
    24  };
    25  
    26  static const char jxr_encoder_type[] = "jxr_encoder_t";
    27  
    28  jxr_encoder_t* jxr_encoder_new() {
    29  	jxr_encoder_t* p = (jxr_encoder_t*)calloc(1, sizeof(*p));
    30  	if(!p) return NULL;
    31  
    32  	p->pType = jxr_encoder_type;
    33  	if(Failed(PKCreateFactory(&p->pFactory, PK_SDK_VERSION))) {
    34  		jxr_encoder_delete(p);
    35  		return NULL;
    36  	}
    37  	if(Failed(PKImageEncode_Create_WMP(&p->pEncoder))) {
    38  		jxr_encoder_delete(p);
    39  		return NULL;
    40  	}
    41  	return p;
    42  }
    43  
    44  void jxr_encoder_delete(jxr_encoder_t* p) {
    45  	if(p == NULL || p->pType != jxr_encoder_type) {
    46  		fprintf(stderr, "jxr: jxr_encoder_delete, invalid jxr_decoder_t type!");
    47  		abort();
    48  	}
    49  
    50  	if(p->pEncoder != NULL) {
    51  		p->pEncoder->Release(&p->pEncoder);
    52  		p->pEncoder = NULL;
    53  	}
    54  	if(p->pStream != NULL) {
    55  		p->pStream->Close(&p->pStream);
    56  		p->pStream = NULL;
    57  	}
    58  	if(p->pFactory != NULL) {
    59  		p->pFactory->Release(&p->pFactory);
    60  		p->pFactory = NULL;
    61  	}
    62  	p->pType = NULL;
    63  }
    64  
    65  jxr_bool_t jxr_encoder_init(jxr_encoder_t* p,
    66  	const char* data, int size, int stride,
    67  	int width, int height, int channels, int depth,
    68  	int quality, jxr_data_type_t type
    69  ) {
    70  	const PKPixelFormatGUID* fmt = NULL;
    71  
    72  	if(p == NULL || p->pType != jxr_encoder_type) {
    73  		fprintf(stderr, "jxr: jxr_encoder_init, invalid jxr_decoder_t type!");
    74  		abort();
    75  	}
    76  
    77  	// lookup best match format
    78  	if(!jxr_golden_format(channels, depth, type, &fmt)) {
    79  		return jxr_false;
    80  	}
    81  	if(Failed(p->pEncoder->SetPixelFormat(p->pEncoder, *fmt))) {
    82  		return jxr_false;
    83  	}
    84  
    85  	// set image size
    86  	if(Failed(p->pEncoder->SetSize(p->pEncoder, width, height))) {
    87  		return jxr_false;
    88  	}
    89  
    90  	p->data = data;
    91  	p->dataSize = size;
    92  	p->stride = stride;
    93  
    94  	p->width = width;
    95  	p->height = height;
    96  	p->channels = channels;
    97  	p->depth = depth;
    98  	p->quality = quality;
    99  	p->dataType = type;
   100  	p->destSize = 0;
   101  
   102  	return jxr_true;
   103  }
   104  
   105  jxr_bool_t jxr_encoder_need_buffer_size(jxr_encoder_t* p, int* size) {
   106  	struct WMPStream* pNilStream = NULL;
   107  
   108  	if(p->destSize == 0) {
   109  		// create discard stream
   110  		if(Failed(CreateWS_Discard(&pNilStream))) {
   111  			return jxr_false;
   112  		}
   113  		if(Failed(p->pEncoder->Initialize(p->pEncoder, pNilStream, &p->wmiSCP, sizeof(p->wmiSCP)))) {
   114  			pNilStream->Close(&pNilStream);
   115  			return jxr_false;
   116  		}
   117  
   118  		{
   119  			// how to set quality ?
   120  		}
   121  
   122  		// try encode
   123  		if(Failed(p->pEncoder->WritePixels(p->pEncoder, p->height, (U8*)p->data, p->stride))) {
   124  			pNilStream->Close(&pNilStream);
   125  			return jxr_false;
   126  		}
   127  		if(Failed(pNilStream->GetPos(pNilStream, &p->destSize))) {
   128  			pNilStream->Close(&pNilStream);
   129  			return jxr_false;
   130  		}
   131  
   132  		pNilStream->Close(&pNilStream);
   133  	}
   134  	if(size != NULL) {
   135  		*size = p->destSize;
   136  	}
   137  	return jxr_true;
   138  }
   139  
   140  jxr_bool_t jxr_encoder_encode(jxr_encoder_t* p, char* buf, int buf_len, int* size) {
   141  	// create new stream
   142  	if(p->pStream == NULL) {
   143  		if(Failed(p->pFactory->CreateStreamFromMemory(&p->pStream, (void*)buf, buf_len))) {
   144  			return jxr_false;
   145  		}
   146  	}
   147  
   148  	// set output steam
   149  	if(Failed(p->pEncoder->Initialize(p->pEncoder, p->pStream, &p->wmiSCP, sizeof(p->wmiSCP)))) {
   150  		return jxr_false;
   151  	}
   152  
   153  	// how to set quality ?
   154  	{
   155  		//
   156  	}
   157  
   158  	// encode
   159  	if(Failed(p->pEncoder->WritePixels(p->pEncoder, p->height, (U8*)p->data, p->stride))) {
   160  		return jxr_false;
   161  	}
   162  	if(Failed(p->pStream->GetPos(p->pStream, &p->destSize))) {
   163  		return jxr_false;
   164  	}
   165  	if(size != NULL) {
   166  		*size = p->destSize;
   167  	}
   168  
   169  	return jxr_true;
   170  }