Added transparency support in RGB565 bitmap outputs, for gif decoder.
[framework/osp/image-core.git] / src / FMedia_JpegEncoder.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file   FMedia_JpegEncoder.cpp
20  * @brief  This file contains the implementation of _JpegEncoder class.
21  */
22
23 #include <stdio.h>
24 #include <jpeglib.h>
25 #include <setjmp.h>
26 #include <FMediaImageTypes.h>
27 #include <FBaseSysLog.h>
28 #include "FMedia_JpegEncoder.h"
29
30 using namespace Tizen::Base;
31
32 namespace Tizen { namespace Media
33 {
34
35 static const int MIN_JPEG_ENC_WIDTH = 16;
36 static const int MIN_JPEG_ENC_HEIGHT = 16;
37 static const int MAX_JPEG_ENC_WIDTH = 5000;
38 static const int MAX_JPEG_ENC_HEIGHT = 5000;
39
40 static void JpegErrorExitStatic(struct jpeg_common_struct * pJpegInfo);
41
42 _JpegEncoder::_JpegEncoder(void)
43 {
44         __pixelFormat = MEDIA_PIXEL_FORMAT_NONE;
45         __quality = 90;
46         __width = 0;
47         __height = 0;
48 }
49
50 _JpegEncoder::~_JpegEncoder(void)
51 {
52
53 }
54
55 result
56 _JpegEncoder::Construct(int width, int height,
57                                                 MediaPixelFormat srcPixelFormat,
58                                                 MediaPixelFormat& reqPixelFormat,
59                                                 int quality)
60 {
61         SysTryReturnResult(NID_MEDIA, width >= MIN_JPEG_ENC_WIDTH, E_INVALID_ARG,
62                 "Width (%d) should be greater than (%d)", width, MIN_JPEG_ENC_WIDTH);
63         SysTryReturnResult(NID_MEDIA, width <= MAX_JPEG_ENC_WIDTH, E_OVERFLOW,
64                 "width (%d) should be lesser than (%d)", width, MAX_JPEG_ENC_WIDTH);
65         SysTryReturnResult(NID_MEDIA, height >= MIN_JPEG_ENC_HEIGHT, E_INVALID_ARG,
66                 "Height (%d) should be greater than (%d)", height, MIN_JPEG_ENC_HEIGHT);
67         SysTryReturnResult(NID_MEDIA, height <= MAX_JPEG_ENC_HEIGHT, E_OVERFLOW,
68                 "Height (%d) should be lesser than (%d)", height, MAX_JPEG_ENC_HEIGHT);
69         SysTryReturnResult(NID_MEDIA, quality > 0, E_INVALID_ARG,
70                 "Quality (%d) should be greater than zero.", quality);
71         SysTryReturnResult(NID_MEDIA, quality <= 100, E_INVALID_ARG,
72                 "Quality (%d) quality should be lesser than 100.", quality);
73
74         // TODO: add handling of srcPixelFormat
75         __width = width;
76         __height = height;
77         __pixelFormat = MEDIA_PIXEL_FORMAT_RGB888;
78         reqPixelFormat = MEDIA_PIXEL_FORMAT_RGB888;
79         __quality = quality;
80
81         return E_SUCCESS;
82 }
83
84
85 Tizen::Base::ByteBuffer*
86 _JpegEncoder::EncodeN(const byte* srcBuf, int srcLength)
87 {
88         result r = E_SUCCESS;
89
90         struct jpeg_compress_struct cinfo;
91         struct jpeg_error_mgr jerr;
92         JSAMPROW ppRows[2] = {0,0};        // pointer to a single row
93         int rowStride = 0;
94         unsigned long outSize = 0;
95         //byte* pPos = null;
96         byte* pOutBuf = null;
97         jmp_buf errJump;
98         ByteBuffer* pRetBuf = null;
99
100         //SysTryReturn(NID_MEDIA, srcLength <= JPG_MAX_SIZE, E_OVERFLOW, E_OVERFLOW,
101         //  "Buffer size is overflowed : size %d byte", srcLength);
102         //SysTryReturn(NID_MEDIA, ((dim.width <= JPG_MAX_WIDTH) &&
103         //  (dim.height <= JPG_MAX_HEIGTH)), E_OVERFLOW, E_OVERFLOW,
104         //  "Dimensions too large : width %d / height :%d", dim.width, dim.height);
105
106         // Initialize
107         cinfo.err = jpeg_std_error(&jerr);
108         jerr.error_exit = JpegErrorExitStatic;
109         cinfo.client_data = &errJump;
110
111         SysTryCatch(NID_MEDIA, !setjmp(errJump), r = E_INVALID_DATA, E_INVALID_DATA,
112                 "[E_INVALID_DATA] error jump");
113
114         jpeg_create_compress(&cinfo);
115
116         // Set output to dest buf
117         jpeg_mem_dest(&cinfo, &pOutBuf, &outSize);
118
119         cinfo.image_width = __width;
120         cinfo.image_height = __height;
121         cinfo.input_components = 3; // TODO: GetBytesPerPixel(pixelFormat);
122         cinfo.in_color_space = JCS_RGB; // colorspace of input image // or JCS_YCbCr
123
124         jpeg_set_defaults(&cinfo);
125         // Make optional parameter settings here
126         jpeg_set_quality(&cinfo, __quality, false);
127
128         jpeg_start_compress(&cinfo, TRUE);
129
130         rowStride = __width * 3; // JSAMPLEs per row in image_buffer   // 4, if use JCS_YCbCr
131
132         // position = (byte*) srcBuf;
133         while (cinfo.next_scanline < cinfo.image_height)
134         {
135                 ppRows[0] = (byte*)srcBuf + cinfo.next_scanline * rowStride;
136                 jpeg_write_scanlines(&cinfo, ppRows, 1);
137         }
138
139         jpeg_finish_compress(&cinfo);
140         jpeg_destroy_compress(&cinfo);
141
142         SysTryCatch(NID_MEDIA, outSize > 0, r = E_SYSTEM, E_SYSTEM,
143                 "[E_SYSTEM] jpeg lib returned outSize (%d)", outSize);
144
145         SysTryCatch(NID_MEDIA, pOutBuf != null, r = E_SYSTEM, E_SYSTEM,
146                 "[E_SYSTEM] outbuf is null.");
147
148         //dstLength = (int) outSize;
149         //dstBuf = new (std::nothrow) byte[outSize];
150         pRetBuf = new (std::nothrow) ByteBuffer();
151         SysTryCatch(NID_MEDIA, pRetBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
152                 "[E_OUT_OF_MEMORY] Could not create new ByteBuffer.");
153
154         r = pRetBuf->Construct(outSize);
155         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagated. Failed to construct ByteBuffer of size %d",
156                 GetErrorMessage(r), outSize);
157         r = pRetBuf->SetArray(pOutBuf, 0, outSize);
158         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagated. Failed to SetArray for buffer %x, size %d",
159                 GetErrorMessage(r), pOutBuf, outSize);
160         pRetBuf->Flip();
161
162         free(pOutBuf);
163
164         return pRetBuf;
165
166 CATCH:
167         if (pOutBuf)
168         {
169                 free(pOutBuf);
170         }
171         if (pRetBuf)
172         {
173                 delete pRetBuf;
174         }
175         return null;
176 }
177
178 static void
179 JpegErrorExitStatic(struct jpeg_common_struct * pJpegInfo)
180 {
181         if (pJpegInfo)
182         {
183                 jmp_buf *pBuf = (jmp_buf*)pJpegInfo->client_data;
184                 if (*pBuf)
185                 {
186                         longjmp(*pBuf, 1);
187                 }
188         }
189 }
190
191 result
192 _JpegEncoder::SetValue(const Tizen::Base::String& key, Tizen::Base::Object &value)
193 {
194         return E_UNSUPPORTED_OPERATION;
195 }
196
197 }} // Tizen::Media