반응형

파이게임에 간단한 카메라를 만들어 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import pygame
 
pygame.init()
pygame.display.set_caption("Pygame Simple Camera")
screen = pygame.display.set_mode((640480), flags=pygame.RESIZABLE, vsync=1)
clock = pygame.time.Clock()
 
class Camera():
    def __init__(self):
        self.offset = pygame.math.Vector2(00)
        self.speed = 4
        
camera = Camera()
 
def LoadImage(path, scale=None, colorkey=None):
    image = pygame.image.load(path).convert()
 
    if scale is not None:
        image = pygame.transform.scale(image, (image.get_width()*scale, image.get_height()*scale))
 
    if colorkey is not None:
        if colorkey == -1:
            colorkey = image.get_at((00))
        image.set_colorkey(colorkey)
 
    return image
 
class Sprite(pygame.sprite.Sprite):
    def __init__(self, spriteName, position, frames):
        pygame.sprite.Sprite.__init__(self)
 
        self.elapsedTime = 0
        self.limitTime = 1000/frames
        # 1초에 한 사이클. 스프라이트가 8프레임이라면 frames에 8을 대입한다.
        
        self.direction = 1
        self.speed = 4
        self.index = 0
        self.images = [ LoadImage(spriteName, 3-1) ]
        self.image = self.images[self.index]
        self.rect = self.image.get_rect(center=position)
 
    def flip_image(self):
        self.images = [pygame.transform.flip(image, TrueFalsefor image in self.images]
        self.image = self.images[self.index]
 
    def update(self):
        if (camera.offset.x != 0 or camera.offset.y != 0):
                self.rect.move_ip(camera.offset.x, camera.offset.y)
        
        # 1초에 frame번 image 업데이트.
        # self.elapsedTime += clock.get_time()
        # if self.elapsedTime < self.limitTime:
        #     pass
        # else:
        #     self.elapsedTime = 0
        #     self.index += 1
        #     if self.index >= len(self.images):
        #         self.index = 0
        #     self.image = self.images[self.index]
            
def main():
    player = Sprite("character.bmp", (screen.get_width()/2, screen.get_height()/2), 1)
    shop = Sprite("shop.bmp", (screen.get_width()/2, screen.get_height()/2), 1)
    all_sprites = pygame.sprite.Group()
    all_sprites.add(shop)
    all_sprites.add(player)
    
    running = True
    
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                running = False
 
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            if player.direction > 0:
                player.flip_image()
                player.direction = -1
            player.rect.move_ip(-player.speed, 0)            
            
        if keys[pygame.K_RIGHT]:
            if player.direction < 0:
                player.flip_image()
                player.direction = 1
            player.rect.move_ip(player.speed, 0)
        
        if keys[pygame.K_UP]:
            if player.direction < 0:
                player.flip_image()
                player.direction = 1
            player.rect.move_ip(0-player.speed)
        
        if keys[pygame.K_DOWN]:
            if player.direction < 0:
                player.flip_image()
                player.direction = 1
            player.rect.move_ip(0, player.speed)
        
        # 카메라 이동
        if keys[pygame.K_a]:
            camera.offset.x = camera.speed
        if keys[pygame.K_d]:
            camera.offset.x = -camera.speed
        if keys[pygame.K_w]:
            camera.offset.y = camera.speed
        if keys[pygame.K_s]:
            camera.offset.y = -camera.speed
 
        all_sprites.update()
        
        # 스프라이트 업데이트 후 카메라 오프셋 초기화
        camera.offset.x = camera.offset.y = 0        
        
        screen.fill("black")        
        all_sprites.draw(screen)
        pygame.display.flip()
 
        clock.tick(60)
 
    pygame.quit()
 
if __name__ == '__main__':
  main()
 

 

코드를 입력하고 실행한다. set_mode()에 vsync 파라미터를 1로 설정하지 않으면 스프라이트가 움직일때 screen tearing 현상이 일어날 수 있다.

pygame.display.set_mode(..., vsync=1)

 

방향키로 캐릭터를, wasd로 카메라를 움직인다.

 

※ 참고

Cameras in Pygame

 

반응형
Posted by J-sean
:
반응형

SDL에 2D 카메라를 만들어 보자.

 

character.bmp
0.00MB
shop.bmp
0.03MB

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include "SDL.h"
 
class Camera {
public:
    int m_width;
    int m_height;
    int m_cameraBorder;
    int m_target_width;
    int m_target_height;
    float m_x, m_y;
    SDL_Texture* m_targetTexture;
public:
    Camera(SDL_Renderer* renderer, int width, int height, int border, SDL_BlendMode mode) {
        m_width = width;
        m_height = height;
        m_cameraBorder = border;
        m_target_width = width + border * 2;
        m_target_height = height + border * 2;
        m_x = 0;
        m_y = 0;
        m_targetTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET,
            m_target_width, m_target_height);
        SDL_SetTextureBlendMode(m_targetTexture, mode);
    }
    void Draw(SDL_Renderer* renderer, int windowHeight) {
        float pixel_h = (float)windowHeight / m_height;
        float correction_x = (int)m_x - m_x;
        float correction_y = (int)m_y - m_y;
        SDL_Rect dst = { (int)(correction_x * pixel_h - pixel_h * m_cameraBorder),
            (int)(correction_y * pixel_h - pixel_h * m_cameraBorder),
            (int)(m_target_width * pixel_h),
            (int)(m_target_height * pixel_h) };
        SDL_RenderCopy(renderer, m_targetTexture, NULL&dst);
    }
    void Update(int xDirection, int yDirection) {
        m_x += 0.5f * xDirection;
        m_y += 0.5f * yDirection;
    }
    void CameraReset(SDL_Renderer* renderer, int width, int height, int border, SDL_BlendMode mode) {
        m_width = width;
        m_height = height;
        m_cameraBorder = border;
        m_target_width = width + border * 2;
        m_target_height = height + border * 2;
        SDL_DestroyTexture(m_targetTexture);
        m_targetTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET,
            m_target_width, m_target_height);
        SDL_SetTextureBlendMode(m_targetTexture, mode);
    }
    ~Camera() {
        SDL_DestroyTexture(m_targetTexture);
    }
};
 
class Sprite {
public:
    int width;
    int height;
    float m_destX, m_destY;
    SDL_Surface* surface;
    SDL_Texture* texture;
public:
    Sprite(SDL_Renderer* renderer, const char* filename) {
        surface = SDL_LoadBMP(filename);
        width = surface->w;
        height = surface->h;
        m_destX = 0;
        m_destY = 0;
        texture = SDL_CreateTextureFromSurface(renderer, surface);
        SDL_FreeSurface(surface);
    }
    void DrawSprite(SDL_Renderer* renderer, Camera* camera, int x, int y) {
        SDL_Rect destRect = { (int)(m_destX - camera->m_x) + camera->m_cameraBorder + x,
                (int)(m_destY - camera->m_y) + camera->m_cameraBorder + y,
                width, height };
 
        SDL_RenderCopy(renderer, texture, NULL&destRect);
    }
    ~Sprite() {
        SDL_DestroyTexture(texture);
    }
};
 
int main(int argc, char** argv) {
    const int Window_Width = 640;
    const int Window_Height = 480;
 
    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
    SDL_Window* window = SDL_CreateWindow("SDL Simple Camera", SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED, Window_Width, Window_Height, SDL_WINDOW_RESIZABLE);
    SDL_assert(window);
 
    SDL_SetHint(SDL_HINT_RENDER_BATCHING, "1");
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED |
        SDL_RENDERER_PRESENTVSYNC);
    SDL_assert(renderer);
 
    // Init
    Camera camera = Camera(renderer, 1601201, SDL_BLENDMODE_BLEND);
    SDL_assert(camera.m_targetTexture);
    Sprite shopSprite = Sprite(renderer, "shop.bmp");
    Sprite characterSprite = Sprite(renderer, "character.bmp");
 
    int xDirection = 0;
    int yDirection = 0;
 
    SDL_Event event;
    bool quit = false;
 
    while (!quit) {
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
            case SDL_QUIT:
                quit = true;
                break;
            case SDL_KEYDOWN:
                if (event.key.keysym.sym == SDLK_ESCAPE)
                    quit = true;
                if (event.key.keysym.sym == SDLK_LEFT)
                    xDirection = -1;
                if (event.key.keysym.sym == SDLK_RIGHT)
                    xDirection = 1;
                if (event.key.keysym.sym == SDLK_UP)
                    yDirection = -1;
                if (event.key.keysym.sym == SDLK_DOWN)
                    yDirection = 1;
                if (event.key.keysym.sym == SDLK_r)
                    camera.CameraReset(renderer, 1601201, SDL_BLENDMODE_BLEND);
                if (event.key.keysym.sym == SDLK_e)
                    camera.CameraReset(renderer, 6404801, SDL_BLENDMODE_BLEND);
                break;
 
            default:
                xDirection = 0;
                yDirection = 0;
                break;
            }
        }
        camera.Update(xDirection, yDirection);
 
        // Camera target
        SDL_SetRenderTarget(renderer, camera.m_targetTexture);
        SDL_SetRenderDrawColor(renderer, 0000xFF);
        SDL_RenderClear(renderer);
 
        // Draw Sprite
        shopSprite.DrawSprite(renderer, &camera, 00);
        characterSprite.DrawSprite(renderer, &camera, 11666);
 
        // Screen target
        SDL_SetRenderTarget(renderer, NULL);
        SDL_SetRenderDrawColor(renderer, 0x000xFF0x000xFF);
        SDL_RenderClear(renderer);
 
        camera.Draw(renderer, Window_Height);
 
        SDL_RenderPresent(renderer);
    }
 
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
 
    return 0;
}
 

 

코드를 입력하고 빌드한다.

 

실행하면 shop과 character 스프라이트가 표시된다.

 

r, e 키로 해상도를 바꿀 수 있다.

 

방향키로 카메라를 움직일 수 있다.

 

 

※ 참고

Pixel perfect camera in SDL2

 

반응형
Posted by J-sean
:
반응형

특정 조건에서 카메라를 흔들어 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class CameraShake : MonoBehaviour
{
    public float shakeTime = 1.0f;
    public float shakeSpeed = 2.0f;
    public float shakeAmount = 1.0f;
 
    private Transform cam;
 
    // Start is called before the first frame update
    void Start()
    {
        cam = GameObject.FindGameObjectWithTag("MainCamera").transform;
    }
 
    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.S))
        {
            StartCoroutine(Shake());
        }
    }
 
    IEnumerator Shake()
    {
        Vector3 originPosition = cam.localPosition;
        float elapsedTime = 0.0f;
 
        while (elapsedTime < shakeTime)
        {
            Vector3 randomPoint = originPosition + Random.insideUnitSphere * shakeAmount;
            cam.localPosition = Vector3.Lerp(cam.localPosition, randomPoint, Time.deltaTime * shakeSpeed);
 
            yield return null;
 
            elapsedTime += Time.deltaTime;
        }
 
        cam.localPosition = originPosition;
    }
}
 

 

'S'키를 누르면 카메라가 진동한다.

 

스크립트를 Cube 오브젝트에 추가하고 'S'키를 누르면 카메라가 진동한다.

 

반응형
Posted by J-sean
:
반응형

라즈베리 파이 카메라를 사용해 보자.


중국에서 구매한 라즈베리 파이용 카메라가 1주일만에 배송 되었다. 라즈베리 파이에서 판매하는 정품 카메라가 아닌 5MP 저가 호환 카메라이다. 약 3만원에 판매되는 8MP 정품 카메라보다 성능은 떨어지지만 가격이 1/10이다.


뒷면


HDMI Port와 Audio Jack 사이에 CSI Camera Port가 있다.


보호 테이프를 제거하고 latch를 들어 올린 다음 케이블을 삽입하고 고정한다.



라즈베리 파이를 부팅하고 Raspberry Pi Configuration에서 Camera - Enable을 선택한다. 재부팅 한다.


파이썬 Picamera 모듈을 사용해 보자. (Picamera 모듈은 기본 설치되어 있다)


파이썬 코드를 실행하면 라즈베리 파이에 연결한 카메라 LED에 불이 들어오고 preview 화면이 30초동안 표시된다.


반응형
Posted by J-sean
:
반응형

ESP32-CAM에는 프로그래머 칩이 없기 때문에 보통 USB to UART Converter를 이용해 프로그래밍 한다. 하지만 아두이노 보드가 있다면 Converter 없이 ESP32-CAM에 프로그래밍 할 수 있다.


2020/11/15 - [Raspberry Pi & Arduino] - NodeMCU(ESP-12E/ESP8266) LED Control Server Programming


USB to UART Converter


eBay에 주문 후 약 한 달 반이 걸려 도착한 ESP32-CAM. 카메라와 함께 작은 정전기방지 비닐에 포장되어 도착했다.


ESP32-CAM 보드



뒷면




Flat Flexible Cable에 8225N V2.0 171026라고 적힌 카메라



뒷면


누군지 기억도 안나는 사람의 명함과 함께 크기 비교


카메라를 연결 하기 위해 저 검은 latch를 들어 올려 열어야 한다.


이렇게.



카메라 케이블을 삽입하고 닫아 준다.


아두이노와 ESP32-CAM을 케이블로 연결한다. 내 가짜 아두이노... ㅠㅠ



Arduino 5V to ESP32-CAM 5V

Arduino GND to ESP32-CAM GND

Arduino RX to ESP32-CAM U0R

Arduino TX to ESP32-CAM U0T

Arduino RESET to Arduino GND

ESP32-CAM IO0 to ESP32-CAM GND


Arduino를 실행하고 File - Preferences 클릭.



Additional Boards Manager URLs에 아래 주소를 입력하고 OK클릭

https://dl.espressif.com/dl/package_esp32_index.json


Tools - Board: "Arduino Uno" - Boards Manager... 클릭


'esp32'를 검색하고 Install 클릭


Board Manager에서 esp32 설치가 완료 되면 위와 같이 설정을 바꿔준다.


Board: ESP32 Wrover Module"

Upload Speed: "115200"

Flash Frequency: "40MHz"

Flash Mode: "QIO"

Partition Scheme: "Huge APP (3MB No OTA/1MB SPIFFS)"

Core Debug Level: "None"

Port: "COM4"(아두이노가 연결된 포트)

Programmer: "AVR ISP"



File - Examples - ESP32 - Camera - CameraWebServer를 클릭 하면 카메라 웹 서버 코드가 로드 된다.


1
2
3
4
5
6
7
8
9
10
11
// Select camera model
#define CAMERA_MODEL_WROVER_KIT
//#define CAMERA_MODEL_ESP_EYE
//#define CAMERA_MODEL_M5STACK_PSRAM
//#define CAMERA_MODEL_M5STACK_WIDE
//#define CAMERA_MODEL_AI_THINKER
 
#include "camera_pins.h"
 
const char* ssid = "*********";
const char* password = "*********";


카메라 웹 서버 코드의 일부


1
2
3
4
5
6
7
8
9
10
11
// Select camera model
//#define CAMERA_MODEL_WROVER_KIT
//#define CAMERA_MODEL_ESP_EYE
//#define CAMERA_MODEL_M5STACK_PSRAM
//#define CAMERA_MODEL_M5STACK_WIDE
#define CAMERA_MODEL_AI_THINKER
 
#include "camera_pins.h"
 
const char* ssid = "my_ssid";
const char* password = "my_password";


대부분 AI_THINKER 카메라를 사용 하므로 #define CAMERA_MODEL_WROVER_KIT은 주석 처리하고 #define CAMERA_MODEL_AI_THINKER을 주석 해제 한다. ssid와 password 부분은 자신의 인터넷 ssid와 password에 맞게 수정한다.


소스를 컴파일하고 ESP32-CAM에 업로드 한다.



업로드가 완료 되면 ESP32-CAM IO0 와 ESP32-CAM GND를 연결한 케이블을 제거 한다.


Tools - Serial Monitor 클릭


Baud Rate을 115200으로 맞춘다.


ESP32-CAM 뒷면의 RST 버튼을 눌러 준다.


RST 버튼을 누르면 잠시 후 Serial Monitor 마지막 줄에 카메라 웹 서버의 주소가 표시 된다.



인터넷 브라우저로 카메라 웹 서버에 접속하면 위와 같은 화면이 나온다. Start Stream 버튼을 클릭 한다.


카메라에 찍히는 영상이 바로 스트리밍 된다. Resolution, Quality, Brightness, Contrast, H-Mirror, V-Flip, Face Detection등의 설정을 변경 할 수 있다.


Serial Monitor에는 스트리밍 상황이 표시 된다.


영상 스트리밍만 확인 하고 싶다면 아래와 같은 형식으로 접속 한다.

http://웹서버주소:81/stream

http://192.168.0.42:81/stream



ESP32-CAM에 프로그램 업로드가 완료되면 5V 전원만 있어도 동작한다. 5V 배터리나 건전지를 사용해도 되고 USB 케이블에서 5V를 받아와도 된다. 컴퓨터 USB 케이블은 5V를 사용한다.


빨간색: 5V

검정색: GND


빨간색 선은 5V에 연결하고 검정색 선은 GND에 연결한다.


ESP32-CAM이 연결된 USB 케이블을 컴퓨터에 연결하면 잘 작동 한다.


반응형
Posted by J-sean
:
반응형

Explains how to take a photo and save the full-size photo in an easy way.


기기의 카메라 앱을 실행 시키고 사진을 찍어 앱 디렉토리에 저장하고 화면에 표시 한다.


<AndroidManifest.xml>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    <!-- The write permission implicitly allows reading, so if you need to write
    to the external storage then you need to request only one permission: -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 
    <uses-feature android:name="android.hardware.camera"
                  android:required="true"/>
 
    <application
        ...
        <provider
            android:authorities="com.example.myapplication.fileprovider"
            android:name="androidx.core.content.FileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths">
            </meta-data>
        </provider>
        ...
    </application>



<res/xml/file_paths.xml>

1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="my_images"
        path="Android/data/com.example.myapplication/files/Pictures"/>
</paths>



<MainActivity.java>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
public class MainActivity extends AppCompatActivity {
 
    static final int PERMISSION_REQUEST_CONTACTS = 1001;
    static final int REQUEST_TAKE_PHOTO = 2001;
 
    ImageView imageView;
    String currentPhotoPath;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        String[] permissionRequests = {
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };
 
        checkPermissions(permissionRequests);
 
        imageView = findViewById(R.id.imageView);
        Button button = findViewById(R.id.button);
 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                if (intent.resolveActivity(getPackageManager()) != null) {
                    File photoFile = null;
                    try {
                        photoFile = createImageFile();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    if (photoFile != null) {
                        Uri photoURI = FileProvider.getUriForFile(getApplicationContext(),
                                "com.example.myapplication.fileprovider", photoFile);
                        intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
                        startActivityForResult(intent, REQUEST_TAKE_PHOTO);
                    }
                }
            }
        });
    }
 
    public void checkPermissions(String[] permissionRequests) {
        final ArrayList<String> permissionRequestList = new ArrayList<String>();
 
        for (final String request : permissionRequests) {
            if (ContextCompat.checkSelfPermission(this, request) != PackageManager.PERMISSION_GRANTED) {
                if (ActivityCompat.shouldShowRequestPermissionRationale(this, request)) {   // Redundant in this case
                    permissionRequestList.add(request);
                } else {
                    permissionRequestList.add(request);
                }
            }
        }
 
        if (!permissionRequestList.isEmpty()) {
            final String[] results = new String[permissionRequestList.size()];
            permissionRequestList.toArray(results);
 
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("info");
 
            String msg = "This app won't work properly unless you grant below permissions.";
            for (String str : results)
                msg += ("\n- "+ str);
 
            builder.setMessage(msg);
            builder.setIcon(android.R.drawable.ic_dialog_info);
 
            builder.setNeutralButton("OK"new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    ActivityCompat.requestPermissions(MainActivity.this, results, PERMISSION_REQUEST_CONTACTS);
                }
            });
 
            AlertDialog dialog = builder.create();
            dialog.show();
        }
    }
 
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_CONTACTS: {
                for (int i = 0; i < grantResults.length; i++) {
                    if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                        Toast.makeText(this, permissions[i] + " permission granted.", Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(this, permissions[i] + " permission denied.", Toast.LENGTH_SHORT).show();
                    }
                }
            }
        }
    }
 
    private File createImageFile() throws IOException {
        String timeStamp = new SimpleDateFormat("yyyMMdd_HHmmss").format(new Date());
        String imageFileName = "IMAGE_" + timeStamp + "_";
        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        // If you saved your photo to the directory provided by getExternalFilesDir(),
        // the media scanner cannot access the files because they are private to your app.
        File image = File.createTempFile(imageFileName, ".jpg", storageDir);
        currentPhotoPath = image.getAbsolutePath();
 
        return image;
    }
 
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
 
        if (requestCode == REQUEST_TAKE_PHOTO && resultCode == RESULT_OK) {
            Bitmap originalBitmap = BitmapFactory.decodeFile(currentPhotoPath);
 
            int scaleFactor = Math.max(originalBitmap.getWidth()/imageView.getWidth(), originalBitmap.getHeight()/imageView.getHeight());
            if (scaleFactor < 1)
                scaleFactor = 1;
            Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalBitmap, originalBitmap.getWidth()/scaleFactor,
                    originalBitmap.getHeight()/scaleFactor, true);
 
            Matrix m = new Matrix();
            m.postRotate(90);
            Bitmap rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 00, scaledBitmap.getWidth(), scaledBitmap.getHeight(), m, true);
 
            imageView.setImageBitmap(rotatedBitmap);
        }
    }
}




Run the app and click CAMERA button.


Take a picture.


The displayed picture is rotated 90 degrees in AVD but is upright in the actual device.


Actual device.


※ Reference:

Android Developers


반응형
Posted by J-sean
:
반응형

Explains how to take a photo and get the thumbnail of it in an easy way.

기기의 카메라 앱을 실행 시키고 사진을 찍어 썸네일을 가져 온다.


<AndroidManifest.xml>

1
    <uses-feature android:name="android.hardware.camera" android:required="true"/>



<MainActivity.java>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class MainActivity extends AppCompatActivity {
 
    static final int REQUEST_IMAGE_CAPTURE = 1001;
 
    ImageView imageView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        imageView = findViewById(R.id.imageView);
        Button button = findViewById(R.id.button);
 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                if (intent.resolveActivity(getPackageManager()) != null) {
                    startActivityForResult(intent, REQUEST_IMAGE_CAPTURE);
                }
            }
        });
    }
 
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            Bundle extras = data.getExtras();
            Bitmap bitmap = (Bitmap)extras.get("data");
            imageView.setImageBitmap(bitmap);
        }
    }
}




Run the app and click CAMERA button.


Take a picture.


Get the thumbnail.


반응형
Posted by J-sean
: